Commit da7ee222 authored by Luca Donno's avatar Luca Donno Committed by Maurelian

contracts-bedrock: fix solhint ordering warnings

parent 483e27c7
......@@ -38,15 +38,6 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver {
__CrossDomainMessenger_init(Predeploys.L2_CROSS_DOMAIN_MESSENGER, blockedSystemAddresses);
}
/**
* @notice Checks whether the message being sent from the other messenger.
*
* @return True if the message was sent from the messenger, false otherwise.
*/
function _isOtherMessenger() internal view override returns (bool) {
return msg.sender == address(portal) && portal.l2Sender() == otherMessenger;
}
/**
* @notice Sends a message via the OptimismPortal contract.
*
......@@ -63,4 +54,13 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver {
) internal override {
portal.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data);
}
/**
* @notice Checks whether the message being sent from the other messenger.
*
* @return True if the message was sent from the messenger, false otherwise.
*/
function _isOtherMessenger() internal view override returns (bool) {
return msg.sender == address(portal) && portal.l2Sender() == otherMessenger;
}
}
......@@ -94,23 +94,27 @@ contract L1StandardBridge is StandardBridge, Semver {
initialize(_messenger);
}
/**
* @notice Initializer.
*
* @param _messenger Address of the L1CrossDomainMessenger.
*/
function initialize(address payable _messenger) public initializer {
__StandardBridge_init(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE));
}
/**
* @custom:legacy
* @notice Retrieves the access of the corresponding L2 bridge contract.
* @notice Finalizes a withdrawal of ERC20 tokens from L2.
*
* @return Address of the corresponding L2 bridge contract.
* @param _l1Token Address of the token on L1.
* @param _l2Token Address of the corresponding token on L2.
* @param _from Address of the withdrawer on L2.
* @param _to Address of the recipient on L1.
* @param _amount Amount of ETH to withdraw.
* @param _extraData Optional data forwarded from L2.
*/
function l2TokenBridge() external view returns (address) {
return address(otherBridge);
function finalizeERC20Withdrawal(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
bytes calldata _extraData
) external onlyOtherBridge {
emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _extraData);
finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData);
}
/**
......@@ -231,25 +235,21 @@ contract L1StandardBridge is StandardBridge, Semver {
/**
* @custom:legacy
* @notice Finalizes a withdrawal of ERC20 tokens from L2.
* @notice Retrieves the access of the corresponding L2 bridge contract.
*
* @param _l1Token Address of the token on L1.
* @param _l2Token Address of the corresponding token on L2.
* @param _from Address of the withdrawer on L2.
* @param _to Address of the recipient on L1.
* @param _amount Amount of ETH to withdraw.
* @param _extraData Optional data forwarded from L2.
* @return Address of the corresponding L2 bridge contract.
*/
function finalizeERC20Withdrawal(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
bytes calldata _extraData
) external onlyOtherBridge {
emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _extraData);
finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData);
function l2TokenBridge() external view returns (address) {
return address(otherBridge);
}
/**
* @notice Initializer.
*
* @param _messenger Address of the L1CrossDomainMessenger.
*/
function initialize(address payable _messenger) public initializer {
__StandardBridge_init(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE));
}
/**
......
......@@ -16,40 +16,6 @@ import { Types } from "../libraries/Types.sol";
*/
// slither-disable-next-line locked-ether
contract L2OutputOracle is OwnableUpgradeable, Semver {
/**
* @notice Emitted when an output is proposed.
*
* @param outputRoot The output root.
* @param l1Timestamp The L1 timestamp when proposed.
* @param l2BlockNumber The L2 block number of the output root.
*/
event OutputProposed(
bytes32 indexed outputRoot,
uint256 indexed l1Timestamp,
uint256 indexed l2BlockNumber
);
/**
* @notice Emitted when an output is deleted.
*
* @param outputRoot The output root.
* @param l1Timestamp The L1 timestamp when proposed.
* @param l2BlockNumber The L2 block number of the output root.
*/
event OutputDeleted(
bytes32 indexed outputRoot,
uint256 indexed l1Timestamp,
uint256 indexed l2BlockNumber
);
/**
* @notice Emitted when the proposer address is changed.
*
* @param previousProposer The previous proposer address.
* @param newProposer The new proposer address.
*/
event ProposerChanged(address indexed previousProposer, address indexed newProposer);
/**
* @notice The interval in L2 blocks at which checkpoints must be submitted.
*/
......@@ -97,6 +63,40 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
*/
mapping(uint256 => Types.OutputProposal) internal l2Outputs;
/**
* @notice Emitted when an output is proposed.
*
* @param outputRoot The output root.
* @param l1Timestamp The L1 timestamp when proposed.
* @param l2BlockNumber The L2 block number of the output root.
*/
event OutputProposed(
bytes32 indexed outputRoot,
uint256 indexed l1Timestamp,
uint256 indexed l2BlockNumber
);
/**
* @notice Emitted when an output is deleted.
*
* @param outputRoot The output root.
* @param l1Timestamp The L1 timestamp when proposed.
* @param l2BlockNumber The L2 block number of the output root.
*/
event OutputDeleted(
bytes32 indexed outputRoot,
uint256 indexed l1Timestamp,
uint256 indexed l2BlockNumber
);
/**
* @notice Emitted when the proposer address is changed.
*
* @param previousProposer The previous proposer address.
* @param newProposer The new proposer address.
*/
event ProposerChanged(address indexed previousProposer, address indexed newProposer);
/**
* @notice Reverts if called by any account other than the proposer.
*/
......@@ -142,24 +142,31 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
}
/**
* @notice Initializer.
* @notice Deletes the most recent output. This is used to remove the most recent output in the
* event that an erreneous output is submitted. It can only be called by the contract's
* owner, not the proposer. Longer term, this should be replaced with a more robust
* mechanism which will allow deletion of proposals shown to be invalid by a fault
* proof.
*
* @param _genesisL2Output The initial L2 output of the L2 chain.
* @param _startingBlockNumber The timestamp to start L2 block at.
* @param _proposer The address of the proposer.
* @param _owner The address of the owner.
* @param _proposal Represents the output proposal to delete
*/
function initialize(
bytes32 _genesisL2Output,
uint256 _startingBlockNumber,
address _proposer,
address _owner
) public initializer {
l2Outputs[_startingBlockNumber] = Types.OutputProposal(_genesisL2Output, block.timestamp);
latestBlockNumber = _startingBlockNumber;
__Ownable_init();
changeProposer(_proposer);
_transferOwnership(_owner);
function deleteL2Output(Types.OutputProposal memory _proposal) external onlyOwner {
Types.OutputProposal memory outputToDelete = l2Outputs[latestBlockNumber];
require(
_proposal.outputRoot == outputToDelete.outputRoot,
"L2OutputOracle: output root to delete does not match the latest output proposal"
);
require(
_proposal.timestamp == outputToDelete.timestamp,
"L2OutputOracle: timestamp to delete does not match the latest output proposal"
);
emit OutputDeleted(outputToDelete.outputRoot, outputToDelete.timestamp, latestBlockNumber);
delete l2Outputs[latestBlockNumber];
latestBlockNumber = latestBlockNumber - SUBMISSION_INTERVAL;
}
/**
......@@ -214,41 +221,6 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
emit OutputProposed(_outputRoot, block.timestamp, _l2BlockNumber);
}
/**
* @notice Deletes the most recent output. This is used to remove the most recent output in the
* event that an erreneous output is submitted. It can only be called by the contract's
* owner, not the proposer. Longer term, this should be replaced with a more robust
* mechanism which will allow deletion of proposals shown to be invalid by a fault
* proof.
*
* @param _proposal Represents the output proposal to delete
*/
function deleteL2Output(Types.OutputProposal memory _proposal) external onlyOwner {
Types.OutputProposal memory outputToDelete = l2Outputs[latestBlockNumber];
require(
_proposal.outputRoot == outputToDelete.outputRoot,
"L2OutputOracle: output root to delete does not match the latest output proposal"
);
require(
_proposal.timestamp == outputToDelete.timestamp,
"L2OutputOracle: timestamp to delete does not match the latest output proposal"
);
emit OutputDeleted(outputToDelete.outputRoot, outputToDelete.timestamp, latestBlockNumber);
delete l2Outputs[latestBlockNumber];
latestBlockNumber = latestBlockNumber - SUBMISSION_INTERVAL;
}
/**
* @notice Computes the block number of the next L2 block that needs to be checkpointed.
*/
function nextBlockNumber() public view returns (uint256) {
return latestBlockNumber + SUBMISSION_INTERVAL;
}
/**
* @notice Returns the L2 output proposal associated with a target L2 block number. If the
* L2 block number provided is between checkpoints, this function will rerutn the next
......@@ -286,18 +258,24 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
}
/**
* @notice Returns the L2 timestamp corresponding to a given L2 block number.
* Returns a null output proposal if none is found.
* @notice Initializer.
*
* @param _l2BlockNumber The L2 block number of the target block.
* @param _genesisL2Output The initial L2 output of the L2 chain.
* @param _startingBlockNumber The timestamp to start L2 block at.
* @param _proposer The address of the proposer.
* @param _owner The address of the owner.
*/
function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {
require(
_l2BlockNumber >= STARTING_BLOCK_NUMBER,
"L2OutputOracle: block number must be greater than or equal to starting block number"
);
return STARTING_TIMESTAMP + ((_l2BlockNumber - STARTING_BLOCK_NUMBER) * L2_BLOCK_TIME);
function initialize(
bytes32 _genesisL2Output,
uint256 _startingBlockNumber,
address _proposer,
address _owner
) public initializer {
l2Outputs[_startingBlockNumber] = Types.OutputProposal(_genesisL2Output, block.timestamp);
latestBlockNumber = _startingBlockNumber;
__Ownable_init();
changeProposer(_proposer);
_transferOwnership(_owner);
}
/**
......@@ -318,4 +296,26 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
emit ProposerChanged(proposer, _newProposer);
proposer = _newProposer;
}
/**
* @notice Computes the block number of the next L2 block that needs to be checkpointed.
*/
function nextBlockNumber() public view returns (uint256) {
return latestBlockNumber + SUBMISSION_INTERVAL;
}
/**
* @notice Returns the L2 timestamp corresponding to a given L2 block number.
* Returns a null output proposal if none is found.
*
* @param _l2BlockNumber The L2 block number of the target block.
*/
function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {
require(
_l2BlockNumber >= STARTING_BLOCK_NUMBER,
"L2OutputOracle: block number must be greater than or equal to starting block number"
);
return STARTING_TIMESTAMP + ((_l2BlockNumber - STARTING_BLOCK_NUMBER) * L2_BLOCK_TIME);
}
}
......@@ -24,30 +24,6 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
*/
uint256 internal constant DEPOSIT_VERSION = 0;
/**
* @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.
*
* @param from Address that triggered the deposit transaction.
* @param to Address that the deposit transaction is directed to.
* @param version Version of this deposit transaction event.
* @param opaqueData ABI encoded deposit data to be parsed off-chain.
*/
event TransactionDeposited(
address indexed from,
address indexed to,
uint256 indexed version,
bytes opaqueData
);
/**
* @notice Emitted when a withdrawal transaction is finalized.
*
* @param withdrawalHash Hash of the withdrawal transaction.
* @param success Whether the withdrawal transaction was successful.
*/
event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);
/**
* @notice Value used to reset the l2Sender, this is more efficient than setting it to zero.
*/
......@@ -92,6 +68,30 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
*/
uint256[48] private __gap;
/**
* @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.
*
* @param from Address that triggered the deposit transaction.
* @param to Address that the deposit transaction is directed to.
* @param version Version of this deposit transaction event.
* @param opaqueData ABI encoded deposit data to be parsed off-chain.
*/
event TransactionDeposited(
address indexed from,
address indexed to,
uint256 indexed version,
bytes opaqueData
);
/**
* @notice Emitted when a withdrawal transaction is finalized.
*
* @param withdrawalHash Hash of the withdrawal transaction.
* @param success Whether the withdrawal transaction was successful.
*/
event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);
/**
* @custom:semver 0.0.1
*
......@@ -104,14 +104,6 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
initialize();
}
/**
* @notice Initializer;
*/
function initialize() public initializer {
l2Sender = DEFAULT_L2_SENDER;
__ResourceMetering_init();
}
/**
* @notice Accepts value so that users can send ETH directly to this contract and have the
* funds be deposited to their address on L2. This is intended as a convenience
......@@ -122,77 +114,6 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(""));
}
/**
* @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in
* deriving deposit transactions. Note that if a deposit is made by a contract, its
* address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider
* using the CrossDomainMessenger contracts for a simpler developer experience.
*
* @param _to Target address on L2.
* @param _value ETH value to send to the recipient.
* @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value).
* @param _isCreation Whether or not the transaction is a contract creation.
* @param _data Data to trigger the recipient with.
*/
function depositTransaction(
address _to,
uint256 _value,
uint64 _gasLimit,
bool _isCreation,
bytes memory _data
) public payable metered(_gasLimit) {
// Just to be safe, make sure that people specify address(0) as the target when doing
// contract creations.
if (_isCreation) {
require(
_to == address(0),
"OptimismPortal: must send to address(0) when creating a contract"
);
}
// Transform the from-address to its alias if the caller is a contract.
address from = msg.sender;
if (msg.sender != tx.origin) {
from = AddressAliasHelper.applyL1ToL2Alias(msg.sender);
}
bytes memory opaqueData = abi.encodePacked(
msg.value,
_value,
_gasLimit,
_isCreation,
_data
);
// Emit a TransactionDeposited event so that the rollup node can derive a deposit
// transaction for this deposit.
emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);
}
/**
* @notice Determine if a given block number is finalized. Reverts if the call to
* L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.
*
* @param _l2BlockNumber The number of the L2 block.
*/
function isBlockFinalized(uint256 _l2BlockNumber) external view returns (bool) {
Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber);
return _isOutputFinalized(proposal);
}
/**
* @notice Determine if an L2 Output is finalized.
*
* @param _proposal The output proposal to check.
*/
function _isOutputFinalized(Types.OutputProposal memory _proposal)
internal
view
returns (bool)
{
return block.timestamp > _proposal.timestamp + FINALIZATION_PERIOD_SECONDS;
}
/**
* @notice Finalizes a withdrawal transaction.
*
......@@ -291,6 +212,85 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
emit WithdrawalFinalized(withdrawalHash, success);
}
/**
* @notice Determine if a given block number is finalized. Reverts if the call to
* L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.
*
* @param _l2BlockNumber The number of the L2 block.
*/
function isBlockFinalized(uint256 _l2BlockNumber) external view returns (bool) {
Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber);
return _isOutputFinalized(proposal);
}
/**
* @notice Initializer;
*/
function initialize() public initializer {
l2Sender = DEFAULT_L2_SENDER;
__ResourceMetering_init();
}
/**
* @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in
* deriving deposit transactions. Note that if a deposit is made by a contract, its
* address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider
* using the CrossDomainMessenger contracts for a simpler developer experience.
*
* @param _to Target address on L2.
* @param _value ETH value to send to the recipient.
* @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value).
* @param _isCreation Whether or not the transaction is a contract creation.
* @param _data Data to trigger the recipient with.
*/
function depositTransaction(
address _to,
uint256 _value,
uint64 _gasLimit,
bool _isCreation,
bytes memory _data
) public payable metered(_gasLimit) {
// Just to be safe, make sure that people specify address(0) as the target when doing
// contract creations.
if (_isCreation) {
require(
_to == address(0),
"OptimismPortal: must send to address(0) when creating a contract"
);
}
// Transform the from-address to its alias if the caller is a contract.
address from = msg.sender;
if (msg.sender != tx.origin) {
from = AddressAliasHelper.applyL1ToL2Alias(msg.sender);
}
bytes memory opaqueData = abi.encodePacked(
msg.value,
_value,
_gasLimit,
_isCreation,
_data
);
// Emit a TransactionDeposited event so that the rollup node can derive a deposit
// transaction for this deposit.
emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);
}
/**
* @notice Determine if an L2 Output is finalized.
*
* @param _proposal The output proposal to check.
*/
function _isOutputFinalized(Types.OutputProposal memory _proposal)
internal
view
returns (bool)
{
return block.timestamp > _proposal.timestamp + FINALIZATION_PERIOD_SECONDS;
}
/**
* @notice Verifies a Merkle Trie inclusion proof that a given withdrawal hash is present in
* the storage of the L2ToL1MessagePasser contract.
......
......@@ -63,19 +63,6 @@ abstract contract ResourceMetering is Initializable {
*/
uint256[49] private __gap;
/**
* @notice Sets initial resource parameter values. This function must either be called by the
* initializer function of an upgradeable child contract.
*/
// solhint-disable-next-line func-name-mixedcase
function __ResourceMetering_init() internal onlyInitializing {
params = ResourceParams({
prevBaseFee: INITIAL_BASE_FEE,
prevBoughtGas: 0,
prevBlockNum: uint64(block.number)
});
}
/**
* @notice Meters access to a function based an amount of a requested resource.
*
......@@ -164,4 +151,17 @@ abstract contract ResourceMetering is Initializable {
Burn.gas(gasCost - usedGas);
}
}
/**
* @notice Sets initial resource parameter values. This function must either be called by the
* initializer function of an upgradeable child contract.
*/
// solhint-disable-next-line func-name-mixedcase
function __ResourceMetering_init() internal onlyInitializing {
params = ResourceParams({
prevBaseFee: INITIAL_BASE_FEE,
prevBoughtGas: 0,
prevBlockNum: uint64(block.number)
});
}
}
......@@ -44,15 +44,6 @@ contract GasPriceOracle is Ownable, Semver {
*/
uint256 public decimals;
/**
* @custom:semver 0.0.1
*
* @param _owner Address that will initially own this contract.
*/
constructor(address _owner) Ownable() Semver(0, 0, 1) {
transferOwnership(_owner);
}
/**
* @notice Emitted when the overhead value is updated.
*/
......@@ -69,30 +60,12 @@ contract GasPriceOracle is Ownable, Semver {
event DecimalsUpdated(uint256 decimals);
/**
* @notice Retrieves the current gas price (base fee).
*
* @return Current L2 gas price (base fee).
*/
function gasPrice() public view returns (uint256) {
return block.basefee;
}
/**
* @notice Retrieves the current base fee.
*
* @return Current L2 base fee.
*/
function baseFee() public view returns (uint256) {
return block.basefee;
}
/**
* @notice Retrieves the latest known L1 base fee.
* @custom:semver 0.0.1
*
* @return Latest known L1 base fee.
* @param _owner Address that will initially own this contract.
*/
function l1BaseFee() public view returns (uint256) {
return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();
constructor(address _owner) Ownable() Semver(0, 0, 1) {
transferOwnership(_owner);
}
/**
......@@ -142,6 +115,33 @@ contract GasPriceOracle is Ownable, Semver {
return scaled;
}
/**
* @notice Retrieves the current gas price (base fee).
*
* @return Current L2 gas price (base fee).
*/
function gasPrice() public view returns (uint256) {
return block.basefee;
}
/**
* @notice Retrieves the current base fee.
*
* @return Current L2 base fee.
*/
function baseFee() public view returns (uint256) {
return block.basefee;
}
/**
* @notice Retrieves the latest known L1 base fee.
*
* @return Latest known L1 base fee.
*/
function l1BaseFee() public view returns (uint256) {
return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();
}
/**
* @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which
* represents the per-transaction gas overhead of posting the transaction and state
......
......@@ -47,15 +47,6 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver {
return otherMessenger;
}
/**
* @notice Checks that the message sender is the L1CrossDomainMessenger on L1.
*
* @return True if the message sender is the L1CrossDomainMessenger on L1.
*/
function _isOtherMessenger() internal view override returns (bool) {
return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == otherMessenger;
}
/**
* @notice Sends a message from L2 to L1.
*
......@@ -74,4 +65,13 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver {
value: _value
}(_to, _gasLimit, _data);
}
/**
* @notice Checks that the message sender is the L1CrossDomainMessenger on L1.
*
* @return True if the message sender is the L1CrossDomainMessenger on L1.
*/
function _isOtherMessenger() internal view override returns (bool) {
return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == otherMessenger;
}
}
......@@ -87,15 +87,6 @@ contract L2StandardBridge is StandardBridge, Semver {
initialize(_otherBridge);
}
/**
* @notice Initializer.
*
* @param _otherBridge Address of the L1StandardBridge.
*/
function initialize(address payable _otherBridge) public initializer {
__StandardBridge_init(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge);
}
/**
* @custom:legacy
* @notice Initiates a withdrawal from L2 to L1.
......@@ -165,6 +156,15 @@ contract L2StandardBridge is StandardBridge, Semver {
emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _extraData);
}
/**
* @notice Initializer.
*
* @param _otherBridge Address of the L1StandardBridge.
*/
function initialize(address payable _otherBridge) public initializer {
__StandardBridge_init(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge);
}
/**
* @custom:legacy
* @notice Internal function to a withdrawal from L2 to L1 to a target account on L1.
......
......@@ -15,6 +15,21 @@ import { Semver } from "../universal/Semver.sol";
* of the L2 output to reduce the cost of proving the existence of sent messages.
*/
contract L2ToL1MessagePasser is Semver {
/**
* @notice The L1 gas limit set when eth is withdrawn using the receive() function.
*/
uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;
/**
* @notice Includes the message hashes for all withdrawals
*/
mapping(bytes32 => bool) public sentMessages;
/**
* @notice A unique value hashed with each withdrawal.
*/
uint256 public nonce;
/**
* @notice Emitted any time a withdrawal is initiated.
*
......@@ -41,21 +56,6 @@ contract L2ToL1MessagePasser is Semver {
*/
event WithdrawerBalanceBurnt(uint256 indexed amount);
/**
* @notice The L1 gas limit set when eth is withdrawn using the receive() function.
*/
uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;
/**
* @notice Includes the message hashes for all withdrawals
*/
mapping(bytes32 => bool) public sentMessages;
/**
* @notice A unique value hashed with each withdrawal.
*/
uint256 public nonce;
/**
* @custom:semver 0.0.1
*/
......@@ -68,6 +68,18 @@ contract L2ToL1MessagePasser is Semver {
initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(""));
}
/**
* @notice Removes all ETH held by this contract from the state. Used to prevent the amount of
* ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to
* create a contract and self-destruct it to itself. Anyone can call this function. Not
* incentivized since this function is very cheap.
*/
function burn() external {
uint256 balance = address(this).balance;
Burn.eth(balance);
emit WithdrawerBalanceBurnt(balance);
}
/**
* @notice Sends a message from L2 to L1.
*
......@@ -98,16 +110,4 @@ contract L2ToL1MessagePasser is Semver {
++nonce;
}
}
/**
* @notice Removes all ETH held by this contract from the state. Used to prevent the amount of
* ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to
* create a contract and self-destruct it to itself. Anyone can call this function. Not
* incentivized since this function is very cheap.
*/
function burn() external {
uint256 balance = address(this).balance;
Burn.eth(balance);
emit WithdrawerBalanceBurnt(balance);
}
}
......@@ -12,6 +12,11 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
* with several older contracts.
*/
contract AddressManager is Ownable {
/**
* @notice Mapping of the hashes of string names to addresses.
*/
mapping(bytes32 => address) private addresses;
/**
* @notice Emitted when an address is modified in the registry.
*
......@@ -21,11 +26,6 @@ contract AddressManager is Ownable {
*/
event AddressSet(string indexed name, address newAddress, address oldAddress);
/**
* @notice Mapping of the hashes of string names to addresses.
*/
mapping(bytes32 => address) private addresses;
/**
* @notice Changes the address associated with a particular name.
*
......
......@@ -15,6 +15,17 @@ import { Semver } from "../universal/Semver.sol";
* system and could, in theory, be removed entirely.
*/
contract DeployerWhitelist is Semver {
/**
* @notice Address of the owner of this contract. Note that when this address is set to
* address(0), the whitelist is disabled.
*/
address public owner;
/**
* @notice Mapping of deployer addresses to boolean whitelist status.
*/
mapping(address => bool) public whitelist;
/**
* @notice Emitted when the owner of this contract changes.
*
......@@ -38,22 +49,6 @@ contract DeployerWhitelist is Semver {
*/
event WhitelistDisabled(address oldOwner);
/**
* @notice Address of the owner of this contract. Note that when this address is set to
* address(0), the whitelist is disabled.
*/
address public owner;
/**
* @notice Mapping of deployer addresses to boolean whitelist status.
*/
mapping(address => bool) public whitelist;
/**
* @custom:semver 0.0.1
*/
constructor() Semver(0, 0, 1) {}
/**
* @notice Blocks functions to anyone except the contract owner.
*/
......@@ -65,6 +60,11 @@ contract DeployerWhitelist is Semver {
_;
}
/**
* @custom:semver 0.0.1
*/
constructor() Semver(0, 0, 1) {}
/**
* @notice Adds or removes an address from the deployment whitelist.
*
......
......@@ -40,13 +40,6 @@ contract L1ChugSplashProxy {
bytes32 internal constant OWNER_KEY =
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @param _owner Address of the initial contract owner.
*/
constructor(address _owner) {
_setOwner(_owner);
}
/**
* @notice Blocks a function from being called when the parent signals that the system should
* be paused via an isUpgrading function.
......@@ -100,14 +93,21 @@ contract L1ChugSplashProxy {
}
}
/**
* @param _owner Address of the initial contract owner.
*/
constructor(address _owner) {
_setOwner(_owner);
}
// slither-disable-next-line locked-ether
fallback() external payable {
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
// slither-disable-next-line locked-ether
receive() external payable {
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
......@@ -206,27 +206,57 @@ contract L1ChugSplashProxy {
}
/**
* @notice Queries the implementation address.
* @notice Changes the owner of the proxy contract.
*
* @return Implementation address.
* @param _owner New owner of the proxy contract.
*/
function _getImplementation() internal view returns (address) {
address implementation;
function _setOwner(address _owner) internal {
assembly {
implementation := sload(IMPLEMENTATION_KEY)
sstore(OWNER_KEY, _owner)
}
return implementation;
}
/**
* @notice Changes the owner of the proxy contract.
* @notice Performs the proxy call via a delegatecall.
*/
function _doProxyCall() internal onlyWhenNotPaused {
address implementation = _getImplementation();
require(implementation != address(0), "L1ChugSplashProxy: implementation is not set yet");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) {
revert(0x0, returndatasize())
}
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
/**
* @notice Queries the implementation address.
*
* @param _owner New owner of the proxy contract.
* @return Implementation address.
*/
function _setOwner(address _owner) internal {
function _getImplementation() internal view returns (address) {
address implementation;
assembly {
sstore(OWNER_KEY, _owner)
implementation := sload(IMPLEMENTATION_KEY)
}
return implementation;
}
/**
......@@ -256,34 +286,4 @@ contract L1ChugSplashProxy {
}
return codeHash;
}
/**
* @notice Performs the proxy call via a delegatecall.
*/
function _doProxyCall() internal onlyWhenNotPaused {
address implementation = _getImplementation();
require(implementation != address(0), "L1ChugSplashProxy: implementation is not set yet");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) {
revert(0x0, returndatasize())
}
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/**
* @title Burner
* @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to
* the contract from the circulating supply. Self-destructing is the only way to remove ETH
* from the circulating supply.
*/
contract Burner {
constructor() payable {
selfdestruct(payable(address(this)));
}
}
/**
* @title Burn
* @notice Utilities for burning stuff.
......@@ -40,3 +28,15 @@ library Burn {
}
}
}
/**
* @title Burner
* @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to
* the contract from the circulating supply. Self-destructing is the only way to remove ETH
* from the circulating supply.
*/
contract Burner {
constructor() payable {
selfdestruct(payable(address(this)));
}
}
......@@ -9,11 +9,6 @@ pragma solidity ^0.8.0;
* various tweaks to improve readability.
*/
library RLPReader {
/**
* @notice Max list length that this library will accept.
*/
uint256 internal constant MAX_LIST_LENGTH = 32;
/**
* @notice RLP item types.
*
......@@ -33,6 +28,11 @@ library RLPReader {
uint256 ptr;
}
/**
* @notice Max list length that this library will accept.
*/
uint256 internal constant MAX_LIST_LENGTH = 32;
/**
* @notice Converts bytes to a reference to memory position and length.
*
......
......@@ -27,37 +27,6 @@ abstract contract CrossDomainMessenger is
PausableUpgradeable,
ReentrancyGuardUpgradeable
{
/**
* @notice Emitted whenever a message is sent to the other chain.
*
* @param target Address of the recipient of the message.
* @param sender Address of the sender of the message.
* @param message Message to trigger the recipient address with.
* @param messageNonce Unique nonce attached to the message.
* @param gasLimit Minimum gas limit that the message can be executed with.
*/
event SentMessage(
address indexed target,
address sender,
bytes message,
uint256 messageNonce,
uint256 gasLimit
);
/**
* @notice Emitted whenever a message is successfully relayed on this chain.
*
* @param msgHash Hash of the message that was relayed.
*/
event RelayedMessage(bytes32 indexed msgHash);
/**
* @notice Emitted whenever a message fails to be relayed on this chain.
*
* @param msgHash Hash of the message that failed to be relayed.
*/
event FailedRelayedMessage(bytes32 indexed msgHash);
/**
* @notice Current message version identifier.
*/
......@@ -146,68 +115,50 @@ abstract contract CrossDomainMessenger is
mapping(address => bool) public blockedSystemAddresses;
/**
* @notice Allows the owner of this contract to temporarily pause message relaying. Backup
* security mechanism just in case. Owner should be the same as the upgrade wallet to
* maintain the security model of the system as a whole.
* @notice Emitted whenever a message is sent to the other chain.
*
* @param target Address of the recipient of the message.
* @param sender Address of the sender of the message.
* @param message Message to trigger the recipient address with.
* @param messageNonce Unique nonce attached to the message.
* @param gasLimit Minimum gas limit that the message can be executed with.
*/
function pause() external onlyOwner {
_pause();
}
event SentMessage(
address indexed target,
address sender,
bytes message,
uint256 messageNonce,
uint256 gasLimit
);
/**
* @notice Allows the owner of this contract to resume message relaying once paused.
* @notice Emitted whenever a message is successfully relayed on this chain.
*
* @param msgHash Hash of the message that was relayed.
*/
function unpause() external onlyOwner {
_unpause();
}
event RelayedMessage(bytes32 indexed msgHash);
/**
* @notice Retrieves the address of the contract or wallet that initiated the currently
* executing message on the other chain. Will throw an error if there is no message
* currently being executed. Allows the recipient of a call to see who triggered it.
* @notice Emitted whenever a message fails to be relayed on this chain.
*
* @return Address of the sender of the currently executing message on the other chain.
* @param msgHash Hash of the message that failed to be relayed.
*/
function xDomainMessageSender() external view returns (address) {
require(
xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,
"CrossDomainMessenger: xDomainMessageSender is not set"
);
return xDomainMsgSender;
}
event FailedRelayedMessage(bytes32 indexed msgHash);
/**
* @notice Retrieves the next message nonce. Message version will be added to the upper two
* bytes of the message nonce. Message version allows us to treat messages as having
* different structures.
*
* @return Nonce of the next message to be sent, with added message version.
* @notice Allows the owner of this contract to temporarily pause message relaying. Backup
* security mechanism just in case. Owner should be the same as the upgrade wallet to
* maintain the security model of the system as a whole.
*/
function messageNonce() public view returns (uint256) {
return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);
function pause() external onlyOwner {
_pause();
}
/**
* @notice Computes the amount of gas required to guarantee that a given message will be
* received on the other chain without running out of gas. Guaranteeing that a message
* will not run out of gas is important because this ensures that a message can always
* be replayed on the other chain if it fails to execute completely.
*
* @param _message Message to compute the amount of required gas for.
* @param _minGasLimit Minimum desired gas limit when message goes to target.
*
* @return Amount of gas required to guarantee message receipt.
* @notice Allows the owner of this contract to resume message relaying once paused.
*/
function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {
return
// Dynamic overhead
((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /
MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +
// Calldata overhead
(uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +
// Constant overhead
MIN_GAS_CONSTANT_OVERHEAD;
function unpause() external onlyOwner {
_unpause();
}
/**
......@@ -326,6 +277,55 @@ abstract contract CrossDomainMessenger is
}
}
/**
* @notice Retrieves the address of the contract or wallet that initiated the currently
* executing message on the other chain. Will throw an error if there is no message
* currently being executed. Allows the recipient of a call to see who triggered it.
*
* @return Address of the sender of the currently executing message on the other chain.
*/
function xDomainMessageSender() external view returns (address) {
require(
xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,
"CrossDomainMessenger: xDomainMessageSender is not set"
);
return xDomainMsgSender;
}
/**
* @notice Retrieves the next message nonce. Message version will be added to the upper two
* bytes of the message nonce. Message version allows us to treat messages as having
* different structures.
*
* @return Nonce of the next message to be sent, with added message version.
*/
function messageNonce() public view returns (uint256) {
return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);
}
/**
* @notice Computes the amount of gas required to guarantee that a given message will be
* received on the other chain without running out of gas. Guaranteeing that a message
* will not run out of gas is important because this ensures that a message can always
* be replayed on the other chain if it fails to execute completely.
*
* @param _message Message to compute the amount of required gas for.
* @param _minGasLimit Minimum desired gas limit when message goes to target.
*
* @return Amount of gas required to guarantee message receipt.
*/
function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {
return
// Dynamic overhead
((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /
MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +
// Calldata overhead
(uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +
// Constant overhead
MIN_GAS_CONSTANT_OVERHEAD;
}
/**
* @notice Intializer.
*
......@@ -354,13 +354,6 @@ abstract contract CrossDomainMessenger is
__ReentrancyGuard_init_unchained();
}
/**
* @notice Checks whether the message is coming from the other messenger. Implemented by child
* contracts because the logic for this depends on the network where the messenger is
* being deployed.
*/
function _isOtherMessenger() internal view virtual returns (bool);
/**
* @notice Sends a low-level message to the other messenger. Needs to be implemented by child
* contracts because the logic for this depends on the network where the messenger is
......@@ -372,4 +365,11 @@ abstract contract CrossDomainMessenger is
uint256 _value,
bytes memory _data
) internal virtual;
/**
* @notice Checks whether the message is coming from the other messenger. Implemented by child
* contracts because the logic for this depends on the network where the messenger is
* being deployed.
*/
function _isOtherMessenger() internal view virtual returns (bool);
}
......@@ -13,6 +13,16 @@ import "./SupportedInterfaces.sol";
* meant for use on L2.
*/
contract OptimismMintableERC20 is ERC20 {
/**
* @notice Address of the corresponding version of this token on the remote chain.
*/
address public remoteToken;
/**
* @notice Address of the StandardBridge on this network.
*/
address public bridge;
/**
* @notice Emitted whenever tokens are minted for an account.
*
......@@ -30,14 +40,12 @@ contract OptimismMintableERC20 is ERC20 {
event Burn(address indexed account, uint256 amount);
/**
* @notice Address of the corresponding version of this token on the remote chain.
*/
address public remoteToken;
/**
* @notice Address of the StandardBridge on this network.
* @notice A modifier that only allows the bridge to call
*/
address public bridge;
modifier onlyBridge() {
require(msg.sender == bridge, "OptimismMintableERC20: only bridge can mint and burn");
_;
}
/**
* @param _bridge Address of the L2 standard bridge.
......@@ -56,27 +64,25 @@ contract OptimismMintableERC20 is ERC20 {
}
/**
* @custom:legacy
* @notice Legacy getter for the remote token. Use remoteToken going forward.
*/
function l1Token() public view returns (address) {
return remoteToken;
}
/**
* @custom:legacy
* @notice Legacy getter for the bridge. Use bridge going forward.
* @notice Allows the StandardBridge on this network to mint tokens.
*
* @param _to Address to mint tokens to.
* @param _amount Amount of tokens to mint.
*/
function l2Bridge() public view returns (address) {
return bridge;
function mint(address _to, uint256 _amount) external virtual onlyBridge {
_mint(_to, _amount);
emit Mint(_to, _amount);
}
/**
* @notice A modifier that only allows the bridge to call
* @notice Allows the StandardBridge on this network to burn tokens.
*
* @param _from Address to burn tokens from.
* @param _amount Amount of tokens to burn.
*/
modifier onlyBridge() {
require(msg.sender == bridge, "OptimismMintableERC20: only bridge can mint and burn");
_;
function burn(address _from, uint256 _amount) external virtual onlyBridge {
_burn(_from, _amount);
emit Burn(_from, _amount);
}
/**
......@@ -94,24 +100,18 @@ contract OptimismMintableERC20 is ERC20 {
}
/**
* @notice Allows the StandardBridge on this network to mint tokens.
*
* @param _to Address to mint tokens to.
* @param _amount Amount of tokens to mint.
* @custom:legacy
* @notice Legacy getter for the remote token. Use remoteToken going forward.
*/
function mint(address _to, uint256 _amount) external virtual onlyBridge {
_mint(_to, _amount);
emit Mint(_to, _amount);
function l1Token() public view returns (address) {
return remoteToken;
}
/**
* @notice Allows the StandardBridge on this network to burn tokens.
*
* @param _from Address to burn tokens from.
* @param _amount Amount of tokens to burn.
* @custom:legacy
* @notice Legacy getter for the bridge. Use bridge going forward.
*/
function burn(address _from, uint256 _amount) external virtual onlyBridge {
_burn(_from, _amount);
emit Burn(_from, _amount);
function l2Bridge() public view returns (address) {
return bridge;
}
}
......@@ -14,6 +14,11 @@ import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol";
* compatible with the older StandardL2ERC20Factory contract.
*/
contract OptimismMintableERC20Factory {
/**
* @notice Address of the StandardBridge on this chain.
*/
address public immutable bridge;
/**
* @custom:legacy
* @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer
......@@ -37,11 +42,6 @@ contract OptimismMintableERC20Factory {
address deployer
);
/**
* @notice Address of the StandardBridge on this chain.
*/
address public immutable bridge;
/**
* @param _bridge Address of the StandardBridge on this chain.
*/
......
......@@ -8,6 +8,20 @@ pragma solidity 0.8.15;
* simulation.
*/
contract Proxy {
/**
* @notice The storage slot that holds the address of the implementation.
* bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
*/
bytes32 internal constant IMPLEMENTATION_KEY =
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @notice The storage slot that holds the address of the owner.
* bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
*/
bytes32 internal constant OWNER_KEY =
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
......@@ -26,18 +40,19 @@ contract Proxy {
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @notice The storage slot that holds the address of the implementation.
* bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
*/
bytes32 internal constant IMPLEMENTATION_KEY =
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @notice The storage slot that holds the address of the owner.
* bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
* @notice A modifier that reverts if not called by the owner or by address(0) to allow
* eth_call to interact with this proxy without needing to use low-level storage
* inspection. We assume that nobody is able to trigger calls from address(0) during
* normal EVM execution.
*/
bytes32 internal constant OWNER_KEY =
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
/**
* @notice Sets the initial admin during contract deployment. Admin address is stored at the
......@@ -52,32 +67,17 @@ contract Proxy {
}
// slither-disable-next-line locked-ether
fallback() external payable {
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
// slither-disable-next-line locked-ether
receive() external payable {
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
/**
* @notice A modifier that reverts if not called by the owner or by address(0) to allow
* eth_call to interact with this proxy without needing to use low-level storage
* inspection. We assume that nobody is able to trigger calls from address(0) during
* normal EVM execution.
*/
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
/**
* @notice Set the implementation contract address. The code at the given address will execute
* when this contract is called.
......@@ -146,19 +146,6 @@ contract Proxy {
emit Upgraded(_implementation);
}
/**
* @notice Queries the implementation address.
*
* @return Implementation address.
*/
function _getImplementation() internal view returns (address) {
address impl;
assembly {
impl := sload(IMPLEMENTATION_KEY)
}
return impl;
}
/**
* @notice Changes the owner of the proxy contract.
*
......@@ -172,19 +159,6 @@ contract Proxy {
emit AdminChanged(previous, _admin);
}
/**
* @notice Queries the owner of the proxy contract.
*
* @return Owner address.
*/
function _getAdmin() internal view returns (address) {
address owner;
assembly {
owner := sload(OWNER_KEY)
}
return owner;
}
/**
* @notice Performs the proxy call via a delegatecall.
*/
......@@ -213,4 +187,30 @@ contract Proxy {
return(0x0, returndatasize())
}
}
/**
* @notice Queries the implementation address.
*
* @return Implementation address.
*/
function _getImplementation() internal view returns (address) {
address impl;
assembly {
impl := sload(IMPLEMENTATION_KEY)
}
return impl;
}
/**
* @notice Queries the owner of the proxy contract.
*
* @return Owner address.
*/
function _getAdmin() internal view returns (address) {
address owner;
assembly {
owner := sload(OWNER_KEY)
}
return owner;
}
}
......@@ -125,24 +125,67 @@ contract ProxyAdmin is Owned {
/**
* @custom:legacy
* @notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.
* @notice Set the upgrading status for the Chugsplash proxy type.
*
* @return Whether or not there is an upgrade going on. May not actually tell you whether an
* upgrade is going on, since we don't currently plan to use this variable for anything
* other than a legacy indicator to fix a UX bug in the ChugSplash proxy.
* @param _upgrading Whether or not the system is upgrading.
*/
function isUpgrading() external view returns (bool) {
return upgrading;
function setUpgrading(bool _upgrading) external onlyOwner {
upgrading = _upgrading;
}
/**
* @notice Updates the admin of the given proxy address.
*
* @param _proxy Address of the proxy to update.
* @param _newAdmin Address of the new proxy admin.
*/
function changeProxyAdmin(address payable _proxy, address _newAdmin) external onlyOwner {
ProxyType ptype = proxyType[_proxy];
if (ptype == ProxyType.ERC1967) {
Proxy(_proxy).changeAdmin(_newAdmin);
} else if (ptype == ProxyType.CHUGSPLASH) {
L1ChugSplashProxy(_proxy).setOwner(_newAdmin);
} else if (ptype == ProxyType.RESOLVED) {
addressManager.transferOwnership(_newAdmin);
} else {
revert("ProxyAdmin: unknown proxy type");
}
}
/**
* @notice Changes a proxy's implementation contract and delegatecalls the new implementation
* with some given data. Useful for atomic upgrade-and-initialize calls.
*
* @param _proxy Address of the proxy to upgrade.
* @param _implementation Address of the new implementation address.
* @param _data Data to trigger the new implementation with.
*/
function upgradeAndCall(
address payable _proxy,
address _implementation,
bytes memory _data
) external payable onlyOwner {
ProxyType ptype = proxyType[_proxy];
if (ptype == ProxyType.ERC1967) {
Proxy(_proxy).upgradeToAndCall{ value: msg.value }(_implementation, _data);
} else {
// reverts if proxy type is unknown
upgrade(_proxy, _implementation);
(bool success, ) = _proxy.call{ value: msg.value }(_data);
require(success, "ProxyAdmin: call to proxy after upgrade failed");
}
}
/**
* @custom:legacy
* @notice Set the upgrading status for the Chugsplash proxy type.
* @notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.
*
* @param _upgrading Whether or not the system is upgrading.
* @return Whether or not there is an upgrade going on. May not actually tell you whether an
* upgrade is going on, since we don't currently plan to use this variable for anything
* other than a legacy indicator to fix a UX bug in the ChugSplash proxy.
*/
function setUpgrading(bool _upgrading) external onlyOwner {
upgrading = _upgrading;
function isUpgrading() external view returns (bool) {
return upgrading;
}
/**
......@@ -185,25 +228,6 @@ contract ProxyAdmin is Owned {
}
}
/**
* @notice Updates the admin of the given proxy address.
*
* @param _proxy Address of the proxy to update.
* @param _newAdmin Address of the new proxy admin.
*/
function changeProxyAdmin(address payable _proxy, address _newAdmin) external onlyOwner {
ProxyType ptype = proxyType[_proxy];
if (ptype == ProxyType.ERC1967) {
Proxy(_proxy).changeAdmin(_newAdmin);
} else if (ptype == ProxyType.CHUGSPLASH) {
L1ChugSplashProxy(_proxy).setOwner(_newAdmin);
} else if (ptype == ProxyType.RESOLVED) {
addressManager.transferOwnership(_newAdmin);
} else {
revert("ProxyAdmin: unknown proxy type");
}
}
/**
* @notice Changes a proxy's implementation contract.
*
......@@ -226,28 +250,4 @@ contract ProxyAdmin is Owned {
revert("ProxyAdmin: unknown proxy type");
}
}
/**
* @notice Changes a proxy's implementation contract and delegatecalls the new implementation
* with some given data. Useful for atomic upgrade-and-initialize calls.
*
* @param _proxy Address of the proxy to upgrade.
* @param _implementation Address of the new implementation address.
* @param _data Data to trigger the new implementation with.
*/
function upgradeAndCall(
address payable _proxy,
address _implementation,
bytes memory _data
) external payable onlyOwner {
ProxyType ptype = proxyType[_proxy];
if (ptype == ProxyType.ERC1967) {
Proxy(_proxy).upgradeToAndCall{ value: msg.value }(_implementation, _data);
} else {
// reverts if proxy type is unknown
upgrade(_proxy, _implementation);
(bool success, ) = _proxy.call{ value: msg.value }(_data);
require(success, "ProxyAdmin: call to proxy after upgrade failed");
}
}
}
......@@ -17,6 +17,26 @@ import { OptimismMintableERC20 } from "./OptimismMintableERC20.sol";
abstract contract StandardBridge is Initializable {
using SafeERC20 for IERC20;
/**
* @notice The L2 gas limit set when eth is depoisited using the receive() function.
*/
uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;
/**
* @notice Messenger contract on this domain.
*/
CrossDomainMessenger public messenger;
/**
* @notice Corresponding bridge on the other domain.
*/
StandardBridge public otherBridge;
/**
* @notice Mapping that stores deposits for a given pair of local and remote tokens.
*/
mapping(address => mapping(address => uint256)) public deposits;
/**
* @notice Emitted when an ETH bridge is initiated to the other chain.
*
......@@ -104,26 +124,6 @@ abstract contract StandardBridge is Initializable {
bytes extraData
);
/**
* @notice The L2 gas limit set when eth is depoisited using the receive() function.
*/
uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;
/**
* @notice Messenger contract on this domain.
*/
CrossDomainMessenger public messenger;
/**
* @notice Corresponding bridge on the other domain.
*/
StandardBridge public otherBridge;
/**
* @notice Mapping that stores deposits for a given pair of local and remote tokens.
*/
mapping(address => mapping(address => uint256)) public deposits;
/**
* @notice Only allow EOAs to call the functions. Note that this is not safe against contracts
* calling code within their constructors, but also doesn't really matter since we're
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment