Skip to content

Commit 11b66b1

Browse files
committed
,revert back to same contract
1 parent 75e4ab0 commit 11b66b1

File tree

2 files changed

+91
-589
lines changed

2 files changed

+91
-589
lines changed

contracts/src/Portal.sol

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ contract Portal is Initializable, ResourceMetering, ISemver {
7070
/// It is not safe to trust `ERC20.balanceOf` as it may lie.
7171
uint256 internal _balance;
7272

73+
// Owner of the current chain
74+
address public chainOwner;
75+
76+
7377
/// @notice Emitted when a transaction is deposited from L1 to L2.
7478
/// The parameters of this event are read by the rollup node and used to derive deposit
7579
/// transactions on L2.
@@ -90,16 +94,42 @@ contract Portal is Initializable, ResourceMetering, ISemver {
9094
/// @param success Whether the withdrawal transaction was successful.
9195
event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);
9296

97+
/// @notice Emitted when a chain owner is set
98+
/// @param chainOwner address of the chain owner
99+
event ChainOwnerSet(address chainOwner);
100+
101+
/// @notice Emitted when the chain owner executes a withdrawal.
102+
/// @param recipient The address that received the funds.
103+
/// @param token The token address (Constants.ETHER for native ETH).
104+
/// @param amount The amount withdrawn.
105+
event ChainOwnerExitWithdrawal(address indexed recipient, address indexed token, uint256 amount);
106+
93107
/// @notice Reverts when paused.
94108
modifier whenNotPaused() {
95109
if (paused()) revert CallPaused();
96110
_;
97111
}
98112

113+
/// @notice Reverts if caller is not the proxy admin.
114+
modifier onlyAdmin() {
115+
address admin;
116+
bytes32 adminSlot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
117+
assembly {
118+
admin := sload(adminSlot)
119+
}
120+
require(msg.sender == admin, "Portal: caller is not admin");
121+
_;
122+
}
123+
124+
modifier onlyChainOwner() {
125+
require(msg.sender == chainOwner, "Portal: caller is not chain owner");
126+
_;
127+
}
128+
99129
/// @notice Semantic version.
100-
/// @custom:semver 1.0.0
130+
/// @custom:semver 1.1.0
101131
function version() public pure virtual returns (string memory) {
102-
return "1.0.0";
132+
return "1.1.0";
103133
}
104134

105135
/// @notice Constructs the OptimismPortal contract.
@@ -383,7 +413,12 @@ contract Portal is Initializable, ResourceMetering, ISemver {
383413
}
384414

385415
_depositTransaction({
386-
_to: _to, _mint: _mint, _value: _value, _gasLimit: _gasLimit, _isCreation: _isCreation, _data: _data
416+
_to: _to,
417+
_mint: _mint,
418+
_value: _value,
419+
_gasLimit: _gasLimit,
420+
_isCreation: _isCreation,
421+
_data: _data
387422
});
388423
}
389424

@@ -405,7 +440,12 @@ contract Portal is Initializable, ResourceMetering, ISemver {
405440
if (token != Constants.ETHER && msg.value != 0) revert NoValue();
406441

407442
_depositTransaction({
408-
_to: _to, _mint: msg.value, _value: _value, _gasLimit: _gasLimit, _isCreation: _isCreation, _data: _data
443+
_to: _to,
444+
_mint: msg.value,
445+
_value: _value,
446+
_gasLimit: _gasLimit,
447+
_isCreation: _isCreation,
448+
_data: _data
409449
});
410450
}
411451

@@ -479,6 +519,53 @@ contract Portal is Initializable, ResourceMetering, ISemver {
479519
);
480520
}
481521

522+
function setChainOwner(address _chainOwner) external onlyAdmin {
523+
chainOwner = _chainOwner;`
524+
emit ChainOwnerSet(chainOwner);
525+
}
526+
527+
/// @notice Allows owner to withdraw the gas paying token held by the portal.
528+
/// Can be called regardless of pause state.
529+
/// @param _recipient The address to receive the withdrawn funds.
530+
function chainOwnerExitPortalNetworkToken(address _recipient) external onlyChainOwner {
531+
chainOwnerExitPortal(address(0), _recipient);
532+
}
533+
534+
/// @notice Allows owner to withdraw all tokens held by the portal.
535+
/// Can be called regardless of pause state.
536+
/// @param _asset The token address to withdraw, or address(0) for the gas paying token.
537+
/// @param _recipient The address to receive the withdrawn funds.
538+
function chainOwnerExitPortal(address _asset, address _recipient) public onlyChainOwner {
539+
require(_recipient != address(0), "Portal: zero recipient");
540+
541+
address token;
542+
if (_asset != address(0)) {
543+
token = _asset;
544+
} else {
545+
(token,) = gasPayingToken();
546+
}
547+
548+
uint256 amount;
549+
if (token == Constants.ETHER) {
550+
amount = address(this).balance;
551+
if (amount > 0) {
552+
(bool success,) = _recipient.call{value: amount}("");
553+
require(success, "Portal: ETH transfer failed");
554+
}
555+
} else {
556+
amount = IERC20(token).balanceOf(address(this));
557+
if (amount > 0) {
558+
(address gasToken,) = gasPayingToken();
559+
if (token == gasToken) {
560+
_balance = 0;
561+
}
562+
IERC20(token).safeTransfer(_recipient, amount);
563+
}
564+
}
565+
566+
emit ChainOwnerExitWithdrawal(_recipient, token, amount);
567+
}
568+
482569
/// @notice Determine if a given output is finalized.
483570
/// Reverts if the call to l2Oracle.getL2Output reverts.
484571
/// Returns a boolean otherwise.

0 commit comments

Comments
 (0)