Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions src/Passage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ pragma solidity ^0.8.24;

// import IERC20 from OpenZeppelin
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {AccessControlDefaultAdminRules} from
"openzeppelin-contracts/contracts/access/extensions/AccessControlDefaultAdminRules.sol";

/// @notice A contract deployed to Host chain that allows tokens to enter the rollup,
/// and enables Builders to fulfill requests to exchange tokens on the Rollup for tokens on the Host.
contract Passage {
/// @notice The chainId of the default rollup chain.
contract Passage is AccessControlDefaultAdminRules {
/// @notice The chainId of rollup that Ether will be sent to by default when entering the rollup via fallback() or receive().
uint256 immutable defaultRollupChainId;

/// @notice Thrown when attempting to fulfill an exit order with a deadline that has passed.
Expand All @@ -25,6 +27,21 @@ contract Passage {
/// @param amount - The amount of the token transferred to the recipient.
event ExitFilled(uint256 rollupChainId, address indexed token, address indexed hostRecipient, uint256 amount);

/// @notice Emitted when the admin withdraws tokens from the contract.
event Withdraw(Withdrawal withdrawal);

/// @notice A bundled withdrawal of Ether and ERC20 tokens.
/// @param recipient - The address to receive the Ether and ERC20 tokens.
/// @param ethAmount - The amount of Ether to transfer to the recipient. Zero if no Ether to transfer.
/// @param tokens - The addresses of the ERC20 tokens to transfer to the recipient.
/// @param tokenAmounts - The amounts of the ERC20 tokens to transfer to the recipient.
struct Withdrawal {
address recipient;
uint256 ethAmount;
address[] tokens;
uint256[] tokenAmounts;
}

/// @notice Details of an exit order to be fulfilled by the Builder.
/// @param token - The address of the token to be transferred to the recipient.
/// If token is the zero address, the amount is native Ether.
Expand All @@ -40,7 +57,14 @@ contract Passage {
uint256 amount;
}

constructor(uint256 _defaultRollupChainId) {
/// @notice Initializes the Admin role.
/// @dev See `AccessControlDefaultAdminRules` for information on contract administration.
/// - Admin role can grant and revoke Sequencer roles.
/// - Admin role can be transferred via two-step process with a 1 day timelock.
/// @param _defaultRollupChainId - the chainId of the rollup that Ether will be sent to by default
/// when entering the rollup via fallback() or receive() fns.
/// @param admin - the address that will be the initial admin.
constructor(uint256 _defaultRollupChainId, address admin) AccessControlDefaultAdminRules(1 days, admin) {
defaultRollupChainId = _defaultRollupChainId;
}

Expand Down Expand Up @@ -111,6 +135,23 @@ contract Passage {
emit ExitFilled(orders[i].rollupChainId, orders[i].token, orders[i].recipient, orders[i].amount);
}
}

/// @notice Allows the admin to withdraw tokens from the contract.
/// @dev Only the admin can call this function.
/// @param withdrawals - The withdrawals to process. See Withdrawal struct docs for details.
function withdraw(Withdrawal[] calldata withdrawals) external onlyRole(DEFAULT_ADMIN_ROLE) {
for (uint256 i = 0; i < withdrawals.length; i++) {
// transfer ether
if (withdrawals[i].ethAmount > 0) {
payable(withdrawals[i].recipient).transfer(withdrawals[i].ethAmount);
}
// transfer ERC20 tokens
for (uint256 j = 0; j < withdrawals[i].tokens.length; j++) {
IERC20(withdrawals[i].tokens[j]).transfer(withdrawals[i].recipient, withdrawals[i].tokenAmounts[j]);
}
emit Withdraw(withdrawals[i]);
}
}
}

/// @notice A contract deployed to the Rollup that allows users to atomically exchange tokens on the Rollup for tokens on the Host.
Expand Down
9 changes: 2 additions & 7 deletions src/Zenith.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ pragma solidity ^0.8.24;

// import openzeppelin Role contracts
import {Passage} from "./Passage.sol";
import {AccessControlDefaultAdminRules} from
"openzeppelin-contracts/contracts/access/extensions/AccessControlDefaultAdminRules.sol";

contract Zenith is Passage, AccessControlDefaultAdminRules {
contract Zenith is Passage {
/// @notice Block header information for the rollup block, signed by the sequencer.
/// @param rollupChainId - the chainId of the rollup chain. Any chainId is accepted by the contract.
/// @param sequence - the sequence number of the rollup block. Must be monotonically increasing. Enforced by the contract.
Expand Down Expand Up @@ -74,10 +72,7 @@ contract Zenith is Passage, AccessControlDefaultAdminRules {
/// - Admin role can grant and revoke Sequencer roles.
/// - Admin role can be transferred via two-step process with a 1 day timelock.
/// @param admin - the address that will be the initial admin.
constructor(uint256 defaultRollupChainId, address admin)
Passage(defaultRollupChainId)
AccessControlDefaultAdminRules(1 days, admin)
{}
constructor(uint256 defaultRollupChainId, address admin) Passage(defaultRollupChainId, admin) {}

/// @notice Submit a rollup block with block data submitted via calldata.
/// @dev Blocks are submitted by Builders, with an attestation to the block data signed by a Sequencer.
Expand Down