Commit 3a0271f8 authored by Kelvin Fichter's avatar Kelvin Fichter Committed by Mark Tyneway

feat(ctb): introduce Types.sol

Introduces a new library, Types.sol, meant to hold various different
structs that get used all over the place.
parent bad725d7
---
'@eth-optimism/contracts-bedrock': patch
---
Introduces Types.sol
This diff is collapsed.
This diff is collapsed.
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
// This file is a generated binding and any manual changes will be lost. // This file is a generated binding and any manual changes will be lost.
package bindings package bindings
var L2ToL1MessagePasserDeployedBin = "0x60806040526004361061005e5760003560e01c806382e3702d1161004357806382e3702d146100c7578063affed0e014610107578063c2b3e5ac1461012b57600080fd5b806344df8e701461008757806354fd4d501461009c57600080fd5b366100825761008033620186a060405180602001604052806000815250610139565b005b600080fd5b34801561009357600080fd5b506100806101ef565b3480156100a857600080fd5b506100b1610227565b6040516100be91906104fb565b60405180910390f35b3480156100d357600080fd5b506100f76100e2366004610515565b60006020819052908152604090205460ff1681565b60405190151581526020016100be565b34801561011357600080fd5b5061011d60015481565b6040519081526020016100be565b61008061013936600461055d565b600061014b60015433863487876102ca565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136906101d990349089908990610661565b60405180910390a4505060018054810190555050565b476101f981610309565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60606102527f0000000000000000000000000000000000000000000000000000000000000000610338565b61027b7f0000000000000000000000000000000000000000000000000000000000000000610338565b6102a47f0000000000000000000000000000000000000000000000000000000000000000610338565b6040516020016102b693929190610689565b604051602081830303815290604052905090565b60008686868686866040516020016102e7969594939291906106ff565b6040516020818303038152906040528051906020012090509695505050505050565b8060405161031690610475565b6040518091039082f0905080158015610333573d6000803e3d6000fd5b505050565b60608160000361037b57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156103a5578061038f81610785565b915061039e9050600a836107ec565b915061037f565b60008167ffffffffffffffff8111156103c0576103c061052e565b6040519080825280601f01601f1916602001820160405280156103ea576020820181803683370190505b5090505b841561046d576103ff600183610800565b915061040c600a86610817565b61041790603061082b565b60f81b81838151811061042c5761042c610843565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610466600a866107ec565b94506103ee565b949350505050565b60088061087383390190565b60005b8381101561049c578181015183820152602001610484565b838111156104ab576000848401525b50505050565b600081518084526104c9816020860160208601610481565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061050e60208301846104b1565b9392505050565b60006020828403121561052757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561057257600080fd5b833573ffffffffffffffffffffffffffffffffffffffff8116811461059657600080fd5b925060208401359150604084013567ffffffffffffffff808211156105ba57600080fd5b818601915086601f8301126105ce57600080fd5b8135818111156105e0576105e061052e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156106265761062661052e565b8160405282815289602084870101111561063f57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b83815282602082015260606040820152600061068060608301846104b1565b95945050505050565b6000845161069b818460208901610481565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516106d7816001850160208a01610481565b600192019182015283516106f2816002840160208801610481565b0160020195945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261074a60c08301846104b1565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036107b6576107b6610756565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826107fb576107fb6107bd565b500490565b60008282101561081257610812610756565b500390565b600082610826576108266107bd565b500690565b6000821982111561083e5761083e610756565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405230fffea164736f6c634300080f000a" var L2ToL1MessagePasserDeployedBin = "0x60806040526004361061005e5760003560e01c806382e3702d1161004357806382e3702d146100c7578063affed0e014610107578063c2b3e5ac1461012b57600080fd5b806344df8e701461008757806354fd4d501461009c57600080fd5b366100825761008033620186a060405180602001604052806000815250610139565b005b600080fd5b34801561009357600080fd5b50610080610242565b3480156100a857600080fd5b506100b161027a565b6040516100be919061055c565b60405180910390f35b3480156100d357600080fd5b506100f76100e2366004610576565b60006020819052908152604090205460ff1681565b60405190151581526020016100be565b34801561011357600080fd5b5061011d60015481565b6040519081526020016100be565b6100806101393660046105be565b600061019e6040518060c0016040528060015481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020013481526020018581526020018481525061031d565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a61369061022c903490899089906106c2565b60405180910390a4505060018054810190555050565b4761024c8161036a565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60606102a57f0000000000000000000000000000000000000000000000000000000000000000610399565b6102ce7f0000000000000000000000000000000000000000000000000000000000000000610399565b6102f77f0000000000000000000000000000000000000000000000000000000000000000610399565b604051602001610309939291906106ea565b604051602081830303815290604052905090565b80516020808301516040808501516060860151608087015160a0880151935160009761034d979096959101610760565b604051602081830303815290604052805190602001209050919050565b80604051610377906104d6565b6040518091039082f0905080158015610394573d6000803e3d6000fd5b505050565b6060816000036103dc57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561040657806103f0816107e6565b91506103ff9050600a8361084d565b91506103e0565b60008167ffffffffffffffff8111156104215761042161058f565b6040519080825280601f01601f19166020018201604052801561044b576020820181803683370190505b5090505b84156104ce57610460600183610861565b915061046d600a86610878565b61047890603061088c565b60f81b81838151811061048d5761048d6108a4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104c7600a8661084d565b945061044f565b949350505050565b6008806108d483390190565b60005b838110156104fd5781810151838201526020016104e5565b8381111561050c576000848401525b50505050565b6000815180845261052a8160208601602086016104e2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061056f6020830184610512565b9392505050565b60006020828403121561058857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156105d357600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146105f757600080fd5b925060208401359150604084013567ffffffffffffffff8082111561061b57600080fd5b818601915086601f83011261062f57600080fd5b8135818111156106415761064161058f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156106875761068761058f565b816040528281528960208487010111156106a057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b8381528260208201526060604082015260006106e16060830184610512565b95945050505050565b600084516106fc8184602089016104e2565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610738816001850160208a016104e2565b600192019182015283516107538160028401602088016104e2565b0160020195945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526107ab60c0830184610512565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610817576108176107b7565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261085c5761085c61081e565b500490565b600082821015610873576108736107b7565b500390565b6000826108875761088761081e565b500690565b6000821982111561089f5761089f6107b7565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405230fffea164736f6c634300080f000a"
This diff is collapsed.
...@@ -899,12 +899,14 @@ func TestWithdrawals(t *testing.T) { ...@@ -899,12 +899,14 @@ func TestWithdrawals(t *testing.T) {
opts.Value = nil opts.Value = nil
tx, err = portal.FinalizeWithdrawalTransaction( tx, err = portal.FinalizeWithdrawalTransaction(
opts, opts,
params.Nonce, bindings.TypesWithdrawalTransaction{
params.Sender, Nonce: params.Nonce,
params.Target, Sender: params.Sender,
params.Value, Target: params.Target,
params.GasLimit, Value: params.Value,
params.Data, GasLimit: params.GasLimit,
Data: params.Data,
},
params.BlockNumber, params.BlockNumber,
params.OutputRootProof, params.OutputRootProof,
params.WithdrawalProof, params.WithdrawalProof,
......
...@@ -154,7 +154,7 @@ type FinalizedWithdrawalParameters struct { ...@@ -154,7 +154,7 @@ type FinalizedWithdrawalParameters struct {
GasLimit *big.Int GasLimit *big.Int
BlockNumber *big.Int BlockNumber *big.Int
Data []byte Data []byte
OutputRootProof bindings.HashingOutputRootProof OutputRootProof bindings.TypesOutputRootProof
WithdrawalProof []byte // RLP Encoded list of trie nodes to prove L2 storage WithdrawalProof []byte // RLP Encoded list of trie nodes to prove L2 storage
} }
...@@ -210,7 +210,7 @@ func FinalizeWithdrawalParameters(ctx context.Context, l2client ProofClient, txH ...@@ -210,7 +210,7 @@ func FinalizeWithdrawalParameters(ctx context.Context, l2client ProofClient, txH
GasLimit: ev.GasLimit, GasLimit: ev.GasLimit,
BlockNumber: new(big.Int).Set(header.Number), BlockNumber: new(big.Int).Set(header.Number),
Data: ev.Data, Data: ev.Data,
OutputRootProof: bindings.HashingOutputRootProof{ OutputRootProof: bindings.TypesOutputRootProof{
Version: [32]byte{}, // Empty for version 1 Version: [32]byte{}, // Empty for version 1
StateRoot: header.Root, StateRoot: header.Root,
WithdrawerStorageRoot: p.StorageHash, WithdrawerStorageRoot: p.StorageHash,
......
This diff is collapsed.
...@@ -5,6 +5,7 @@ import { ...@@ -5,6 +5,7 @@ import {
OwnableUpgradeable OwnableUpgradeable
} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Semver } from "../universal/Semver.sol"; import { Semver } from "../universal/Semver.sol";
import { Types } from "../libraries/Types.sol";
/** /**
* @custom:proxied * @custom:proxied
...@@ -15,17 +16,6 @@ import { Semver } from "../universal/Semver.sol"; ...@@ -15,17 +16,6 @@ import { Semver } from "../universal/Semver.sol";
*/ */
// slither-disable-next-line locked-ether // slither-disable-next-line locked-ether
contract L2OutputOracle is OwnableUpgradeable, Semver { contract L2OutputOracle is OwnableUpgradeable, Semver {
/**
* @notice OutputProposal represents a commitment to the L2 state.
* The timestamp is the L1 timestamp that the output root is posted.
* This timestamp is used to verify that the finalization period
* has passed since the output root was submitted.
*/
struct OutputProposal {
bytes32 outputRoot;
uint256 timestamp;
}
/** /**
* @notice Emitted when an output is proposed. * @notice Emitted when an output is proposed.
* *
...@@ -105,7 +95,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -105,7 +95,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
* outputs should not be considered finalized until the finalization period (as defined * outputs should not be considered finalized until the finalization period (as defined
* in the Optimism Portal) has passed. * in the Optimism Portal) has passed.
*/ */
mapping(uint256 => OutputProposal) internal l2Outputs; mapping(uint256 => Types.OutputProposal) internal l2Outputs;
/** /**
* @notice Reverts if called by any account other than the proposer. * @notice Reverts if called by any account other than the proposer.
...@@ -165,7 +155,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -165,7 +155,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
address _proposer, address _proposer,
address _owner address _owner
) public initializer { ) public initializer {
l2Outputs[_startingBlockNumber] = OutputProposal(_genesisL2Output, block.timestamp); l2Outputs[_startingBlockNumber] = Types.OutputProposal(_genesisL2Output, block.timestamp);
latestBlockNumber = _startingBlockNumber; latestBlockNumber = _startingBlockNumber;
__Ownable_init(); __Ownable_init();
changeProposer(_proposer); changeProposer(_proposer);
...@@ -218,7 +208,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -218,7 +208,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
); );
} }
l2Outputs[_l2BlockNumber] = OutputProposal(_outputRoot, block.timestamp); l2Outputs[_l2BlockNumber] = Types.OutputProposal(_outputRoot, block.timestamp);
latestBlockNumber = _l2BlockNumber; latestBlockNumber = _l2BlockNumber;
emit OutputProposed(_outputRoot, block.timestamp, _l2BlockNumber); emit OutputProposed(_outputRoot, block.timestamp, _l2BlockNumber);
...@@ -233,8 +223,8 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -233,8 +223,8 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
* *
* @param _proposal Represents the output proposal to delete * @param _proposal Represents the output proposal to delete
*/ */
function deleteL2Output(OutputProposal memory _proposal) external onlyOwner { function deleteL2Output(Types.OutputProposal memory _proposal) external onlyOwner {
OutputProposal memory outputToDelete = l2Outputs[latestBlockNumber]; Types.OutputProposal memory outputToDelete = l2Outputs[latestBlockNumber];
require( require(
_proposal.outputRoot == outputToDelete.outputRoot, _proposal.outputRoot == outputToDelete.outputRoot,
...@@ -268,7 +258,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -268,7 +258,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
* *
* @param _l2BlockNumber The L2 block number of the target block. * @param _l2BlockNumber The L2 block number of the target block.
*/ */
function getL2Output(uint256 _l2BlockNumber) external view returns (OutputProposal memory) { function getL2Output(uint256 _l2BlockNumber) external view returns (Types.OutputProposal memory) {
require( require(
_l2BlockNumber >= STARTING_BLOCK_NUMBER, _l2BlockNumber >= STARTING_BLOCK_NUMBER,
"L2OutputOracle: block number cannot be less than the starting block number." "L2OutputOracle: block number cannot be less than the starting block number."
...@@ -283,7 +273,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -283,7 +273,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
? _l2BlockNumber ? _l2BlockNumber
: _l2BlockNumber + (SUBMISSION_INTERVAL - offset); : _l2BlockNumber + (SUBMISSION_INTERVAL - offset);
OutputProposal memory output = l2Outputs[lookupBlockNumber]; Types.OutputProposal memory output = l2Outputs[lookupBlockNumber];
require( require(
output.outputRoot != bytes32(0), output.outputRoot != bytes32(0),
"L2OutputOracle: No output found for that block number." "L2OutputOracle: No output found for that block number."
......
...@@ -4,6 +4,7 @@ pragma solidity 0.8.15; ...@@ -4,6 +4,7 @@ pragma solidity 0.8.15;
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { ExcessivelySafeCall } from "excessively-safe-call/src/ExcessivelySafeCall.sol"; import { ExcessivelySafeCall } from "excessively-safe-call/src/ExcessivelySafeCall.sol";
import { L2OutputOracle } from "./L2OutputOracle.sol"; import { L2OutputOracle } from "./L2OutputOracle.sol";
import { Types } from "../libraries/Types.sol";
import { Hashing } from "../libraries/Hashing.sol"; import { Hashing } from "../libraries/Hashing.sol";
import { SecureMerkleTrie } from "../libraries/trie/SecureMerkleTrie.sol"; import { SecureMerkleTrie } from "../libraries/trie/SecureMerkleTrie.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
...@@ -175,8 +176,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -175,8 +176,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
* @param _l2BlockNumber The number of the L2 block. * @param _l2BlockNumber The number of the L2 block.
*/ */
function isBlockFinalized(uint256 _l2BlockNumber) external view returns (bool) { function isBlockFinalized(uint256 _l2BlockNumber) external view returns (bool) {
L2OutputOracle.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber); Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber);
return _isOutputFinalized(proposal); return _isOutputFinalized(proposal);
} }
...@@ -185,7 +185,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -185,7 +185,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
* *
* @param _proposal The output proposal to check. * @param _proposal The output proposal to check.
*/ */
function _isOutputFinalized(L2OutputOracle.OutputProposal memory _proposal) function _isOutputFinalized(Types.OutputProposal memory _proposal)
internal internal
view view
returns (bool) returns (bool)
...@@ -196,25 +196,15 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -196,25 +196,15 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
/** /**
* @notice Finalizes a withdrawal transaction. * @notice Finalizes a withdrawal transaction.
* *
* @param _nonce Nonce for the provided message. * @param _tx Withdrawal transaction to finalize.
* @param _sender Message sender address on L2.
* @param _target Target address on L1.
* @param _value ETH to send to the target.
* @param _gasLimit Minumum gas to be forwarded to the target.
* @param _data Data to send to the target.
* @param _l2BlockNumber L2 block number of the outputRoot. * @param _l2BlockNumber L2 block number of the outputRoot.
* @param _outputRootProof Inclusion proof of the withdrawer contracts storage root. * @param _outputRootProof Inclusion proof of the withdrawer contracts storage root.
* @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract. * @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract.
*/ */
function finalizeWithdrawalTransaction( function finalizeWithdrawalTransaction(
uint256 _nonce, Types.WithdrawalTransaction memory _tx,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes calldata _data,
uint256 _l2BlockNumber, uint256 _l2BlockNumber,
Hashing.OutputRootProof calldata _outputRootProof, Types.OutputRootProof calldata _outputRootProof,
bytes calldata _withdrawalProof bytes calldata _withdrawalProof
) external payable { ) external payable {
// Prevent nested withdrawals within withdrawals. // Prevent nested withdrawals within withdrawals.
...@@ -226,13 +216,13 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -226,13 +216,13 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
// Prevent users from creating a deposit transaction where this address is the message // Prevent users from creating a deposit transaction where this address is the message
// sender on L2. // sender on L2.
require( require(
_target != address(this), _tx.target != address(this),
"OptimismPortal: you cannot send messages to the portal contract" "OptimismPortal: you cannot send messages to the portal contract"
); );
// Get the output root. This will fail if there is no // Get the output root. This will fail if there is no
// output root for the given block number. // output root for the given block number.
L2OutputOracle.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber); Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber);
// Ensure that enough time has passed since the proposal was submitted before allowing a // Ensure that enough time has passed since the proposal was submitted before allowing a
// withdrawal. Under the assumption that the fault proof mechanism is operating correctly, // withdrawal. Under the assumption that the fault proof mechanism is operating correctly,
...@@ -248,14 +238,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -248,14 +238,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
// All withdrawals have a unique hash, we'll use this as the identifier for the withdrawal // All withdrawals have a unique hash, we'll use this as the identifier for the withdrawal
// and to prevent replay attacks. // and to prevent replay attacks.
bytes32 withdrawalHash = Hashing.hashWithdrawal( bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);
_nonce,
_sender,
_target,
_value,
_gasLimit,
_data
);
// Verify that the hash of this withdrawal was stored in the withdrawal contract on L2. If // Verify that the hash of this withdrawal was stored in the withdrawal contract on L2. If
// this is true, then we know that this withdrawal was actually triggered on L2 can can // this is true, then we know that this withdrawal was actually triggered on L2 can can
...@@ -282,22 +265,22 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -282,22 +265,22 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
// target contract is at least the gas limit specified by the user. We can do this by // target contract is at least the gas limit specified by the user. We can do this by
// enforcing that, at this point in time, we still have gaslimit + buffer gas available. // enforcing that, at this point in time, we still have gaslimit + buffer gas available.
require( require(
gasleft() >= _gasLimit + FINALIZE_GAS_BUFFER, gasleft() >= _tx.gasLimit + FINALIZE_GAS_BUFFER,
"OptimismPortal: insufficient gas to finalize withdrawal" "OptimismPortal: insufficient gas to finalize withdrawal"
); );
// Set the l2Sender so contracts know who triggered this withdrawal on L2. // Set the l2Sender so contracts know who triggered this withdrawal on L2.
l2Sender = _sender; l2Sender = _tx.sender;
// Trigger the call to the target contract. We use excessivelySafeCall because we don't // Trigger the call to the target contract. We use excessivelySafeCall because we don't
// care about the returndata and we don't want target contracts to be able to force this // care about the returndata and we don't want target contracts to be able to force this
// call to run out of gas. // call to run out of gas.
(bool success, ) = ExcessivelySafeCall.excessivelySafeCall( (bool success, ) = ExcessivelySafeCall.excessivelySafeCall(
_target, _tx.target,
_gasLimit, _tx.gasLimit,
_value, _tx.value,
0, 0,
_data _tx.data
); );
// Reset the l2Sender back to the default value. // Reset the l2Sender back to the default value.
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Types } from "../libraries/Types.sol";
import { Hashing } from "../libraries/Hashing.sol"; import { Hashing } from "../libraries/Hashing.sol";
import { Burn } from "../libraries/Burn.sol"; import { Burn } from "../libraries/Burn.sol";
import { Semver } from "../universal/Semver.sol"; import { Semver } from "../universal/Semver.sol";
...@@ -80,12 +81,14 @@ contract L2ToL1MessagePasser is Semver { ...@@ -80,12 +81,14 @@ contract L2ToL1MessagePasser is Semver {
bytes memory _data bytes memory _data
) public payable { ) public payable {
bytes32 withdrawalHash = Hashing.hashWithdrawal( bytes32 withdrawalHash = Hashing.hashWithdrawal(
nonce, Types.WithdrawalTransaction({
msg.sender, nonce: nonce,
_target, sender: msg.sender,
msg.value, target: _target,
_gasLimit, value: msg.value,
_data gasLimit: _gasLimit,
data: _data
})
); );
sentMessages[withdrawalHash] = true; sentMessages[withdrawalHash] = true;
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.0; pragma solidity ^0.8.0;
import { Types } from "./Types.sol";
import { Hashing } from "./Hashing.sol"; import { Hashing } from "./Hashing.sol";
import { RLPWriter } from "./rlp/RLPWriter.sol"; import { RLPWriter } from "./rlp/RLPWriter.sol";
...@@ -13,38 +14,24 @@ library Encoding { ...@@ -13,38 +14,24 @@ library Encoding {
* @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent
* to the L2 system. Useful for searching for a deposit in the L2 system. * to the L2 system. Useful for searching for a deposit in the L2 system.
* *
* @param _from Address of the sender of the deposit. * @param _tx User deposit transaction to encode.
* @param _to Address of the receiver of the deposit.
* @param _value ETH value to send to the receiver.
* @param _mint ETH value to mint on L2.
* @param _gasLimit Gas limit to use for the transaction.
* @param _isCreation Whether or not the transaction is a contract creation.
* @param _data Data to send with the transaction.
* @param _l1BlockHash Hash of the L1 block where the deposit was included.
* @param _logIndex Index of the deposit event in the L1 block.
* *
* @return RLP encoded L2 deposit transaction. * @return RLP encoded L2 deposit transaction.
*/ */
function encodeDepositTransaction( function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)
address _from, internal
address _to, pure
uint256 _value, returns (bytes memory)
uint256 _mint, {
uint64 _gasLimit, bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);
bool _isCreation,
bytes memory _data,
bytes32 _l1BlockHash,
uint256 _logIndex
) internal pure returns (bytes memory) {
bytes32 source = Hashing.hashDepositSource(_l1BlockHash, _logIndex);
bytes[] memory raw = new bytes[](7); bytes[] memory raw = new bytes[](7);
raw[0] = RLPWriter.writeBytes(abi.encodePacked(source)); raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));
raw[1] = RLPWriter.writeAddress(_from); raw[1] = RLPWriter.writeAddress(_tx.from);
raw[2] = _isCreation ? RLPWriter.writeBytes("") : RLPWriter.writeAddress(_to); raw[2] = _tx.isCreation ? RLPWriter.writeBytes("") : RLPWriter.writeAddress(_tx.to);
raw[3] = RLPWriter.writeUint(_mint); raw[3] = RLPWriter.writeUint(_tx.mint);
raw[4] = RLPWriter.writeUint(_value); raw[4] = RLPWriter.writeUint(_tx.value);
raw[5] = RLPWriter.writeUint(uint256(_gasLimit)); raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));
raw[6] = RLPWriter.writeBytes(_data); raw[6] = RLPWriter.writeBytes(_tx.data);
return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw)); return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));
} }
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.0; pragma solidity ^0.8.0;
import { Types } from "./Types.sol";
import { Encoding } from "./Encoding.sol"; import { Encoding } from "./Encoding.sol";
/** /**
...@@ -8,58 +9,21 @@ import { Encoding } from "./Encoding.sol"; ...@@ -8,58 +9,21 @@ import { Encoding } from "./Encoding.sol";
* @notice Hashing handles Optimism's various different hashing schemes. * @notice Hashing handles Optimism's various different hashing schemes.
*/ */
library Hashing { library Hashing {
/**
* @notice Struct representing the elements that are hashed together to generate an output root
* which itself represents a snapshot of the L2 state.
*/
struct OutputRootProof {
bytes32 version;
bytes32 stateRoot;
bytes32 withdrawerStorageRoot;
bytes32 latestBlockhash;
}
/** /**
* @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a
* given deposit is sent to the L2 system. Useful for searching for a deposit in the L2 * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2
* system. * system.
* *
* @param _from Address of the sender of the deposit. * @param _tx User deposit transaction to hash.
* @param _to Address of the receiver of the deposit.
* @param _value ETH value to send to the receiver.
* @param _mint ETH value to mint on L2.
* @param _gasLimit Gas limit to use for the transaction.
* @param _isCreation Whether or not the transaction is a contract creation.
* @param _data Data to send with the transaction.
* @param _l1BlockHash Hash of the L1 block where the deposit was included.
* @param _logIndex Index of the deposit event in the L1 block.
* *
* @return Hash of the RLP encoded L2 deposit transaction. * @return Hash of the RLP encoded L2 deposit transaction.
*/ */
function hashDepositTransaction( function hashDepositTransaction(Types.UserDepositTransaction memory _tx)
address _from, internal
address _to, pure
uint256 _value, returns (bytes32)
uint256 _mint, {
uint64 _gasLimit, return keccak256(Encoding.encodeDepositTransaction(_tx));
bool _isCreation,
bytes memory _data,
bytes32 _l1BlockHash,
uint256 _logIndex
) internal pure returns (bytes32) {
bytes memory raw = Encoding.encodeDepositTransaction(
_from,
_to,
_value,
_mint,
_gasLimit,
_isCreation,
_data,
_l1BlockHash,
_logIndex
);
return keccak256(raw);
} }
/** /**
...@@ -166,22 +130,20 @@ library Hashing { ...@@ -166,22 +130,20 @@ library Hashing {
/** /**
* @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract
* @param _nonce Nonce for the provided message. *
* @param _sender Message sender address on L2. * @param _tx Withdrawal transaction to hash.
* @param _target Target address on L1. *
* @param _value ETH to send to the target. * @return Hashed withdrawal transaction.
* @param _gasLimit Gas to be forwarded to the target.
* @param _data Data to send to the target.
*/ */
function hashWithdrawal( function hashWithdrawal(Types.WithdrawalTransaction memory _tx)
uint256 _nonce, internal
address _sender, pure
address _target, returns (bytes32)
uint256 _value, {
uint256 _gasLimit, return
bytes memory _data keccak256(
) internal pure returns (bytes32) { abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)
return keccak256(abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data)); );
} }
/** /**
...@@ -192,7 +154,7 @@ library Hashing { ...@@ -192,7 +154,7 @@ library Hashing {
* *
* @return Hashed output root proof. * @return Hashed output root proof.
*/ */
function hashOutputRootProof(OutputRootProof memory _outputRootProof) function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)
internal internal
pure pure
returns (bytes32) returns (bytes32)
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title Types
* @notice Contains various types used throughout the Optimism contract system.
*/
library Types {
/**
* @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1
* timestamp that the output root is posted. This timestamp is used to verify that the
* finalization period has passed since the output root was submitted.
*/
struct OutputProposal {
bytes32 outputRoot;
uint256 timestamp;
}
/**
* @notice Struct representing the elements that are hashed together to generate an output root
* which itself represents a snapshot of the L2 state.
*/
struct OutputRootProof {
bytes32 version;
bytes32 stateRoot;
bytes32 withdrawerStorageRoot;
bytes32 latestBlockhash;
}
/**
* @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end
* user (as opposed to a system deposit transaction generated by the system).
*/
struct UserDepositTransaction {
address from;
address to;
uint256 value;
uint256 mint;
uint64 gasLimit;
bool isCreation;
bytes data;
bytes32 l1BlockHash;
uint256 logIndex;
}
/**
* @notice Struct representing a withdrawal transaction.
*/
struct WithdrawalTransaction {
uint256 nonce;
address sender;
address target;
uint256 value;
uint256 gasLimit;
bytes data;
}
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { CommonTest } from "./CommonTest.t.sol"; import { CommonTest } from "./CommonTest.t.sol";
import { Types } from "../libraries/Types.sol";
import { Encoding } from "../libraries/Encoding.sol"; import { Encoding } from "../libraries/Encoding.sol";
contract Encoding_Test is CommonTest { contract Encoding_Test is CommonTest {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { CommonTest } from "./CommonTest.t.sol"; import { CommonTest } from "./CommonTest.t.sol";
import { Types } from "../libraries/Types.sol";
import { Hashing } from "../libraries/Hashing.sol"; import { Hashing } from "../libraries/Hashing.sol";
import { Encoding } from "../libraries/Encoding.sol"; import { Encoding } from "../libraries/Encoding.sol";
...@@ -64,12 +65,14 @@ contract Hashing_Test is CommonTest { ...@@ -64,12 +65,14 @@ contract Hashing_Test is CommonTest {
bytes memory _data bytes memory _data
) external { ) external {
bytes32 hash = Hashing.hashWithdrawal( bytes32 hash = Hashing.hashWithdrawal(
_nonce, Types.WithdrawalTransaction(
_sender, _nonce,
_target, _sender,
_value, _target,
_gasLimit, _value,
_data _gasLimit,
_data
)
); );
bytes32 _hash = ffi.hashWithdrawal( bytes32 _hash = ffi.hashWithdrawal(
...@@ -90,7 +93,7 @@ contract Hashing_Test is CommonTest { ...@@ -90,7 +93,7 @@ contract Hashing_Test is CommonTest {
bytes32 _withdrawerStorageRoot, bytes32 _withdrawerStorageRoot,
bytes32 _latestBlockhash bytes32 _latestBlockhash
) external { ) external {
Hashing.OutputRootProof memory proof = Hashing.OutputRootProof({ Types.OutputRootProof memory proof = Types.OutputRootProof({
version: _version, version: _version,
stateRoot: _stateRoot, stateRoot: _stateRoot,
withdrawerStorageRoot: _withdrawerStorageRoot, withdrawerStorageRoot: _withdrawerStorageRoot,
...@@ -121,15 +124,17 @@ contract Hashing_Test is CommonTest { ...@@ -121,15 +124,17 @@ contract Hashing_Test is CommonTest {
uint256 _logIndex uint256 _logIndex
) external { ) external {
bytes32 hash = Hashing.hashDepositTransaction( bytes32 hash = Hashing.hashDepositTransaction(
_from, Types.UserDepositTransaction(
_to, _from,
_value, _to,
_mint, _value,
_gas, _mint,
false, // isCreate _gas,
_data, false, // isCreate
bytes32(uint256(0)), _data,
_logIndex bytes32(uint256(0)),
_logIndex
)
); );
bytes32 _hash = ffi.hashDepositTransaction( bytes32 _hash = ffi.hashDepositTransaction(
......
...@@ -4,7 +4,7 @@ pragma solidity 0.8.15; ...@@ -4,7 +4,7 @@ pragma solidity 0.8.15;
import { L2OutputOracle_Initializer, NextImpl } from "./CommonTest.t.sol"; import { L2OutputOracle_Initializer, NextImpl } from "./CommonTest.t.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { Proxy } from "../universal/Proxy.sol"; import { Proxy } from "../universal/Proxy.sol";
import { Types } from "../libraries/Types.sol";
contract L2OutputOracleTest is L2OutputOracle_Initializer { contract L2OutputOracleTest is L2OutputOracle_Initializer {
bytes32 proposedOutput1 = keccak256(abi.encode(1)); bytes32 proposedOutput1 = keccak256(abi.encode(1));
...@@ -23,7 +23,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -23,7 +23,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
assertEq(oracle.proposer(), proposer); assertEq(oracle.proposer(), proposer);
assertEq(oracle.owner(), owner); assertEq(oracle.owner(), owner);
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(startingBlockNumber); Types.OutputProposal memory proposal = oracle.getL2Output(startingBlockNumber);
assertEq(proposal.outputRoot, genesisL2Output); assertEq(proposal.outputRoot, genesisL2Output);
assertEq(proposal.timestamp, initL1Time); assertEq(proposal.timestamp, initL1Time);
} }
...@@ -50,7 +50,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -50,7 +50,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
vm.prank(proposer); vm.prank(proposer);
oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0); oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(nextBlockNumber); Types.OutputProposal memory proposal = oracle.getL2Output(nextBlockNumber);
assertEq(proposal.outputRoot, proposedOutput1); assertEq(proposal.outputRoot, proposedOutput1);
assertEq(proposal.timestamp, block.timestamp); assertEq(proposal.timestamp, block.timestamp);
...@@ -61,11 +61,11 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -61,11 +61,11 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
// The block number is too low: // The block number is too low:
vm.expectRevert("L2OutputOracle: block number cannot be less than the starting block number."); vm.expectRevert("L2OutputOracle: block number cannot be less than the starting block number.");
proposal = oracle.getL2Output(0); oracle.getL2Output(0);
// The block number is larger than the latest proposed output: // The block number is larger than the latest proposed output:
vm.expectRevert("L2OutputOracle: No output found for that block number."); vm.expectRevert("L2OutputOracle: No output found for that block number.");
proposal = oracle.getL2Output(nextBlockNumber + 1); oracle.getL2Output(nextBlockNumber + 1);
} }
// Test: nextBlockNumber() should return the correct value // Test: nextBlockNumber() should return the correct value
...@@ -268,10 +268,10 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -268,10 +268,10 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
test_proposingAnotherOutput(); test_proposingAnotherOutput();
uint256 latestBlockNumber = oracle.latestBlockNumber(); uint256 latestBlockNumber = oracle.latestBlockNumber();
L2OutputOracle.OutputProposal memory proposalToDelete = oracle.getL2Output( Types.OutputProposal memory proposalToDelete = oracle.getL2Output(
latestBlockNumber latestBlockNumber
); );
L2OutputOracle.OutputProposal memory newLatestOutput = oracle.getL2Output( Types.OutputProposal memory newLatestOutput = oracle.getL2Output(
latestBlockNumber - submissionInterval latestBlockNumber - submissionInterval
); );
...@@ -288,7 +288,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -288,7 +288,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
uint256 latestBlockNumberAfter = oracle.latestBlockNumber(); uint256 latestBlockNumberAfter = oracle.latestBlockNumber();
assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter); assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(latestBlockNumberAfter); Types.OutputProposal memory proposal = oracle.getL2Output(latestBlockNumberAfter);
// validate that the new latest output is as expected. // validate that the new latest output is as expected.
assertEq(newLatestOutput.outputRoot, proposal.outputRoot); assertEq(newLatestOutput.outputRoot, proposal.outputRoot);
assertEq(newLatestOutput.timestamp, proposal.timestamp); assertEq(newLatestOutput.timestamp, proposal.timestamp);
...@@ -300,7 +300,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -300,7 +300,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
function testCannot_deleteL2Output_ifNotOwner() external { function testCannot_deleteL2Output_ifNotOwner() external {
uint256 latestBlockNumber = oracle.latestBlockNumber(); uint256 latestBlockNumber = oracle.latestBlockNumber();
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(latestBlockNumber); Types.OutputProposal memory proposal = oracle.getL2Output(latestBlockNumber);
vm.expectRevert("Ownable: caller is not the owner"); vm.expectRevert("Ownable: caller is not the owner");
oracle.deleteL2Output(proposal); oracle.deleteL2Output(proposal);
...@@ -310,7 +310,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -310,7 +310,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
test_proposingAnotherOutput(); test_proposingAnotherOutput();
uint256 previousBlockNumber = oracle.latestBlockNumber() - submissionInterval; uint256 previousBlockNumber = oracle.latestBlockNumber() - submissionInterval;
L2OutputOracle.OutputProposal memory proposalToDelete = oracle.getL2Output( Types.OutputProposal memory proposalToDelete = oracle.getL2Output(
previousBlockNumber previousBlockNumber
); );
...@@ -325,7 +325,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -325,7 +325,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
test_proposingAnotherOutput(); test_proposingAnotherOutput();
uint256 latestBlockNumber = oracle.latestBlockNumber(); uint256 latestBlockNumber = oracle.latestBlockNumber();
L2OutputOracle.OutputProposal memory proposalToDelete = oracle.getL2Output( Types.OutputProposal memory proposalToDelete = oracle.getL2Output(
latestBlockNumber latestBlockNumber
); );
...@@ -354,7 +354,7 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { ...@@ -354,7 +354,7 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {
assertEq(startingTimestamp, oracleImpl.STARTING_TIMESTAMP()); assertEq(startingTimestamp, oracleImpl.STARTING_TIMESTAMP());
assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME()); assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME());
L2OutputOracle.OutputProposal memory initOutput = oracleImpl.getL2Output( Types.OutputProposal memory initOutput = oracleImpl.getL2Output(
startingBlockNumber startingBlockNumber
); );
assertEq(genesisL2Output, initOutput.outputRoot); assertEq(genesisL2Output, initOutput.outputRoot);
......
...@@ -3,6 +3,7 @@ pragma solidity 0.8.15; ...@@ -3,6 +3,7 @@ pragma solidity 0.8.15;
import { CommonTest } from "./CommonTest.t.sol"; import { CommonTest } from "./CommonTest.t.sol";
import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol"; import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol";
import { Types } from "../libraries/Types.sol";
import { Hashing } from "../libraries/Hashing.sol"; import { Hashing } from "../libraries/Hashing.sol";
contract L2ToL1MessagePasserTest is CommonTest { contract L2ToL1MessagePasserTest is CommonTest {
...@@ -65,12 +66,14 @@ contract L2ToL1MessagePasserTest is CommonTest { ...@@ -65,12 +66,14 @@ contract L2ToL1MessagePasserTest is CommonTest {
); );
bytes32 withdrawalHash = Hashing.hashWithdrawal( bytes32 withdrawalHash = Hashing.hashWithdrawal(
nonce, Types.WithdrawalTransaction(
alice, nonce,
target, alice,
value, target,
gasLimit, value,
data gasLimit,
data
)
); );
messagePasser.initiateWithdrawal{ value: value }( messagePasser.initiateWithdrawal{ value: value }(
......
...@@ -5,6 +5,7 @@ import { Portal_Initializer, CommonTest, NextImpl } from "./CommonTest.t.sol"; ...@@ -5,6 +5,7 @@ import { Portal_Initializer, CommonTest, NextImpl } from "./CommonTest.t.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { OptimismPortal } from "../L1/OptimismPortal.sol"; import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { Types } from "../libraries/Types.sol";
import { Hashing } from "../libraries/Hashing.sol"; import { Hashing } from "../libraries/Hashing.sol";
import { Proxy } from "../universal/Proxy.sol"; import { Proxy } from "../universal/Proxy.sol";
...@@ -214,11 +215,8 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -214,11 +215,8 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(address(op).balance, NON_ZERO_VALUE); assertEq(address(op).balance, NON_ZERO_VALUE);
} }
// TODO: test this deeply function test_cannotVerifyRecentWithdrawal() external {
// function test_verifyWithdrawal() external {} Types.OutputRootProof memory outputRootProof = Types
function test_cannotFinalizeRecentWithdrawal() external {
Hashing.OutputRootProof memory outputRootProof = Hashing
.OutputRootProof({ .OutputRootProof({
version: bytes32(0), version: bytes32(0),
stateRoot: bytes32(0), stateRoot: bytes32(0),
...@@ -230,20 +228,21 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -230,20 +228,21 @@ contract OptimismPortal_Test is Portal_Initializer {
vm.mockCall( vm.mockCall(
address(op.L2_ORACLE()), address(op.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(L2OutputOracle.OutputProposal(bytes32(uint256(1)), recentTimestamp)) abi.encode(Types.OutputProposal(bytes32(uint256(1)), recentTimestamp))
); );
vm.expectRevert("OptimismPortal: proposal is not yet finalized"); vm.expectRevert("OptimismPortal: proposal is not yet finalized");
op.finalizeWithdrawalTransaction(0, alice, alice, 0, 0, hex"", 0, outputRootProof, hex""); op.finalizeWithdrawalTransaction(Types.WithdrawalTransaction(0, alice, alice, 0, 0, hex""), 0, outputRootProof, hex"");
} }
function test_invalidWithdrawalProof() external { function test_invalidWithdrawalProof() external {
vm.mockCall( vm.mockCall(
address(op.L2_ORACLE()), address(op.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(L2OutputOracle.OutputProposal(bytes32(uint256(1)), block.timestamp)) abi.encode(Types.OutputProposal(bytes32(uint256(1)), block.timestamp))
); );
Hashing.OutputRootProof memory outputRootProof = Hashing
Types.OutputRootProof memory outputRootProof = Types
.OutputRootProof({ .OutputRootProof({
version: bytes32(0), version: bytes32(0),
stateRoot: bytes32(0), stateRoot: bytes32(0),
...@@ -257,7 +256,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -257,7 +256,7 @@ contract OptimismPortal_Test is Portal_Initializer {
); );
vm.expectRevert("OptimismPortal: invalid output root proof"); vm.expectRevert("OptimismPortal: invalid output root proof");
op.finalizeWithdrawalTransaction(0, alice, alice, 0, 0, hex"", 0, outputRootProof, hex""); op.finalizeWithdrawalTransaction(Types.WithdrawalTransaction(0, alice, alice, 0, 0, hex""), 0, outputRootProof, hex"");
} }
function test_simple_isBlockFinalized() external { function test_simple_isBlockFinalized() external {
...@@ -267,7 +266,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -267,7 +266,7 @@ contract OptimismPortal_Test is Portal_Initializer {
L2OutputOracle.getL2Output.selector L2OutputOracle.getL2Output.selector
), ),
abi.encode( abi.encode(
L2OutputOracle.OutputProposal( Types.OutputProposal(
bytes32(uint256(1)), bytes32(uint256(1)),
startingBlockNumber startingBlockNumber
) )
...@@ -321,7 +320,6 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -321,7 +320,6 @@ contract OptimismPortal_Test is Portal_Initializer {
) external { ) external {
// Cannot call the optimism portal // Cannot call the optimism portal
vm.assume(_target != address(op)); vm.assume(_target != address(op));
uint256 _nonce = messagePasser.nonce(); uint256 _nonce = messagePasser.nonce();
( (
...@@ -339,22 +337,23 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -339,22 +337,23 @@ contract OptimismPortal_Test is Portal_Initializer {
_data _data
); );
Hashing.OutputRootProof memory proof = Hashing.OutputRootProof({ // Ensure the values returned from ffi are correct
assertEq(outputRoot, Hashing.hashOutputRootProof(Types.OutputRootProof({
version: bytes32(uint256(0)), version: bytes32(uint256(0)),
stateRoot: stateRoot, stateRoot: stateRoot,
withdrawerStorageRoot: storageRoot, withdrawerStorageRoot: storageRoot,
latestBlockhash: bytes32(uint256(0)) latestBlockhash: bytes32(uint256(0))
}); })));
// Ensure the values returned from ffi are correct
assertEq(outputRoot, Hashing.hashOutputRootProof(proof));
assertEq(withdrawalHash, Hashing.hashWithdrawal( assertEq(withdrawalHash, Hashing.hashWithdrawal(
_nonce, Types.WithdrawalTransaction(
_sender, _nonce,
_target, _sender,
_value, _target,
uint64(_gasLimit), _value,
_data uint64(_gasLimit),
_data
)
)); ));
// Mock the call to the oracle // Mock the call to the oracle
...@@ -378,14 +377,21 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -378,14 +377,21 @@ contract OptimismPortal_Test is Portal_Initializer {
vm.warp(op.FINALIZATION_PERIOD_SECONDS() + 1); vm.warp(op.FINALIZATION_PERIOD_SECONDS() + 1);
op.finalizeWithdrawalTransaction{ value: _value }( op.finalizeWithdrawalTransaction{ value: _value }(
messagePasser.nonce() - 1, Types.WithdrawalTransaction(
_sender, messagePasser.nonce() - 1,
_target, _sender,
_value, _target,
uint64(_gasLimit), _value,
_data, uint64(_gasLimit),
_data
),
100, // l2BlockNumber 100, // l2BlockNumber
proof, Types.OutputRootProof({
version: bytes32(uint256(0)),
stateRoot: stateRoot,
withdrawerStorageRoot: storageRoot,
latestBlockhash: bytes32(uint256(0))
}),
withdrawalProof withdrawalProof
); );
} }
......
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