@@ -3,9 +3,38 @@ pragma solidity ^0.8.24;
3
3
4
4
import {IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol " ;
5
5
6
+ contract BasePassage {
7
+ /// @notice Emitted when an swap order is fulfilled by the Builder.
8
+ /// @param originChainId - The chainId on which the swap order was submitted.
9
+ /// @param token - The address of the token transferred to the recipient. address(0) corresponds to native Ether.
10
+ /// @param recipient - The recipient of the token.
11
+ /// @param amount - The amount of the token transferred to the recipient.
12
+ event SwapFulfilled (
13
+ uint256 indexed originChainId , address indexed token , address indexed recipient , uint256 amount
14
+ );
15
+
16
+ /// @notice Fulfill a rollup Swap order.
17
+ /// The user calls `swap` on a rollup; the Builder calls `fulfillSwap` on the target chain.
18
+ /// @custom:emits SwapFulfilled
19
+ /// @param originChainId - The chainId of the rollup on which `swap` was called.
20
+ /// @param token - The address of the token to be transferred to the recipient.
21
+ /// address(0) corresponds to native Ether.
22
+ /// @param recipient - The recipient of the token.
23
+ /// @param amount - The amount of the token to be transferred to the recipient.
24
+ function fulfillSwap (uint256 originChainId , address token , address recipient , uint256 amount ) external payable {
25
+ if (token == address (0 )) {
26
+ require (amount == msg .value );
27
+ payable (recipient).transfer (msg .value );
28
+ } else {
29
+ IERC20 (token).transferFrom (msg .sender , recipient, amount);
30
+ }
31
+ emit SwapFulfilled (originChainId, token, recipient, amount);
32
+ }
33
+ }
34
+
6
35
/// @notice A contract deployed to Host chain that allows tokens to enter the rollup,
7
36
/// and enables Builders to fulfill requests to exchange tokens on the Rollup for tokens on the Host.
8
- contract Passage {
37
+ contract Passage is BasePassage {
9
38
/// @notice The chainId of rollup that Ether will be sent to by default when entering the rollup via fallback() or receive().
10
39
uint256 public immutable defaultRollupChainId;
11
40
@@ -24,14 +53,6 @@ contract Passage {
24
53
/// @notice Emitted when the admin withdraws tokens from the contract.
25
54
event Withdrawal (address indexed token , address indexed recipient , uint256 amount );
26
55
27
- /// @notice Emitted when an exit order is fulfilled by the Builder.
28
- /// @param token - The address of the token transferred to the recipient. address(0) corresponds to native host Ether.
29
- /// @param hostRecipient - The recipient of the token on host.
30
- /// @param amount - The amount of the token transferred to the recipient.
31
- event ExitFulfilled (
32
- uint256 indexed rollupChainId , address indexed token , address indexed hostRecipient , uint256 amount
33
- );
34
-
35
56
/// @param _defaultRollupChainId - the chainId of the rollup that Ether will be sent to by default
36
57
/// when entering the rollup via fallback() or receive() fns.
37
58
constructor (uint256 _defaultRollupChainId , address _withdrawalAdmin ) {
@@ -81,89 +102,68 @@ contract Passage {
81
102
}
82
103
emit Withdrawal (token, recipient, amount);
83
104
}
84
-
85
- /// @notice Fulfill a rollup Exit order.
86
- /// The user calls `exit` on Rollup; the Builder calls `fulfillExit` on Host.
87
- /// @custom:emits ExitFilled
88
- /// @param rollupChainId - The chainId of the rollup on which the `submitExit` was called.
89
- /// @param token - The address of the token to be transferred to the recipient.
90
- /// If token is the zero address, the amount is native Ether.
91
- /// Corresponds to tokenOut_H in the RollupPassage contract.
92
- /// @param recipient - The recipient of the token on host.
93
- /// Corresponds to recipient_H in the RollupPassage contract.
94
- /// @param amount - The amount of the token to be transferred to the recipient.
95
- /// Corresponds to one or more amountOutMinimum_H in the RollupPassage contract.
96
- function fulfillExit (uint256 rollupChainId , address token , address recipient , uint256 amount ) external payable {
97
- if (token == address (0 )) {
98
- require (amount == msg .value );
99
- payable (recipient).transfer (msg .value );
100
- } else {
101
- IERC20 (token).transferFrom (msg .sender , recipient, amount);
102
- }
103
- emit ExitFulfilled (rollupChainId, token, recipient, amount);
104
- }
105
105
}
106
106
107
107
/// @notice A contract deployed to the Rollup that allows users to atomically exchange tokens on the Rollup for tokens on the Host.
108
- contract RollupPassage {
109
- /// @notice Thrown when an exit transaction is submitted with a deadline that has passed.
108
+ contract RollupPassage is BasePassage {
109
+ /// @notice Thrown when an swap transaction is submitted with a deadline that has passed.
110
110
error OrderExpired ();
111
111
112
- /// @notice Emitted when an exit order is successfully processed, indicating it was also fulfilled on host.
113
- /// @dev See `exit` for parameter docs.
114
- event Exit (
115
- address indexed tokenIn_RU ,
116
- address indexed tokenOut_H ,
117
- address indexed recipient_H ,
112
+ /// @notice Emitted when an swap order is successfully processed, indicating it was also fulfilled on the target chain.
113
+ /// @dev See `swap` for parameter docs.
114
+ event Swap (
115
+ uint256 indexed targetChainId ,
116
+ address indexed tokenIn ,
117
+ address indexed tokenOut ,
118
+ address recipient ,
118
119
uint256 deadline ,
119
- uint256 amountIn_RU ,
120
- uint256 amountOutMinimum_H
120
+ uint256 amountIn ,
121
+ uint256 amountOut
121
122
);
122
123
123
124
/// @notice Emitted when tokens or native Ether is swept from the contract.
124
125
/// @dev Intended to improve visibility for Builders to ensure Sweep isn't called unexpectedly.
125
126
/// Intentionally does not bother to emit which token(s) were swept, nor their amounts.
126
127
event Sweep (address indexed token , address indexed recipient , uint256 amount );
127
128
128
- /// @notice Request to exit the rollup with ERC20s.
129
- /// @dev Exits are modeled as a swap between two tokens.
130
- /// tokenIn_RU is provided on the rollup; in exchange,
131
- /// tokenOut_H is expected to be received on host.
132
- /// Exits may "swap" native rollup Ether for host WETH -
133
- /// two assets that represent the same underlying token and should have roughly the same value -
134
- /// or they may be a more "true" swap of rollup USDC for host WETH.
135
- /// Fees paid to the Builders for fulfilling the exit orders
129
+ /// @notice Request to swap ERC20s.
130
+ /// @dev tokenIn is provided on the rollup; in exchange,
131
+ /// tokenOut is expected to be received on targetChainId.
132
+ /// @dev targetChainId may be the current chainId, the Host chainId, or..
133
+ /// @dev Fees paid to the Builders for fulfilling the swap orders
136
134
/// can be included within the "exchange rate" between tokenIn and tokenOut.
137
- /// @dev The Builder claims the tokenIn_RU from the contract by submitting a transaction to `sweep` the tokens within the same block.
138
- /// @dev The Rollup STF MUST NOT apply `submitExit` transactions to the rollup state
139
- /// UNLESS a sufficient ExitFilled event is emitted on host within the same block.
140
- /// @param tokenIn_RU - The address of the token the user supplies as the input on the rollup for the trade.
141
- /// @param tokenOut_H - The address of the token the user expects to receive on host.
142
- /// @param recipient_H - The address of the recipient of tokenOut_H on host.
143
- /// @param deadline - The deadline by which the exit order must be fulfilled.
144
- /// @param amountIn_RU - The amount of tokenIn_RU the user supplies as the input on the rollup for the trade.
145
- /// @param amountOutMinimum_H - The minimum amount of tokenOut_H the user expects to receive on host.
135
+ /// @dev The Builder claims the tokenIn from the contract by submitting a transaction to `sweep` the tokens within the same block.
136
+ /// @dev The Rollup STF MUST NOT apply `swap` transactions to the rollup state
137
+ /// UNLESS a sufficient SwapFulfilled event is emitted on the target chain within the same block.
138
+ /// @param targetChainId - The chain on which tokens should be output.
139
+ /// @param tokenIn - The address of the token the user supplies as the input on the rollup for the trade.
140
+ /// @param tokenOut - The address of the token the user expects to receive on the target chain.
141
+ /// @param recipient - The address of the recipient of tokenOut on the target chain.
142
+ /// @param deadline - The deadline by which the swap order must be fulfilled.
143
+ /// @param amountIn - The amount of tokenIn the user supplies as the input on the rollup for the trade.
144
+ /// @param amountOut - The minimum amount of tokenOut the user expects to receive on the target chain.
146
145
/// @custom:reverts Expired if the deadline has passed.
147
- /// @custom:emits Exit if the exit transaction succeeds.
148
- function exit (
149
- address tokenIn_RU ,
150
- address tokenOut_H ,
151
- address recipient_H ,
146
+ /// @custom:emits Swap if the swap transaction succeeds.
147
+ function swap (
148
+ uint256 targetChainId ,
149
+ address tokenIn ,
150
+ address tokenOut ,
151
+ address recipient ,
152
152
uint256 deadline ,
153
- uint256 amountIn_RU ,
154
- uint256 amountOutMinimum_H
153
+ uint256 amountIn ,
154
+ uint256 amountOut
155
155
) external payable {
156
156
// check that the deadline hasn't passed
157
157
if (block .timestamp >= deadline) revert OrderExpired ();
158
158
159
- if (tokenIn_RU == address (0 )) {
160
- require (amountIn_RU == msg .value );
159
+ if (tokenIn == address (0 )) {
160
+ require (amountIn == msg .value );
161
161
} else {
162
- IERC20 (tokenIn_RU ).transferFrom (msg .sender , address (this ), amountIn_RU );
162
+ IERC20 (tokenIn ).transferFrom (msg .sender , address (this ), amountIn );
163
163
}
164
164
165
- // emit the exit event
166
- emit Exit (tokenIn_RU, tokenOut_H, recipient_H, deadline, amountIn_RU, amountOutMinimum_H );
165
+ // emit the swap event
166
+ emit Swap (targetChainId, tokenIn, tokenOut, recipient, deadline, amountIn, amountOut );
167
167
}
168
168
169
169
/// @notice Transfer the entire balance of ERC20 tokens to the recipient.
0 commit comments