Skip to content

Commit 98ba4ba

Browse files
authored
feat: fulfill swaps on Host or Rollup (#37)
1 parent 1479eae commit 98ba4ba

File tree

1 file changed

+69
-69
lines changed

1 file changed

+69
-69
lines changed

src/Passage.sol

Lines changed: 69 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,38 @@ pragma solidity ^0.8.24;
33

44
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
55

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+
635
/// @notice A contract deployed to Host chain that allows tokens to enter the rollup,
736
/// 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 {
938
/// @notice The chainId of rollup that Ether will be sent to by default when entering the rollup via fallback() or receive().
1039
uint256 public immutable defaultRollupChainId;
1140

@@ -24,14 +53,6 @@ contract Passage {
2453
/// @notice Emitted when the admin withdraws tokens from the contract.
2554
event Withdrawal(address indexed token, address indexed recipient, uint256 amount);
2655

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-
3556
/// @param _defaultRollupChainId - the chainId of the rollup that Ether will be sent to by default
3657
/// when entering the rollup via fallback() or receive() fns.
3758
constructor(uint256 _defaultRollupChainId, address _withdrawalAdmin) {
@@ -81,89 +102,68 @@ contract Passage {
81102
}
82103
emit Withdrawal(token, recipient, amount);
83104
}
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-
}
105105
}
106106

107107
/// @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.
110110
error OrderExpired();
111111

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,
118119
uint256 deadline,
119-
uint256 amountIn_RU,
120-
uint256 amountOutMinimum_H
120+
uint256 amountIn,
121+
uint256 amountOut
121122
);
122123

123124
/// @notice Emitted when tokens or native Ether is swept from the contract.
124125
/// @dev Intended to improve visibility for Builders to ensure Sweep isn't called unexpectedly.
125126
/// Intentionally does not bother to emit which token(s) were swept, nor their amounts.
126127
event Sweep(address indexed token, address indexed recipient, uint256 amount);
127128

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
136134
/// 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.
146145
/// @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,
152152
uint256 deadline,
153-
uint256 amountIn_RU,
154-
uint256 amountOutMinimum_H
153+
uint256 amountIn,
154+
uint256 amountOut
155155
) external payable {
156156
// check that the deadline hasn't passed
157157
if (block.timestamp >= deadline) revert OrderExpired();
158158

159-
if (tokenIn_RU == address(0)) {
160-
require(amountIn_RU == msg.value);
159+
if (tokenIn == address(0)) {
160+
require(amountIn == msg.value);
161161
} else {
162-
IERC20(tokenIn_RU).transferFrom(msg.sender, address(this), amountIn_RU);
162+
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
163163
}
164164

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);
167167
}
168168

169169
/// @notice Transfer the entire balance of ERC20 tokens to the recipient.

0 commit comments

Comments
 (0)