@@ -7,20 +7,23 @@ import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
7
7
/// @notice A contract deployed to Host chain that allows tokens to enter the rollup,
8
8
/// and enables Builders to fulfill requests to exchange tokens on the Rollup for tokens on the Host.
9
9
contract HostPassage {
10
+ /// @notice The chainId of the default rollup chain.
11
+ uint256 immutable defaultRollupChainId;
12
+
10
13
/// @notice Thrown when attempting to fulfill an exit order with a deadline that has passed.
11
14
error OrderExpired ();
12
15
13
16
/// @notice Emitted when tokens enter the rollup.
14
17
/// @param token - The address of the token entering the rollup.
15
18
/// @param rollupRecipient - The recipient of the token on the rollup.
16
19
/// @param amount - The amount of the token entering the rollup.
17
- event Enter (address indexed token , address indexed rollupRecipient , uint256 amount );
20
+ event Enter (uint256 rollupChainId , address indexed token , address indexed rollupRecipient , uint256 amount );
18
21
19
22
/// @notice Emitted when an exit order is fulfilled by the Builder.
20
23
/// @param token - The address of the token transferred to the recipient.
21
24
/// @param hostRecipient - The recipient of the token on host.
22
25
/// @param amount - The amount of the token transferred to the recipient.
23
- event ExitFilled (address indexed token , address indexed hostRecipient , uint256 amount );
26
+ event ExitFilled (uint256 rollupChainId , address indexed token , address indexed hostRecipient , uint256 amount );
24
27
25
28
/// @notice Details of an exit order to be fulfilled by the Builder.
26
29
/// @param token - The address of the token to be transferred to the recipient.
@@ -30,37 +33,56 @@ contract HostPassage {
30
33
/// Corresponds to recipient_H in the RollupPassage contract.
31
34
/// @param amount - The amount of the token to be transferred to the recipient.
32
35
/// Corresponds to one or more amountOutMinimum_H in the RollupPassage contract.
33
- /// @param deadline - The deadline by which the exit order must be fulfilled.
34
- /// Corresponds to deadline in the RollupPassage contract.
35
- /// If the ExitOrder is a combination of multiple orders, the deadline SHOULD be the latest of all orders.
36
36
struct ExitOrder {
37
+ uint256 rollupChainId;
37
38
address token;
38
39
address recipient;
39
40
uint256 amount;
40
- uint256 deadline;
41
+ }
42
+
43
+ constructor (uint256 _defaultRollupChainId ) {
44
+ defaultRollupChainId = _defaultRollupChainId;
41
45
}
42
46
43
47
/// @notice Allows native Ether to enter the rollup by being sent directly to the contract.
44
48
fallback () external payable {
45
- enter (msg .sender );
49
+ enter (defaultRollupChainId, msg .sender );
46
50
}
47
51
48
52
/// @notice Allows native Ether to enter the rollup by being sent directly to the contract.
49
53
receive () external payable {
50
- enter (msg .sender );
54
+ enter (defaultRollupChainId, msg .sender );
51
55
}
52
56
53
57
/// @notice Allows native Ether to enter the rollup.
54
58
/// @dev Permanently burns the entire msg.value by locking it in this contract.
59
+ /// @param rollupChainId - The rollup chain to enter.
60
+ /// @param rollupRecipient - The recipient of the Ether on the rollup.
61
+ /// @custom:emits Enter indicating the amount of Ether to mint on the rollup & its recipient.
62
+ function enter (uint256 rollupChainId , address rollupRecipient ) public payable {
63
+ emit Enter (rollupChainId, address (0 ), rollupRecipient, msg .value );
64
+ }
65
+
66
+ /// @notice Allows ERC20s to enter the rollup.
67
+ /// @dev Permanently burns the token amount by locking it in this contract.
68
+ /// @param rollupChainId - The rollup chain to enter.
55
69
/// @param rollupRecipient - The recipient of the Ether on the rollup.
56
- /// @custom:emits Enter indicatig the amount of Ether to mint on the rollup & its recipient.
57
- function enter (address rollupRecipient ) public payable {
58
- emit Enter (address (0 ), rollupRecipient, msg .value );
70
+ /// @param token - The address of the ERC20 token on the Host.
71
+ /// @param amount - The amount of the ERC20 token to transfer to the rollup.
72
+ /// @custom:emits Enter indicating the amount of tokens to mint on the rollup & its recipient.
73
+ function enter (uint256 rollupChainId , address rollupRecipient , address token , uint256 amount ) public payable {
74
+ IERC20 (token).transferFrom (msg .sender , address (this ), amount);
75
+ emit Enter (rollupChainId, token, rollupRecipient, amount);
59
76
}
60
77
61
78
/// @notice Fulfills exit orders by transferring tokenOut to the recipient
62
79
/// @param orders The exit orders to fulfill
63
80
/// @custom:emits ExitFilled for each exit order fulfilled.
81
+ /// @dev Builder SHOULD call `filfillExits` atomically with `submitBlock`.
82
+ /// Builder SHOULD set a block expiration time that is AT MOST the minimum of all exit order deadlines;
83
+ /// this way, `fulfillExits` + `submitBlock` will revert atomically on mainnet if any exit orders have expired.
84
+ /// Otherwise, `filfillExits` may mine on mainnet, while `submitExit` reverts on the rollup,
85
+ /// and the Builder can't collect the corresponding value on the rollup.
64
86
/// @dev Called by the Builder atomically with a transaction calling `submitBlock`.
65
87
/// The user-submitted transactions initiating the ExitOrders on the rollup
66
88
/// must be included by the Builder in the rollup block submitted via `submitBlock`.
@@ -72,15 +94,21 @@ contract HostPassage {
72
94
/// the Builder may transfer the cumulative tokenOut to the user in a single ExitFilled event.
73
95
/// The rollup STF will apply the user's exit transactions on the rollup up to the point that sum(tokenOut) is lte the ExitFilled amount.
74
96
/// TODO: add option to fulfill ExitOrders with native ETH? or is it sufficient to only allow users to exit via WETH?
75
- function fulfillExits (ExitOrder[] calldata orders ) external {
97
+ function fulfillExits (ExitOrder[] calldata orders ) external payable {
98
+ uint256 ethRemaining = msg .value ;
76
99
for (uint256 i = 0 ; i < orders.length ; i++ ) {
77
- ExitOrder memory order = orders[i];
78
- // check that the deadline hasn't passed
79
- if (block .timestamp > order.deadline) revert OrderExpired ();
80
- // transfer tokens to the recipient
81
- IERC20 (order.token).transferFrom (msg .sender , order.recipient, order.amount);
100
+ // transfer value
101
+ if (orders[i].token == address (0 )) {
102
+ // transfer native Ether to the recipient
103
+ payable (orders[i].recipient).transfer (orders[i].amount);
104
+ // NOTE: this will underflow if sender attempts to transfer more Ether than they sent to the contract
105
+ ethRemaining -= orders[i].amount;
106
+ } else {
107
+ // transfer tokens to the recipient
108
+ IERC20 (orders[i].token).transferFrom (msg .sender , orders[i].recipient, orders[i].amount);
109
+ }
82
110
// emit
83
- emit ExitFilled (order. token, order .recipient, order .amount);
111
+ emit ExitFilled (orders[i].rollupChainId, orders[i]. token, orders[i] .recipient, orders[i] .amount);
84
112
}
85
113
}
86
114
}
@@ -154,7 +182,7 @@ contract RollupPassage {
154
182
/// @param amountOutMinimum_H - The minimum amount of tokenOut_H the user expects to receive on host.
155
183
/// @custom:reverts Expired if the deadline has passed.
156
184
/// @custom:emits Exit if the exit transaction succeeds.
157
- function submitExit (address tokenOut_H , address recipient_H , uint256 deadline , uint256 amountOutMinimum_H )
185
+ function submitEthExit (address tokenOut_H , address recipient_H , uint256 deadline , uint256 amountOutMinimum_H )
158
186
external
159
187
payable
160
188
{
@@ -183,7 +211,7 @@ contract RollupPassage {
183
211
/// @dev Called by the Builder within the same block as `submitExit` transactions to claim the amounts of native Ether.
184
212
/// @dev Builder MUST ensure that no other account calls `sweepETH` before them.
185
213
/// @param recipient - The address to receive the native Ether.
186
- function sweepETH (address payable recipient ) public {
214
+ function sweepEth (address payable recipient ) public {
187
215
recipient.transfer (address (this ).balance);
188
216
emit Sweep (recipient);
189
217
}
0 commit comments