-
Notifications
You must be signed in to change notification settings - Fork 64
feat: upgrade bridge to allow for transfer of all token assets #103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
59f88b0
c3cfd54
1ff1b41
f004b73
75e4ab0
11b66b1
97452bd
7980767
d3a9285
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.15; | ||
|
|
||
| import {Script} from "forge-std/Script.sol"; | ||
| import {PortalWithChainExit} from "../src/PortalWithChainExit.sol"; | ||
| import {console2 as console} from "forge-std/console2.sol"; | ||
|
|
||
| contract DeployPortalWithChainExit is Script { | ||
| function run() public { | ||
| vm.startBroadcast(); | ||
| PortalWithChainExit portalWithChainExit = new PortalWithChainExit(); | ||
| vm.stopBroadcast(); | ||
| console.log("Deploying PortalWithChainOwnerExit at:", address(portalWithChainExit)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,6 +70,10 @@ contract Portal is Initializable, ResourceMetering, ISemver { | |
| /// It is not safe to trust `ERC20.balanceOf` as it may lie. | ||
| uint256 internal _balance; | ||
|
|
||
| // Owner of the current chain | ||
| address public chainOwner; | ||
|
|
||
|
|
||
| /// @notice Emitted when a transaction is deposited from L1 to L2. | ||
| /// The parameters of this event are read by the rollup node and used to derive deposit | ||
| /// transactions on L2. | ||
|
|
@@ -90,16 +94,47 @@ contract Portal is Initializable, ResourceMetering, ISemver { | |
| /// @param success Whether the withdrawal transaction was successful. | ||
| event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); | ||
|
|
||
| /// @notice Emitted when a chain owner is set | ||
| /// @param chainOwner address of the chain owner | ||
| event ChainOwnerSet(address chainOwner); | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. New ChainOwnerEvent |
||
|
|
||
| /// @notice Emitted when the chain owner executes a withdrawal. | ||
| /// @param recipient The address that received the funds. | ||
| /// @param token The token address (Constants.ETHER for native ETH). | ||
| /// @param amount The amount withdrawn. | ||
| event ChainOwnerExitWithdrawal(address indexed recipient, address indexed token, uint256 amount); | ||
|
|
||
| /// @notice Reverts when paused. | ||
| modifier whenNotPaused() { | ||
| if (paused()) revert CallPaused(); | ||
| _; | ||
| } | ||
|
|
||
| /// @notice Reverts if caller is not the proxy admin. | ||
| modifier onlyAdmin() { | ||
| address admin; | ||
| bytes32 adminSlot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; | ||
| assembly { | ||
| admin := sload(adminSlot) | ||
| } | ||
| require(msg.sender == admin, "Portal: caller is not admin"); | ||
| _; | ||
| } | ||
|
|
||
| modifier onlyChainOwnerAndAdmin() { | ||
| address admin; | ||
| bytes32 adminSlot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; | ||
| assembly { | ||
| admin := sload(adminSlot) | ||
| } | ||
| require(msg.sender == chainOwner || msg.sender == admin, "Portal: caller is not chain owner or admin"); | ||
| _; | ||
| } | ||
|
|
||
| /// @notice Semantic version. | ||
| /// @custom:semver 1.0.0 | ||
| /// @custom:semver 1.1.0 | ||
| function version() public pure virtual returns (string memory) { | ||
| return "1.0.0"; | ||
| return "1.1.0"; | ||
| } | ||
|
|
||
| /// @notice Constructs the OptimismPortal contract. | ||
|
|
@@ -489,6 +524,54 @@ contract Portal is Initializable, ResourceMetering, ISemver { | |
| ); | ||
| } | ||
|
|
||
| function setChainOwner(address _chainOwner) external onlyChainOwnerAndAdmin { | ||
| require(_chainOwner != address(0), "chain owner must not be 0 address"); | ||
| chainOwner = _chainOwner; | ||
| emit ChainOwnerSet(chainOwner); | ||
| } | ||
|
|
||
| /// @notice Allows owner to withdraw the gas paying token held by the portal. | ||
| /// Can be called regardless of pause state. | ||
| /// @param _recipient The address to receive the withdrawn funds. | ||
| function chainOwnerExitPortalNetworkToken(address _recipient) external onlyChainOwnerAndAdmin { | ||
| chainOwnerExitPortal(address(0), _recipient); | ||
| } | ||
|
|
||
| /// @notice Allows owner to withdraw all tokens held by the portal. | ||
| /// Can be called regardless of pause state. | ||
| /// @param _asset The token address to withdraw, or address(0) for the gas paying token. | ||
| /// @param _recipient The address to receive the withdrawn funds. | ||
| function chainOwnerExitPortal(address _asset, address _recipient) public onlyChainOwnerAndAdmin { | ||
| require(_recipient != address(0), "Portal: zero recipient"); | ||
|
|
||
| address token; | ||
| if (_asset != address(0)) { | ||
| token = _asset; | ||
| } else { | ||
| (token,) = gasPayingToken(); | ||
| } | ||
|
|
||
| uint256 amount; | ||
| if (token == Constants.ETHER) { | ||
| amount = address(this).balance; | ||
| if (amount > 0) { | ||
| (bool success,) = _recipient.call{value: amount}(""); | ||
| require(success, "Portal: ETH transfer failed"); | ||
| } | ||
| } else { | ||
| amount = IERC20(token).balanceOf(address(this)); | ||
| if (amount > 0) { | ||
| (address gasToken,) = gasPayingToken(); | ||
| if (token == gasToken) { | ||
| _balance = 0; | ||
| } | ||
| IERC20(token).safeTransfer(_recipient, amount); | ||
| } | ||
| } | ||
|
|
||
| emit ChainOwnerExitWithdrawal(_recipient, token, amount); | ||
| } | ||
|
|
||
| /// @notice Determine if a given output is finalized. | ||
| /// Reverts if the call to l2Oracle.getL2Output reverts. | ||
| /// Returns a boolean otherwise. | ||
|
|
@@ -505,4 +588,4 @@ contract Portal is Initializable, ResourceMetering, ISemver { | |
| function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) { | ||
| return block.timestamp > _timestamp; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think removing this bracket causes the code to not compile anymore |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New chainOwner Variable