Skip to content

Commit 37f386a

Browse files
authored
refactor: reorganize contracts (#68)
1 parent 3cbe2fe commit 37f386a

18 files changed

+302
-263
lines changed

script/Zenith.s.sol

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.24;
33

4-
import {Script} from "forge-std/Script.sol";
4+
// deploy contracts
55
import {Zenith} from "../src/Zenith.sol";
6-
import {Passage, RollupPassage} from "../src/Passage.sol";
76
import {Transactor} from "../src/Transact.sol";
8-
import {HostOrders, RollupOrders} from "../src/Orders.sol";
7+
import {HostOrders, RollupOrders} from "../src/orders/Orders.sol";
8+
import {Passage} from "../src/passage/Passage.sol";
9+
import {RollupPassage} from "../src/passage/RollupPassage.sol";
10+
// utils
11+
import {Script} from "forge-std/Script.sol";
912

1013
contract ZenithScript is Script {
1114
// deploy:

src/Transact.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.24;
33

4-
import {Passage} from "./Passage.sol";
4+
import {Passage} from "./passage/Passage.sol";
55

66
/// @notice A contract deployed to Host chain that enables transactions from L1 to be sent on an L2.
77
contract Transactor {

src/UsesPermit2.sol

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.24;
3+
4+
import {IOrders} from "./orders/IOrders.sol";
5+
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";
6+
7+
abstract contract UsesPermit2 {
8+
/// @param permit - the permit2 single token transfer details. includes a `deadline` and an unordered `nonce`.
9+
/// @param signer - the signer of the permit2 info; the owner of the tokens.
10+
/// @param signature - the signature over the permit + witness.
11+
struct Permit2 {
12+
ISignatureTransfer.PermitTransferFrom permit;
13+
address owner;
14+
bytes signature;
15+
}
16+
17+
/// @param permit - the permit2 batch token transfer details. includes a `deadline` and an unordered `nonce`.
18+
/// @param signer - the signer of the permit2 info; the owner of the tokens.
19+
/// @param signature - the signature over the permit + witness.
20+
struct Permit2Batch {
21+
ISignatureTransfer.PermitBatchTransferFrom permit;
22+
address owner;
23+
bytes signature;
24+
}
25+
26+
/// @notice Struct to hold the pre-hashed witness field and the witness type string.
27+
struct Witness {
28+
bytes32 witnessHash;
29+
string witnessTypeString;
30+
}
31+
32+
/// @notice The Permit2 contract address.
33+
address immutable permit2Contract;
34+
35+
constructor(address _permit2) {
36+
permit2Contract = _permit2;
37+
}
38+
}
File renamed without changes.

src/orders/OrderDestination.sol

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.24;
3+
4+
import {OrdersPermit2} from "./OrdersPermit2.sol";
5+
import {IOrders} from "./IOrders.sol";
6+
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
7+
8+
/// @notice Contract capable of processing fulfillment of intent-based Orders.
9+
abstract contract OrderDestination is IOrders, OrdersPermit2 {
10+
/// @notice Emitted when Order Outputs are sent to their recipients.
11+
/// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
12+
event Filled(Output[] outputs);
13+
14+
/// @notice Fill any number of Order(s), by transferring their Output(s).
15+
/// @dev Filler may aggregate multiple Outputs with the same (`chainId`, `recipient`, `token`) into a single Output with the summed `amount`.
16+
/// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
17+
/// @param outputs - The Outputs to be transferred.
18+
/// @custom:emits Filled
19+
function fill(Output[] memory outputs) external payable {
20+
// transfer outputs
21+
_transferOutputs(outputs);
22+
23+
// emit
24+
emit Filled(outputs);
25+
}
26+
27+
/// @notice Fill any number of Order(s), by transferring their Output(s) via permit2 signed batch transfer.
28+
/// @dev Can only provide ERC20 tokens as Outputs.
29+
/// @dev Filler may aggregate multiple Outputs with the same (`chainId`, `recipient`, `token`) into a single Output with the summed `amount`.
30+
/// @dev the permit2 signer is the Filler providing the Outputs.
31+
/// @dev the permit2 `permitted` tokens MUST match provided Outputs.
32+
/// @dev Filler MUST submit `fill` and `intitiate` within an atomic bundle.
33+
/// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
34+
/// @param outputs - The Outputs to be transferred. signed over via permit2 witness.
35+
/// @param permit2 - the permit2 details, signer, and signature.
36+
/// @custom:emits Filled
37+
function fillPermit2(Output[] memory outputs, OrdersPermit2.Permit2Batch calldata permit2) external {
38+
// transfer all tokens to the Output recipients via permit2 (includes check on nonce & deadline)
39+
_permitWitnessTransferFrom(
40+
outputWitness(outputs), _fillTransferDetails(outputs, permit2.permit.permitted), permit2
41+
);
42+
43+
// emit
44+
emit Filled(outputs);
45+
}
46+
47+
/// @notice Transfer the Order Outputs to their recipients.
48+
function _transferOutputs(Output[] memory outputs) internal {
49+
uint256 value = msg.value;
50+
for (uint256 i; i < outputs.length; i++) {
51+
if (outputs[i].token == address(0)) {
52+
// this line should underflow if there's an attempt to spend more ETH than is attached to the transaction
53+
value -= outputs[i].amount;
54+
payable(outputs[i].recipient).transfer(outputs[i].amount);
55+
} else {
56+
IERC20(outputs[i].token).transferFrom(msg.sender, outputs[i].recipient, outputs[i].amount);
57+
}
58+
}
59+
}
60+
}

src/Orders.sol renamed to src/orders/OrderOrigin.sol

+2-64
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,10 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.24;
33

4-
import {OrdersPermit2, UsesPermit2} from "./permit2/UsesPermit2.sol";
5-
import {IOrders} from "./interfaces/IOrders.sol";
4+
import {OrdersPermit2} from "./OrdersPermit2.sol";
5+
import {IOrders} from "./IOrders.sol";
66
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
77

8-
/// @notice Contract capable of processing fulfillment of intent-based Orders.
9-
abstract contract OrderDestination is IOrders, OrdersPermit2 {
10-
/// @notice Emitted when Order Outputs are sent to their recipients.
11-
/// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
12-
event Filled(Output[] outputs);
13-
14-
/// @notice Fill any number of Order(s), by transferring their Output(s).
15-
/// @dev Filler may aggregate multiple Outputs with the same (`chainId`, `recipient`, `token`) into a single Output with the summed `amount`.
16-
/// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
17-
/// @param outputs - The Outputs to be transferred.
18-
/// @custom:emits Filled
19-
function fill(Output[] memory outputs) external payable {
20-
// transfer outputs
21-
_transferOutputs(outputs);
22-
23-
// emit
24-
emit Filled(outputs);
25-
}
26-
27-
/// @notice Fill any number of Order(s), by transferring their Output(s) via permit2 signed batch transfer.
28-
/// @dev Can only provide ERC20 tokens as Outputs.
29-
/// @dev Filler may aggregate multiple Outputs with the same (`chainId`, `recipient`, `token`) into a single Output with the summed `amount`.
30-
/// @dev the permit2 signer is the Filler providing the Outputs.
31-
/// @dev the permit2 `permitted` tokens MUST match provided Outputs.
32-
/// @dev Filler MUST submit `fill` and `intitiate` within an atomic bundle.
33-
/// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
34-
/// @param outputs - The Outputs to be transferred. signed over via permit2 witness.
35-
/// @param permit2 - the permit2 details, signer, and signature.
36-
/// @custom:emits Filled
37-
function fillPermit2(Output[] memory outputs, OrdersPermit2.Permit2Batch calldata permit2) external {
38-
// transfer all tokens to the Output recipients via permit2 (includes check on nonce & deadline)
39-
_permitWitnessTransferFrom(
40-
outputWitness(outputs), _fillTransferDetails(outputs, permit2.permit.permitted), permit2
41-
);
42-
43-
// emit
44-
emit Filled(outputs);
45-
}
46-
47-
/// @notice Transfer the Order Outputs to their recipients.
48-
function _transferOutputs(Output[] memory outputs) internal {
49-
uint256 value = msg.value;
50-
for (uint256 i; i < outputs.length; i++) {
51-
if (outputs[i].token == address(0)) {
52-
// this line should underflow if there's an attempt to spend more ETH than is attached to the transaction
53-
value -= outputs[i].amount;
54-
payable(outputs[i].recipient).transfer(outputs[i].amount);
55-
} else {
56-
IERC20(outputs[i].token).transferFrom(msg.sender, outputs[i].recipient, outputs[i].amount);
57-
}
58-
}
59-
}
60-
}
61-
628
/// @notice Contract capable of registering initiation of intent-based Orders.
639
abstract contract OrderOrigin is IOrders, OrdersPermit2 {
6410
/// @notice Thrown when an Order is submitted with a deadline that has passed.
@@ -154,11 +100,3 @@ abstract contract OrderOrigin is IOrders, OrdersPermit2 {
154100
}
155101
}
156102
}
157-
158-
contract HostOrders is OrderDestination {
159-
constructor(address _permit2) UsesPermit2(_permit2) {}
160-
}
161-
162-
contract RollupOrders is OrderOrigin, OrderDestination {
163-
constructor(address _permit2) UsesPermit2(_permit2) {}
164-
}

src/orders/Orders.sol

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.24;
3+
4+
import {OrderDestination} from "./OrderDestination.sol";
5+
import {OrderOrigin} from "./OrderOrigin.sol";
6+
import {UsesPermit2} from "../UsesPermit2.sol";
7+
8+
contract HostOrders is OrderDestination {
9+
constructor(address _permit2) UsesPermit2(_permit2) {}
10+
}
11+
12+
contract RollupOrders is OrderOrigin, OrderDestination {
13+
constructor(address _permit2) UsesPermit2(_permit2) {}
14+
}
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,9 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.24;
33

4+
import {IOrders} from "./IOrders.sol";
5+
import {UsesPermit2} from "../UsesPermit2.sol";
46
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";
5-
import {IOrders} from "../interfaces/IOrders.sol";
6-
7-
abstract contract UsesPermit2 {
8-
/// @param permit - the permit2 single token transfer details. includes a `deadline` and an unordered `nonce`.
9-
/// @param signer - the signer of the permit2 info; the owner of the tokens.
10-
/// @param signature - the signature over the permit + witness.
11-
struct Permit2 {
12-
ISignatureTransfer.PermitTransferFrom permit;
13-
address owner;
14-
bytes signature;
15-
}
16-
17-
/// @param permit - the permit2 batch token transfer details. includes a `deadline` and an unordered `nonce`.
18-
/// @param signer - the signer of the permit2 info; the owner of the tokens.
19-
/// @param signature - the signature over the permit + witness.
20-
struct Permit2Batch {
21-
ISignatureTransfer.PermitBatchTransferFrom permit;
22-
address owner;
23-
bytes signature;
24-
}
25-
26-
/// @notice Struct to hold the pre-hashed witness field and the witness type string.
27-
struct Witness {
28-
bytes32 witnessHash;
29-
string witnessTypeString;
30-
}
31-
32-
/// @notice The Permit2 contract address.
33-
address immutable permit2Contract;
34-
35-
constructor(address _permit2) {
36-
permit2Contract = _permit2;
37-
}
38-
}
397

408
abstract contract OrdersPermit2 is UsesPermit2 {
419
string constant _OUTPUT_WITNESS_TYPESTRING =
@@ -128,72 +96,3 @@ abstract contract OrdersPermit2 is UsesPermit2 {
12896
}
12997
}
13098
}
131-
132-
abstract contract PassagePermit2 is UsesPermit2 {
133-
string constant _ENTER_WITNESS_TYPESTRING =
134-
"EnterWitness witness)EnterWitness(uint256 rollupChainId,address rollupRecipient)TokenPermissions(address token,uint256 amount)";
135-
136-
bytes32 constant _ENTER_WITNESS_TYPEHASH = keccak256("EnterWitness(uint256 rollupChainId,address rollupRecipient)");
137-
138-
string constant _EXIT_WITNESS_TYPESTRING =
139-
"ExitWitness witness)ExitWitness(address hostRecipient)TokenPermissions(address token,uint256 amount)";
140-
141-
bytes32 constant _EXIT_WITNESS_TYPEHASH = keccak256("ExitWitness(address hostRecipient)");
142-
143-
/// @notice Struct to hash Enter witness data into a 32-byte witness field, in an EIP-712 compliant way.
144-
struct EnterWitness {
145-
uint256 rollupChainId;
146-
address rollupRecipient;
147-
}
148-
149-
/// @notice Struct to hash Exit witness data into a 32-byte witness field, in an EIP-712 compliant way.
150-
struct ExitWitness {
151-
address hostRecipient;
152-
}
153-
154-
/// @notice Encode & hash the rollupChainId and rollupRecipient for use as a permit2 witness.
155-
/// @return _witness - the hashed witness and its typestring.
156-
function enterWitness(uint256 rollupChainId, address rollupRecipient)
157-
public
158-
pure
159-
returns (Witness memory _witness)
160-
{
161-
_witness.witnessHash =
162-
keccak256(abi.encode(_ENTER_WITNESS_TYPEHASH, EnterWitness(rollupChainId, rollupRecipient)));
163-
_witness.witnessTypeString = _ENTER_WITNESS_TYPESTRING;
164-
}
165-
166-
/// @notice Hash the hostRecipient for use as a permit2 witness.
167-
/// @return _witness - the hashed witness and its typestring.
168-
function exitWitness(address hostRecipient) public pure returns (Witness memory _witness) {
169-
_witness.witnessHash = keccak256(abi.encode(_EXIT_WITNESS_TYPEHASH, ExitWitness(hostRecipient)));
170-
_witness.witnessTypeString = _EXIT_WITNESS_TYPESTRING;
171-
}
172-
173-
/// @notice Transfer tokens using permit2.
174-
/// @param _witness - the hashed witness and its typestring.
175-
/// @param permit2 - the Permit2 information.
176-
function _permitWitnessTransferFrom(Witness memory _witness, Permit2 calldata permit2) internal {
177-
ISignatureTransfer(permit2Contract).permitWitnessTransferFrom(
178-
permit2.permit,
179-
_selfTransferDetails(permit2.permit.permitted.amount),
180-
permit2.owner,
181-
_witness.witnessHash,
182-
_witness.witnessTypeString,
183-
permit2.signature
184-
);
185-
}
186-
187-
/// @notice Construct TransferDetails transferring a balance to this contract, for passing to permit2.
188-
/// @dev always transfers the full amount to address(this).
189-
/// @param amount - the amount to transfer to this contract.
190-
/// @return transferDetails - the SignatureTransferDetails generated.
191-
function _selfTransferDetails(uint256 amount)
192-
internal
193-
view
194-
returns (ISignatureTransfer.SignatureTransferDetails memory transferDetails)
195-
{
196-
transferDetails.to = address(this);
197-
transferDetails.requestedAmount = amount;
198-
}
199-
}

0 commit comments

Comments
 (0)