@@ -3,10 +3,12 @@ pragma solidity ^0.8.24;
33
44// import IERC20 from OpenZeppelin
55import {IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol " ;
6+ import {AccessControlDefaultAdminRules} from
7+ "openzeppelin-contracts/contracts/access/extensions/AccessControlDefaultAdminRules.sol " ;
68
79/// @notice A contract deployed to Host chain that allows tokens to enter the rollup,
810/// and enables Builders to fulfill requests to exchange tokens on the Rollup for tokens on the Host.
9- contract Passage {
11+ contract Passage is AccessControlDefaultAdminRules {
1012 /// @notice The chainId of the default rollup chain.
1113 uint256 immutable defaultRollupChainId;
1214
@@ -25,6 +27,16 @@ contract Passage {
2527 /// @param amount - The amount of the token transferred to the recipient.
2628 event ExitFilled (uint256 rollupChainId , address indexed token , address indexed hostRecipient , uint256 amount );
2729
30+ /// @notice Emitted when the admin withdraws tokens from the contract.
31+ event Withdraw (Withdrawal withdrawal );
32+
33+ struct Withdrawal {
34+ address recipient;
35+ uint256 ethAmount;
36+ address [] tokens;
37+ uint256 [] tokenAmounts;
38+ }
39+
2840 /// @notice Details of an exit order to be fulfilled by the Builder.
2941 /// @param token - The address of the token to be transferred to the recipient.
3042 /// If token is the zero address, the amount is native Ether.
@@ -40,7 +52,12 @@ contract Passage {
4052 uint256 amount;
4153 }
4254
43- constructor (uint256 _defaultRollupChainId ) {
55+ /// @notice Initializes the Admin role.
56+ /// @dev See `AccessControlDefaultAdminRules` for information on contract administration.
57+ /// - Admin role can grant and revoke Sequencer roles.
58+ /// - Admin role can be transferred via two-step process with a 1 day timelock.
59+ /// @param admin - the address that will be the initial admin.
60+ constructor (uint256 _defaultRollupChainId , address admin ) AccessControlDefaultAdminRules (1 days, admin) {
4461 defaultRollupChainId = _defaultRollupChainId;
4562 }
4663
@@ -111,6 +128,22 @@ contract Passage {
111128 emit ExitFilled (orders[i].rollupChainId, orders[i].token, orders[i].recipient, orders[i].amount);
112129 }
113130 }
131+
132+ /// @notice Allows the admin to withdraw tokens from the contract.
133+ /// @dev Only the admin can call this function.
134+ function withdraw (Withdrawal[] calldata withdrawals ) external onlyRole (DEFAULT_ADMIN_ROLE) {
135+ for (uint256 i = 0 ; i < withdrawals.length ; i++ ) {
136+ // transfer ether
137+ if (withdrawals[i].ethAmount > 0 ) {
138+ payable (withdrawals[i].recipient).transfer (withdrawals[i].ethAmount);
139+ }
140+ // transfer ERC20 tokens
141+ for (uint256 j = 0 ; j < withdrawals[i].tokens.length ; j++ ) {
142+ IERC20 (withdrawals[i].tokens[j]).transfer (withdrawals[i].recipient, withdrawals[i].tokenAmounts[j]);
143+ }
144+ emit Withdraw (withdrawals[i]);
145+ }
146+ }
114147}
115148
116149/// @notice A contract deployed to the Rollup that allows users to atomically exchange tokens on the Rollup for tokens on the Host.
0 commit comments