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
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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;
}
}
60 changes: 30 additions & 30 deletions packages/contracts-bedrock/contracts/L1/L1StandardBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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));
}

/**
Expand Down
190 changes: 95 additions & 95 deletions packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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);
}
}
Loading