Skip to content

Commit f86a1c1

Browse files
authored
Merge pull request #36 from init4tech/anna/refactor
refactor: modify style of Zenith functions
2 parents d89de06 + 9b98393 commit f86a1c1

File tree

1 file changed

+60
-133
lines changed

1 file changed

+60
-133
lines changed

src/Passage.sol

+60-133
Original file line numberDiff line numberDiff line change
@@ -12,53 +12,25 @@ contract Passage {
1212
/// @notice The address that is allowed to withdraw funds from the contract.
1313
address public immutable withdrawalAdmin;
1414

15-
/// @notice Thrown when attempting to fulfill an exit order with a deadline that has passed.
16-
error OrderExpired();
17-
1815
/// @notice Thrown when attempting to withdraw funds if not withdrawal admin.
1916
error OnlyWithdrawalAdmin();
2017

2118
/// @notice Emitted when tokens enter the rollup.
2219
/// @param token - The address of the token entering the rollup.
2320
/// @param rollupRecipient - The recipient of the token on the rollup.
2421
/// @param amount - The amount of the token entering the rollup.
25-
event Enter(uint256 rollupChainId, address indexed token, address indexed rollupRecipient, uint256 amount);
22+
event Enter(uint256 indexed rollupChainId, address indexed token, address indexed rollupRecipient, uint256 amount);
23+
24+
/// @notice Emitted when the admin withdraws tokens from the contract.
25+
event Withdrawal(address indexed token, address indexed recipient, uint256 amount);
2626

2727
/// @notice Emitted when an exit order is fulfilled by the Builder.
28-
/// @param token - The address of the token transferred to the recipient.
28+
/// @param token - The address of the token transferred to the recipient. address(0) corresponds to native host Ether.
2929
/// @param hostRecipient - The recipient of the token on host.
3030
/// @param amount - The amount of the token transferred to the recipient.
31-
event ExitFilled(uint256 rollupChainId, address indexed token, address indexed hostRecipient, uint256 amount);
32-
33-
/// @notice Emitted when the admin withdraws tokens from the contract.
34-
event Withdraw(Withdrawal withdrawal);
35-
36-
/// @notice A bundled withdrawal of Ether and ERC20 tokens.
37-
/// @param recipient - The address to receive the Ether and ERC20 tokens.
38-
/// @param ethAmount - The amount of Ether to transfer to the recipient. Zero if no Ether to transfer.
39-
/// @param tokens - The addresses of the ERC20 tokens to transfer to the recipient.
40-
/// @param tokenAmounts - The amounts of the ERC20 tokens to transfer to the recipient.
41-
struct Withdrawal {
42-
address recipient;
43-
uint256 ethAmount;
44-
address[] tokens;
45-
uint256[] tokenAmounts;
46-
}
47-
48-
/// @notice Details of an exit order to be fulfilled by the Builder.
49-
/// @param token - The address of the token to be transferred to the recipient.
50-
/// If token is the zero address, the amount is native Ether.
51-
/// Corresponds to tokenOut_H in the RollupPassage contract.
52-
/// @param recipient - The recipient of the token on host.
53-
/// Corresponds to recipient_H in the RollupPassage contract.
54-
/// @param amount - The amount of the token to be transferred to the recipient.
55-
/// Corresponds to one or more amountOutMinimum_H in the RollupPassage contract.
56-
struct ExitOrder {
57-
uint256 rollupChainId;
58-
address token;
59-
address recipient;
60-
uint256 amount;
61-
}
31+
event ExitFulfilled(
32+
uint256 indexed rollupChainId, address indexed token, address indexed hostRecipient, uint256 amount
33+
);
6234

6335
/// @param _defaultRollupChainId - the chainId of the rollup that Ether will be sent to by default
6436
/// when entering the rollup via fallback() or receive() fns.
@@ -93,64 +65,42 @@ contract Passage {
9365
/// @param token - The address of the ERC20 token on the Host.
9466
/// @param amount - The amount of the ERC20 token to transfer to the rollup.
9567
/// @custom:emits Enter indicating the amount of tokens to mint on the rollup & its recipient.
96-
function enter(uint256 rollupChainId, address rollupRecipient, address token, uint256 amount) public payable {
68+
function enter(uint256 rollupChainId, address token, address rollupRecipient, uint256 amount) external payable {
9769
IERC20(token).transferFrom(msg.sender, address(this), amount);
9870
emit Enter(rollupChainId, token, rollupRecipient, amount);
9971
}
10072

101-
/// @notice Fulfills exit orders by transferring tokenOut to the recipient
102-
/// @param orders The exit orders to fulfill
103-
/// @custom:emits ExitFilled for each exit order fulfilled.
104-
/// @dev Builder SHOULD call `fulfillExits` atomically with `submitBlock`.
105-
/// Builder SHOULD set a block expiration time that is AT MOST the minimum of all exit order deadlines;
106-
/// this way, `fulfillExits` + `submitBlock` will revert atomically on mainnet if any exit orders have expired.
107-
/// Otherwise, `fulfillExits` may mine on mainnet, while `submitExit` reverts on the rollup,
108-
/// and the Builder can't collect the corresponding value on the rollup.
109-
/// @dev Called by the Builder atomically with a transaction calling `submitBlock`.
110-
/// The user-submitted transactions initiating the ExitOrders on the rollup
111-
/// must be included by the Builder in the rollup block submitted via `submitBlock`.
112-
/// @dev The user transfers tokenIn on the rollup, and receives tokenOut on host.
113-
/// @dev The Builder receives tokenIn on the rollup, and transfers tokenOut to the user on host.
114-
/// @dev The rollup STF MUST NOT apply `submitExit` transactions to the rollup state
115-
/// UNLESS a corresponding ExitFilled event is emitted on host in the same block.
116-
/// @dev If the user submits multiple exit transactions for the same token in the same rollup block,
117-
/// the Builder may transfer the cumulative tokenOut to the user in a single ExitFilled event.
118-
/// 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.
119-
/// TODO: add option to fulfill ExitOrders with native ETH? or is it sufficient to only allow users to exit via WETH?
120-
function fulfillExits(ExitOrder[] calldata orders) external payable {
121-
uint256 ethRemaining = msg.value;
122-
for (uint256 i = 0; i < orders.length; i++) {
123-
// transfer value
124-
if (orders[i].token == address(0)) {
125-
// transfer native Ether to the recipient
126-
payable(orders[i].recipient).transfer(orders[i].amount);
127-
// NOTE: this will underflow if sender attempts to transfer more Ether than they sent to the contract
128-
ethRemaining -= orders[i].amount;
129-
} else {
130-
// transfer tokens to the recipient
131-
IERC20(orders[i].token).transferFrom(msg.sender, orders[i].recipient, orders[i].amount);
132-
}
133-
// emit
134-
emit ExitFilled(orders[i].rollupChainId, orders[i].token, orders[i].recipient, orders[i].amount);
73+
/// @notice Allows the admin to withdraw ETH or ERC20 tokens from the contract.
74+
/// @dev Only the admin can call this function.
75+
function withdraw(address token, address recipient, uint256 amount) external {
76+
if (msg.sender != withdrawalAdmin) revert OnlyWithdrawalAdmin();
77+
if (token == address(0)) {
78+
payable(recipient).transfer(amount);
79+
} else {
80+
IERC20(token).transfer(recipient, amount);
13581
}
82+
emit Withdrawal(token, recipient, amount);
13683
}
13784

138-
/// @notice Allows the admin to withdraw tokens from the contract.
139-
/// @dev Only the admin can call this function.
140-
/// @param withdrawals - The withdrawals to process. See Withdrawal struct docs for details.
141-
function withdraw(Withdrawal[] calldata withdrawals) external {
142-
if (msg.sender != withdrawalAdmin) revert OnlyWithdrawalAdmin();
143-
for (uint256 i = 0; i < withdrawals.length; i++) {
144-
// transfer ether
145-
if (withdrawals[i].ethAmount > 0) {
146-
payable(withdrawals[i].recipient).transfer(withdrawals[i].ethAmount);
147-
}
148-
// transfer ERC20 tokens
149-
for (uint256 j = 0; j < withdrawals[i].tokens.length; j++) {
150-
IERC20(withdrawals[i].tokens[j]).transfer(withdrawals[i].recipient, withdrawals[i].tokenAmounts[j]);
151-
}
152-
emit Withdraw(withdrawals[i]);
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);
153102
}
103+
emit ExitFulfilled(rollupChainId, token, recipient, amount);
154104
}
155105
}
156106

@@ -159,8 +109,8 @@ contract RollupPassage {
159109
/// @notice Thrown when an exit transaction is submitted with a deadline that has passed.
160110
error OrderExpired();
161111

162-
/// @notice Emitted when an exit order is submitted & successfully processed, indicating it was also fulfilled on host.
163-
/// @dev See `submitExit` for parameter docs.
112+
/// @notice Emitted when an exit order is successfully processed, indicating it was also fulfilled on host.
113+
/// @dev See `exit` for parameter docs.
164114
event Exit(
165115
address indexed tokenIn_RU,
166116
address indexed tokenOut_H,
@@ -173,9 +123,9 @@ contract RollupPassage {
173123
/// @notice Emitted when tokens or native Ether is swept from the contract.
174124
/// @dev Intended to improve visibility for Builders to ensure Sweep isn't called unexpectedly.
175125
/// Intentionally does not bother to emit which token(s) were swept, nor their amounts.
176-
event Sweep(address indexed recipient);
126+
event Sweep(address indexed token, address indexed recipient, uint256 amount);
177127

178-
/// @notice Expresses an intent to exit the rollup with ERC20s.
128+
/// @notice Request to exit the rollup with ERC20s.
179129
/// @dev Exits are modeled as a swap between two tokens.
180130
/// tokenIn_RU is provided on the rollup; in exchange,
181131
/// tokenOut_H is expected to be received on host.
@@ -195,65 +145,42 @@ contract RollupPassage {
195145
/// @param amountOutMinimum_H - The minimum amount of tokenOut_H the user expects to receive on host.
196146
/// @custom:reverts Expired if the deadline has passed.
197147
/// @custom:emits Exit if the exit transaction succeeds.
198-
function submitExit(
148+
function exit(
199149
address tokenIn_RU,
200150
address tokenOut_H,
201151
address recipient_H,
202152
uint256 deadline,
203153
uint256 amountIn_RU,
204154
uint256 amountOutMinimum_H
205-
) external {
155+
) external payable {
206156
// check that the deadline hasn't passed
207157
if (block.timestamp >= deadline) revert OrderExpired();
208158

209-
// transfer the tokens from the user to the contract
210-
IERC20(tokenIn_RU).transferFrom(msg.sender, address(this), amountIn_RU);
159+
if (tokenIn_RU == address(0)) {
160+
require(amountIn_RU == msg.value);
161+
} else {
162+
IERC20(tokenIn_RU).transferFrom(msg.sender, address(this), amountIn_RU);
163+
}
211164

212165
// emit the exit event
213166
emit Exit(tokenIn_RU, tokenOut_H, recipient_H, deadline, amountIn_RU, amountOutMinimum_H);
214167
}
215168

216-
/// @notice Expresses an intent to exit the rollup with native Ether.
217-
/// @dev See `submitExit` above for dev details on how exits work.
218-
/// @dev tokenIn_RU is set to address(0), native rollup Ether.
219-
/// amountIn_RU is set to msg.value.
220-
/// @param tokenOut_H - The address of the token the user expects to receive on host.
221-
/// @param recipient_H - The address of the recipient of tokenOut_H on host.
222-
/// @param deadline - The deadline by which the exit order must be fulfilled.
223-
/// @param amountOutMinimum_H - The minimum amount of tokenOut_H the user expects to receive on host.
224-
/// @custom:reverts Expired if the deadline has passed.
225-
/// @custom:emits Exit if the exit transaction succeeds.
226-
function submitEthExit(address tokenOut_H, address recipient_H, uint256 deadline, uint256 amountOutMinimum_H)
227-
external
228-
payable
229-
{
230-
// check that the deadline hasn't passed
231-
if (block.timestamp >= deadline) revert OrderExpired();
232-
233-
// emit the exit event
234-
emit Exit(address(0), tokenOut_H, recipient_H, deadline, msg.value, amountOutMinimum_H);
235-
}
236-
237-
/// @notice Transfer the entire balance of tokens to the recipient.
238-
/// @dev Called by the Builder within the same block as `submitExit` transactions to claim the amounts of `tokenIn`.
169+
/// @notice Transfer the entire balance of ERC20 tokens to the recipient.
170+
/// @dev Called by the Builder within the same block as users' `swap` transactions
171+
/// to claim the amounts of `tokenIn`.
239172
/// @dev Builder MUST ensure that no other account calls `sweep` before them.
173+
/// @param token - The token to transfer.
240174
/// @param recipient - The address to receive the tokens.
241-
/// @param tokens - The addresses of the tokens to transfer.
242-
/// TODO: should there be more granular control for the builder to specify a different recipient for each token?
243-
function sweep(address recipient, address[] calldata tokens) public {
244-
for (uint256 i = 0; i < tokens.length; i++) {
245-
IERC20 token = IERC20(tokens[i]);
246-
token.transfer(recipient, token.balanceOf(address(this)));
175+
function sweep(address token, address recipient) public {
176+
uint256 balance;
177+
if (token == address(0)) {
178+
balance = address(this).balance;
179+
payable(recipient).transfer(balance);
180+
} else {
181+
balance = IERC20(token).balanceOf(address(this));
182+
IERC20(token).transfer(recipient, balance);
247183
}
248-
emit Sweep(recipient);
249-
}
250-
251-
/// @notice Transfer the entire balance of native Ether to the recipient.
252-
/// @dev Called by the Builder within the same block as `submitExit` transactions to claim the amounts of native Ether.
253-
/// @dev Builder MUST ensure that no other account calls `sweepETH` before them.
254-
/// @param recipient - The address to receive the native Ether.
255-
function sweepEth(address payable recipient) public {
256-
recipient.transfer(address(this).balance);
257-
emit Sweep(recipient);
184+
emit Sweep(token, recipient, balance);
258185
}
259186
}

0 commit comments

Comments
 (0)