Commit 0c426483 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

contracts-bedrock: migrate interop portal to fp (#11051)

* contracts-bedrock: migrate interop portal to fp

Utilize fault proofs in the interop portal. This is
useful for removing the `L2OutputOracle` from the codebase.
We will need to deploy the interop devnet using the permissioned
dispute game after this change, so we want to ensure that the
deploy script can set that up easily.

* ctb: migrate interop to fp portal

* snapshots: regenerate

* lint: fix

* contracts-bedrock: always enable fault proofs with interop

* interop: support fault proofs

* deploy script: only deploy correct contracts

* contracts-bedrock: cleanup deploy

* contracts-bedrock: fix deploy

The deploy script is very coupled to unit tests

* portal2: reduce codesize

* lint: fix

* snapshots: update

* snapshots: update

* semver-lock: regenerate

* deploy script: update

* tests: update excludes

* summary: update
parent a3b6a600
# `OptimismPortal2` Invariants # `OptimismPortal2` Invariants
## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`. ## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`.
**Test:** [`OptimismPortal2.t.sol#L160`](../test/invariants/OptimismPortal2.t.sol#L160) **Test:** [`OptimismPortal2.t.sol#L161`](../test/invariants/OptimismPortal2.t.sol#L161)
All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed. All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed.
## `finalizeWithdrawalTransaction` should revert if the proof maturity period has not elapsed. ## `finalizeWithdrawalTransaction` should revert if the proof maturity period has not elapsed.
**Test:** [`OptimismPortal2.t.sol#L182`](../test/invariants/OptimismPortal2.t.sol#L182) **Test:** [`OptimismPortal2.t.sol#L183`](../test/invariants/OptimismPortal2.t.sol#L183)
A withdrawal that has been proven should not be able to be finalized until after the proof maturity period has elapsed. A withdrawal that has been proven should not be able to be finalized until after the proof maturity period has elapsed.
## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized. ## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized.
**Test:** [`OptimismPortal2.t.sol#L211`](../test/invariants/OptimismPortal2.t.sol#L211) **Test:** [`OptimismPortal2.t.sol#L212`](../test/invariants/OptimismPortal2.t.sol#L212)
Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice. Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice.
## A withdrawal should **always** be able to be finalized `PROOF_MATURITY_DELAY_SECONDS` after it was successfully proven, if the game has resolved and passed the air-gap. ## A withdrawal should **always** be able to be finalized `PROOF_MATURITY_DELAY_SECONDS` after it was successfully proven, if the game has resolved and passed the air-gap.
**Test:** [`OptimismPortal2.t.sol#L239`](../test/invariants/OptimismPortal2.t.sol#L239) **Test:** [`OptimismPortal2.t.sol#L240`](../test/invariants/OptimismPortal2.t.sol#L240)
This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `PROOF_MATURITY_DELAY_SECONDS` after it was successfully proven and the game has resolved and passed the air-gap. This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `PROOF_MATURITY_DELAY_SECONDS` after it was successfully proven and the game has resolved and passed the air-gap.
\ No newline at end of file
...@@ -384,7 +384,6 @@ contract Deploy is Deployer { ...@@ -384,7 +384,6 @@ contract Deploy is Deployer {
deployL1ERC721Bridge(); deployL1ERC721Bridge();
deployOptimismPortal(); deployOptimismPortal();
deployL2OutputOracle(); deployL2OutputOracle();
// Fault proofs // Fault proofs
deployOptimismPortal2(); deployOptimismPortal2();
deployDisputeGameFactory(); deployDisputeGameFactory();
...@@ -642,10 +641,9 @@ contract Deploy is Deployer { ...@@ -642,10 +641,9 @@ contract Deploy is Deployer {
function deployOptimismPortal() public broadcast returns (address addr_) { function deployOptimismPortal() public broadcast returns (address addr_) {
console.log("Deploying OptimismPortal implementation"); console.log("Deploying OptimismPortal implementation");
if (cfg.useInterop()) { if (cfg.useInterop()) {
addr_ = address(new OptimismPortalInterop{ salt: _implSalt() }()); console.log("Attempting to deploy OptimismPortal with interop, this config is a noop");
} else {
addr_ = address(new OptimismPortal{ salt: _implSalt() }());
} }
addr_ = address(new OptimismPortal{ salt: _implSalt() }());
save("OptimismPortal", addr_); save("OptimismPortal", addr_);
console.log("OptimismPortal deployed at %s", addr_); console.log("OptimismPortal deployed at %s", addr_);
...@@ -666,22 +664,31 @@ contract Deploy is Deployer { ...@@ -666,22 +664,31 @@ contract Deploy is Deployer {
uint32(cfg.respectedGameType()) == cfg.respectedGameType(), "Deploy: respectedGameType must fit into uint32" uint32(cfg.respectedGameType()) == cfg.respectedGameType(), "Deploy: respectedGameType must fit into uint32"
); );
OptimismPortal2 portal = new OptimismPortal2{ salt: _implSalt() }({ if (cfg.useInterop()) {
addr_ = address(
new OptimismPortalInterop{ salt: _implSalt() }({
_proofMaturityDelaySeconds: cfg.proofMaturityDelaySeconds(), _proofMaturityDelaySeconds: cfg.proofMaturityDelaySeconds(),
_disputeGameFinalityDelaySeconds: cfg.disputeGameFinalityDelaySeconds() _disputeGameFinalityDelaySeconds: cfg.disputeGameFinalityDelaySeconds()
}); })
);
} else {
addr_ = address(
new OptimismPortal2{ salt: _implSalt() }({
_proofMaturityDelaySeconds: cfg.proofMaturityDelaySeconds(),
_disputeGameFinalityDelaySeconds: cfg.disputeGameFinalityDelaySeconds()
})
);
}
save("OptimismPortal2", address(portal)); save("OptimismPortal2", addr_);
console.log("OptimismPortal2 deployed at %s", address(portal)); console.log("OptimismPortal2 deployed at %s", addr_);
// Override the `OptimismPortal2` contract to the deployed implementation. This is necessary // Override the `OptimismPortal2` contract to the deployed implementation. This is necessary
// to check the `OptimismPortal2` implementation alongside dependent contracts, which // to check the `OptimismPortal2` implementation alongside dependent contracts, which
// are always proxies. // are always proxies.
Types.ContractSet memory contracts = _proxiesUnstrict(); Types.ContractSet memory contracts = _proxiesUnstrict();
contracts.OptimismPortal2 = address(portal); contracts.OptimismPortal2 = addr_;
ChainAssertions.checkOptimismPortal2({ _contracts: contracts, _cfg: cfg, _isProxy: false }); ChainAssertions.checkOptimismPortal2({ _contracts: contracts, _cfg: cfg, _isProxy: false });
addr_ = address(portal);
} }
/// @notice Deploy the L2OutputOracle /// @notice Deploy the L2OutputOracle
......
...@@ -40,12 +40,12 @@ ...@@ -40,12 +40,12 @@
"sourceCodeHash": "0x9fe0a9001edecd2a04daada4ca9e17d66141b1c982f73653493b4703d2c675c4" "sourceCodeHash": "0x9fe0a9001edecd2a04daada4ca9e17d66141b1c982f73653493b4703d2c675c4"
}, },
"src/L1/OptimismPortal2.sol": { "src/L1/OptimismPortal2.sol": {
"initCodeHash": "0x7f5122fb6d5c1123c870f936f8a33f752190ae90932434ad9b726fb2b582746f", "initCodeHash": "0x12071439501e60420ab217cea4477306864014b66722d09b8cb8e01369f343ec",
"sourceCodeHash": "0x9af4d957b9d554b9926ad27572766d6f22c515f1ed6f620389b32c46ebce4c7b" "sourceCodeHash": "0xf597b9dcb97e733948a7179b8951dd46e4bb1ebc0715dd9440ffdabe0ecb0843"
}, },
"src/L1/OptimismPortalInterop.sol": { "src/L1/OptimismPortalInterop.sol": {
"initCodeHash": "0x4ab4c99bd776d1817f7475161db0ce47e735a91bb9fb486338238aa762fe0909", "initCodeHash": "0xa8ce00980799cb918b44fbbfdf4370a069d3bd15a92b2ed6850e98ebc0388b86",
"sourceCodeHash": "0x49ae32c402536774928116b833e2256741dbbdf99900ea5df159efab684d1008" "sourceCodeHash": "0xe3805faeb962594d5c2c18cdeb35c2db1248393650bec2ad5cadf41759f151f2"
}, },
"src/L1/ProtocolVersions.sol": { "src/L1/ProtocolVersions.sol": {
"initCodeHash": "0x72cd467e8bcf019c02675d72ab762e088bcc9cc0f1a4e9f587fa4589f7fdd1b8", "initCodeHash": "0x72cd467e8bcf019c02675d72ab762e088bcc9cc0f1a4e9f587fa4589f7fdd1b8",
......
...@@ -821,11 +821,21 @@ ...@@ -821,11 +821,21 @@
"name": "WithdrawalProvenExtension1", "name": "WithdrawalProvenExtension1",
"type": "event" "type": "event"
}, },
{
"inputs": [],
"name": "AlreadyFinalized",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "BadTarget", "name": "BadTarget",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "Blacklisted",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "CallPaused", "name": "CallPaused",
...@@ -851,11 +861,31 @@ ...@@ -851,11 +861,31 @@
"name": "InvalidDataRemainder", "name": "InvalidDataRemainder",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "InvalidDisputeGame",
"type": "error"
},
{
"inputs": [],
"name": "InvalidGameType",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "InvalidHeader", "name": "InvalidHeader",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "InvalidMerkleProof",
"type": "error"
},
{
"inputs": [],
"name": "InvalidProof",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "LargeCalldata", "name": "LargeCalldata",
...@@ -881,6 +911,11 @@ ...@@ -881,6 +911,11 @@
"name": "OutOfGas", "name": "OutOfGas",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "ProposalNotValidated",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "SmallGasLimit", "name": "SmallGasLimit",
...@@ -905,5 +940,10 @@ ...@@ -905,5 +940,10 @@
"inputs": [], "inputs": [],
"name": "UnexpectedString", "name": "UnexpectedString",
"type": "error" "type": "error"
},
{
"inputs": [],
"name": "Unproven",
"type": "error"
} }
] ]
\ No newline at end of file
[ [
{
"inputs": [
{
"internalType": "uint256",
"name": "_proofMaturityDelaySeconds",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_disputeGameFinalityDelaySeconds",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{ {
"stateMutability": "payable", "stateMutability": "payable",
"type": "receive" "type": "receive"
...@@ -16,6 +32,37 @@ ...@@ -16,6 +32,37 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "contract IDisputeGame",
"name": "_disputeGame",
"type": "address"
}
],
"name": "blacklistDisputeGame",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "_withdrawalHash",
"type": "bytes32"
},
{
"internalType": "address",
"name": "_proofSubmitter",
"type": "address"
}
],
"name": "checkWithdrawal",
"outputs": [],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
...@@ -87,6 +134,51 @@ ...@@ -87,6 +134,51 @@
"stateMutability": "payable", "stateMutability": "payable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "contract IDisputeGame",
"name": "",
"type": "address"
}
],
"name": "disputeGameBlacklist",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "disputeGameFactory",
"outputs": [
{
"internalType": "contract DisputeGameFactory",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "disputeGameFinalityDelaySeconds",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [], "inputs": [],
"name": "donateETH", "name": "donateETH",
...@@ -139,6 +231,56 @@ ...@@ -139,6 +231,56 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"components": [
{
"internalType": "uint256",
"name": "nonce",
"type": "uint256"
},
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "address",
"name": "target",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "gasLimit",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"internalType": "struct Types.WithdrawalTransaction",
"name": "_tx",
"type": "tuple"
},
{
"internalType": "address",
"name": "_proofSubmitter",
"type": "address"
}
],
"name": "finalizeWithdrawalTransactionExternalProof",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
...@@ -174,8 +316,8 @@ ...@@ -174,8 +316,8 @@
{ {
"inputs": [ "inputs": [
{ {
"internalType": "contract L2OutputOracle", "internalType": "contract DisputeGameFactory",
"name": "_l2Oracle", "name": "_disputeGameFactory",
"type": "address" "type": "address"
}, },
{ {
...@@ -187,6 +329,11 @@ ...@@ -187,6 +329,11 @@
"internalType": "contract SuperchainConfig", "internalType": "contract SuperchainConfig",
"name": "_superchainConfig", "name": "_superchainConfig",
"type": "address" "type": "address"
},
{
"internalType": "GameType",
"name": "_initialRespectedGameType",
"type": "uint32"
} }
], ],
"name": "initialize", "name": "initialize",
...@@ -194,38 +341,6 @@ ...@@ -194,38 +341,6 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "uint256",
"name": "_l2OutputIndex",
"type": "uint256"
}
],
"name": "isOutputFinalized",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l2Oracle",
"outputs": [
{
"internalType": "contract L2OutputOracle",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [], "inputs": [],
"name": "l2Sender", "name": "l2Sender",
...@@ -258,6 +373,25 @@ ...@@ -258,6 +373,25 @@
"stateMutability": "pure", "stateMutability": "pure",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "bytes32",
"name": "_withdrawalHash",
"type": "bytes32"
}
],
"name": "numProofSubmitters",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [], "inputs": [],
"name": "params", "name": "params",
...@@ -287,13 +421,50 @@ ...@@ -287,13 +421,50 @@
"outputs": [ "outputs": [
{ {
"internalType": "bool", "internalType": "bool",
"name": "paused_", "name": "",
"type": "bool" "type": "bool"
} }
], ],
"stateMutability": "view", "stateMutability": "view",
"type": "function" "type": "function"
}, },
{
"inputs": [],
"name": "proofMaturityDelaySeconds",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "proofSubmitters",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
...@@ -335,7 +506,7 @@ ...@@ -335,7 +506,7 @@
}, },
{ {
"internalType": "uint256", "internalType": "uint256",
"name": "_l2OutputIndex", "name": "_disputeGameIndex",
"type": "uint256" "type": "uint256"
}, },
{ {
...@@ -382,24 +553,50 @@ ...@@ -382,24 +553,50 @@
"internalType": "bytes32", "internalType": "bytes32",
"name": "", "name": "",
"type": "bytes32" "type": "bytes32"
},
{
"internalType": "address",
"name": "",
"type": "address"
} }
], ],
"name": "provenWithdrawals", "name": "provenWithdrawals",
"outputs": [ "outputs": [
{ {
"internalType": "bytes32", "internalType": "contract IDisputeGame",
"name": "outputRoot", "name": "disputeGameProxy",
"type": "bytes32" "type": "address"
}, },
{ {
"internalType": "uint128", "internalType": "uint64",
"name": "timestamp", "name": "timestamp",
"type": "uint128" "type": "uint64"
}
],
"stateMutability": "view",
"type": "function"
}, },
{ {
"internalType": "uint128", "inputs": [],
"name": "l2OutputIndex", "name": "respectedGameType",
"type": "uint128" "outputs": [
{
"internalType": "GameType",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "respectedGameTypeUpdatedAt",
"outputs": [
{
"internalType": "uint64",
"name": "",
"type": "uint64"
} }
], ],
"stateMutability": "view", "stateMutability": "view",
...@@ -451,6 +648,19 @@ ...@@ -451,6 +648,19 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "GameType",
"name": "_gameType",
"type": "uint32"
}
],
"name": "setRespectedGameType",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{ {
"inputs": [], "inputs": [],
"name": "superchainConfig", "name": "superchainConfig",
...@@ -490,6 +700,19 @@ ...@@ -490,6 +700,19 @@
"stateMutability": "pure", "stateMutability": "pure",
"type": "function" "type": "function"
}, },
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "contract IDisputeGame",
"name": "disputeGame",
"type": "address"
}
],
"name": "DisputeGameBlacklisted",
"type": "event"
},
{ {
"anonymous": false, "anonymous": false,
"inputs": [ "inputs": [
...@@ -503,6 +726,25 @@ ...@@ -503,6 +726,25 @@
"name": "Initialized", "name": "Initialized",
"type": "event" "type": "event"
}, },
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "GameType",
"name": "newGameType",
"type": "uint32"
},
{
"indexed": true,
"internalType": "Timestamp",
"name": "updatedAt",
"type": "uint64"
}
],
"name": "RespectedGameTypeSet",
"type": "event"
},
{ {
"anonymous": false, "anonymous": false,
"inputs": [ "inputs": [
...@@ -578,11 +820,40 @@ ...@@ -578,11 +820,40 @@
"name": "WithdrawalProven", "name": "WithdrawalProven",
"type": "event" "type": "event"
}, },
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "withdrawalHash",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "proofSubmitter",
"type": "address"
}
],
"name": "WithdrawalProvenExtension1",
"type": "event"
},
{
"inputs": [],
"name": "AlreadyFinalized",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "BadTarget", "name": "BadTarget",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "Blacklisted",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "CallPaused", "name": "CallPaused",
...@@ -608,11 +879,31 @@ ...@@ -608,11 +879,31 @@
"name": "InvalidDataRemainder", "name": "InvalidDataRemainder",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "InvalidDisputeGame",
"type": "error"
},
{
"inputs": [],
"name": "InvalidGameType",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "InvalidHeader", "name": "InvalidHeader",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "InvalidMerkleProof",
"type": "error"
},
{
"inputs": [],
"name": "InvalidProof",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "LargeCalldata", "name": "LargeCalldata",
...@@ -638,6 +929,11 @@ ...@@ -638,6 +929,11 @@
"name": "OutOfGas", "name": "OutOfGas",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "ProposalNotValidated",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "SmallGasLimit", "name": "SmallGasLimit",
...@@ -667,5 +963,10 @@ ...@@ -667,5 +963,10 @@
"inputs": [], "inputs": [],
"name": "UnexpectedString", "name": "UnexpectedString",
"type": "error" "type": "error"
},
{
"inputs": [],
"name": "Unproven",
"type": "error"
} }
] ]
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -43,10 +43,10 @@ ...@@ -43,10 +43,10 @@
}, },
{ {
"bytes": "32", "bytes": "32",
"label": "provenWithdrawals", "label": "spacer_52_0_32",
"offset": 0, "offset": 0,
"slot": "52", "slot": "52",
"type": "mapping(bytes32 => struct OptimismPortal.ProvenWithdrawal)" "type": "bytes32"
}, },
{ {
"bytes": "1", "bytes": "1",
...@@ -64,10 +64,10 @@ ...@@ -64,10 +64,10 @@
}, },
{ {
"bytes": "20", "bytes": "20",
"label": "l2Oracle", "label": "spacer_54_0_20",
"offset": 0, "offset": 0,
"slot": "54", "slot": "54",
"type": "contract L2OutputOracle" "type": "address"
}, },
{ {
"bytes": "20", "bytes": "20",
...@@ -78,38 +78,45 @@ ...@@ -78,38 +78,45 @@
}, },
{ {
"bytes": "20", "bytes": "20",
"label": "spacer_56_0_20", "label": "disputeGameFactory",
"offset": 0, "offset": 0,
"slot": "56", "slot": "56",
"type": "address" "type": "contract DisputeGameFactory"
}, },
{ {
"bytes": "32", "bytes": "32",
"label": "spacer_57_0_32", "label": "provenWithdrawals",
"offset": 0, "offset": 0,
"slot": "57", "slot": "57",
"type": "bytes32" "type": "mapping(bytes32 => mapping(address => struct OptimismPortal2.ProvenWithdrawal))"
}, },
{ {
"bytes": "32", "bytes": "32",
"label": "spacer_58_0_32", "label": "disputeGameBlacklist",
"offset": 0, "offset": 0,
"slot": "58", "slot": "58",
"type": "bytes32" "type": "mapping(contract IDisputeGame => bool)"
}, },
{ {
"bytes": "32", "bytes": "4",
"label": "spacer_59_0_32", "label": "respectedGameType",
"offset": 0, "offset": 0,
"slot": "59", "slot": "59",
"type": "bytes32" "type": "GameType"
},
{
"bytes": "8",
"label": "respectedGameTypeUpdatedAt",
"offset": 4,
"slot": "59",
"type": "uint64"
}, },
{ {
"bytes": "32", "bytes": "32",
"label": "spacer_60_0_32", "label": "proofSubmitters",
"offset": 0, "offset": 0,
"slot": "60", "slot": "60",
"type": "bytes32" "type": "mapping(bytes32 => address[])"
}, },
{ {
"bytes": "32", "bytes": "32",
......
...@@ -153,9 +153,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -153,9 +153,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
} }
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 3.11.0-beta.1 /// @custom:semver 3.11.0-beta.2
function version() public pure virtual returns (string memory) { function version() public pure virtual returns (string memory) {
return "3.11.0-beta.1"; return "3.11.0-beta.2";
} }
/// @notice Constructs the OptimismPortal contract. /// @notice Constructs the OptimismPortal contract.
...@@ -300,23 +300,17 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -300,23 +300,17 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
Claim outputRoot = gameProxy.rootClaim(); Claim outputRoot = gameProxy.rootClaim();
// The game type of the dispute game must be the respected game type. // The game type of the dispute game must be the respected game type.
require(gameType.raw() == respectedGameType.raw(), "OptimismPortal: invalid game type"); if (gameType.raw() != respectedGameType.raw()) revert InvalidGameType();
// Verify that the output root can be generated with the elements in the proof. // Verify that the output root can be generated with the elements in the proof.
require( if (outputRoot.raw() != Hashing.hashOutputRootProof(_outputRootProof)) revert InvalidProof();
outputRoot.raw() == Hashing.hashOutputRootProof(_outputRootProof),
"OptimismPortal: invalid output root proof"
);
// Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier. // Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier.
bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx); bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);
// We do not allow for proving withdrawals against dispute games that have resolved against the favor // We do not allow for proving withdrawals against dispute games that have resolved against the favor
// of the root claim. // of the root claim.
require( if (gameProxy.status() == GameStatus.CHALLENGER_WINS) revert InvalidDisputeGame();
gameProxy.status() != GameStatus.CHALLENGER_WINS,
"OptimismPortal: cannot prove against invalid dispute games"
);
// Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract. // Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract.
// Refer to the Solidity documentation for more information on how storage layouts are // Refer to the Solidity documentation for more information on how storage layouts are
...@@ -332,15 +326,14 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -332,15 +326,14 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
// on L2. If this is true, under the assumption that the SecureMerkleTrie does not have // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have
// bugs, then we know that this withdrawal was actually triggered on L2 and can therefore // bugs, then we know that this withdrawal was actually triggered on L2 and can therefore
// be relayed on L1. // be relayed on L1.
require( if (
SecureMerkleTrie.verifyInclusionProof({ SecureMerkleTrie.verifyInclusionProof({
_key: abi.encode(storageKey), _key: abi.encode(storageKey),
_value: hex"01", _value: hex"01",
_proof: _withdrawalProof, _proof: _withdrawalProof,
_root: _outputRootProof.messagePasserStorageRoot _root: _outputRootProof.messagePasserStorageRoot
}), }) == false
"OptimismPortal: invalid withdrawal inclusion proof" ) revert InvalidMerkleProof();
);
// Designate the withdrawalHash as proven by storing the `disputeGameProxy` & `timestamp` in the // Designate the withdrawalHash as proven by storing the `disputeGameProxy` & `timestamp` in the
// `provenWithdrawals` mapping. A `withdrawalHash` can only be proven once unless the dispute game it proved // `provenWithdrawals` mapping. A `withdrawalHash` can only be proven once unless the dispute game it proved
...@@ -631,15 +624,12 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -631,15 +624,12 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
IDisputeGame disputeGameProxy = provenWithdrawal.disputeGameProxy; IDisputeGame disputeGameProxy = provenWithdrawal.disputeGameProxy;
// The dispute game must not be blacklisted. // The dispute game must not be blacklisted.
require(!disputeGameBlacklist[disputeGameProxy], "OptimismPortal: dispute game has been blacklisted"); if (disputeGameBlacklist[disputeGameProxy]) revert Blacklisted();
// A withdrawal can only be finalized if it has been proven. We know that a withdrawal has // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has
// been proven at least once when its timestamp is non-zero. Unproven withdrawals will have // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have
// a timestamp of zero. // a timestamp of zero.
require( if (provenWithdrawal.timestamp == 0) revert Unproven();
provenWithdrawal.timestamp != 0,
"OptimismPortal: withdrawal has not been proven by proof submitter address yet"
);
uint64 createdAt = disputeGameProxy.createdAt().raw(); uint64 createdAt = disputeGameProxy.createdAt().raw();
...@@ -660,15 +650,12 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -660,15 +650,12 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
// A proven withdrawal must wait until the dispute game it was proven against has been // A proven withdrawal must wait until the dispute game it was proven against has been
// resolved in favor of the root claim (the output proposal). This is to prevent users // resolved in favor of the root claim (the output proposal). This is to prevent users
// from finalizing withdrawals proven against non-finalized output roots. // from finalizing withdrawals proven against non-finalized output roots.
require( if (disputeGameProxy.status() != GameStatus.DEFENDER_WINS) revert ProposalNotValidated();
disputeGameProxy.status() == GameStatus.DEFENDER_WINS,
"OptimismPortal: output proposal has not been validated"
);
// The game type of the dispute game must be the respected game type. This was also checked in // The game type of the dispute game must be the respected game type. This was also checked in
// `proveWithdrawalTransaction`, but we check it again in case the respected game type has changed since // `proveWithdrawalTransaction`, but we check it again in case the respected game type has changed since
// the withdrawal was proven. // the withdrawal was proven.
require(disputeGameProxy.gameType().raw() == respectedGameType.raw(), "OptimismPortal: invalid game type"); if (disputeGameProxy.gameType().raw() != respectedGameType.raw()) revert InvalidGameType();
// The game must have been created after `respectedGameTypeUpdatedAt`. This is to prevent users from creating // The game must have been created after `respectedGameTypeUpdatedAt`. This is to prevent users from creating
// invalid disputes against a deployed game type while the off-chain challenge agents are not watching. // invalid disputes against a deployed game type while the off-chain challenge agents are not watching.
...@@ -686,7 +673,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -686,7 +673,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
); );
// Check that this withdrawal has not already been finalized, this is replay protection. // Check that this withdrawal has not already been finalized, this is replay protection.
require(!finalizedWithdrawals[_withdrawalHash], "OptimismPortal: withdrawal has already been finalized"); if (finalizedWithdrawals[_withdrawalHash]) revert AlreadyFinalized();
} }
/// @notice External getter for the number of proof submitters for a withdrawal hash. /// @notice External getter for the number of proof submitters for a withdrawal hash.
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { OptimismPortal } from "src/L1/OptimismPortal.sol"; import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol";
import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol"; import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol";
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { Constants } from "src/libraries/Constants.sol"; import { Constants } from "src/libraries/Constants.sol";
...@@ -11,10 +11,17 @@ import { Constants } from "src/libraries/Constants.sol"; ...@@ -11,10 +11,17 @@ import { Constants } from "src/libraries/Constants.sol";
/// @notice The OptimismPortal is a low-level contract responsible for passing messages between L1 /// @notice The OptimismPortal is a low-level contract responsible for passing messages between L1
/// and L2. Messages sent directly to the OptimismPortal have no form of replayability. /// and L2. Messages sent directly to the OptimismPortal have no form of replayability.
/// Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface. /// Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface.
contract OptimismPortalInterop is OptimismPortal { contract OptimismPortalInterop is OptimismPortal2 {
/// @notice Thrown when a non-depositor account attempts update static configuration. /// @notice Thrown when a non-depositor account attempts update static configuration.
error Unauthorized(); error Unauthorized();
constructor(
uint256 _proofMaturityDelaySeconds,
uint256 _disputeGameFinalityDelaySeconds
)
OptimismPortal2(_proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds)
{ }
/// @custom:semver +interop /// @custom:semver +interop
function version() public pure override returns (string memory) { function version() public pure override returns (string memory) {
return string.concat(super.version(), "+interop"); return string.concat(super.version(), "+interop");
......
...@@ -22,3 +22,19 @@ error CallPaused(); ...@@ -22,3 +22,19 @@ error CallPaused();
error GasEstimation(); error GasEstimation();
/// @notice Error for when a method is being reentered. /// @notice Error for when a method is being reentered.
error NonReentrant(); error NonReentrant();
/// @notice Error for invalid proof.
error InvalidProof();
/// @notice Error for invalid game type.
error InvalidGameType();
/// @notice Error for an invalid dispute game.
error InvalidDisputeGame();
/// @notice Error for an invalid merkle proof.
error InvalidMerkleProof();
/// @notice Error for when a dispute game has been blacklisted.
error Blacklisted();
/// @notice Error for when trying to withdrawal without first proven.
error Unproven();
/// @notice Error for when a proposal is not validated.
error ProposalNotValidated();
/// @notice Error for when a withdrawal has already been finalized.
error AlreadyFinalized();
...@@ -559,7 +559,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -559,7 +559,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external { function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external {
// Modify the version to invalidate the withdrawal proof. // Modify the version to invalidate the withdrawal proof.
_outputRootProof.version = bytes32(uint256(1)); _outputRootProof.version = bytes32(uint256(1));
vm.expectRevert("OptimismPortal: invalid output root proof"); vm.expectRevert(InvalidProof.selector);
optimismPortal2.proveWithdrawalTransaction({ optimismPortal2.proveWithdrawalTransaction({
_tx: _defaultTx, _tx: _defaultTx,
_disputeGameIndex: _proposedGameIndex, _disputeGameIndex: _proposedGameIndex,
...@@ -603,7 +603,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -603,7 +603,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
vm.mockCall(address(game), abi.encodeCall(game.status, ()), abi.encode(GameStatus.CHALLENGER_WINS)); vm.mockCall(address(game), abi.encodeCall(game.status, ()), abi.encode(GameStatus.CHALLENGER_WINS));
vm.mockCall(address(game2), abi.encodeCall(game.status, ()), abi.encode(GameStatus.CHALLENGER_WINS)); vm.mockCall(address(game2), abi.encodeCall(game.status, ()), abi.encode(GameStatus.CHALLENGER_WINS));
vm.expectRevert("OptimismPortal: cannot prove against invalid dispute games"); vm.expectRevert(InvalidDisputeGame.selector);
optimismPortal2.proveWithdrawalTransaction({ optimismPortal2.proveWithdrawalTransaction({
_tx: _defaultTx, _tx: _defaultTx,
_disputeGameIndex: _proposedGameIndex, _disputeGameIndex: _proposedGameIndex,
...@@ -621,7 +621,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -621,7 +621,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
abi.encode(GameType.wrap(0xFF), Timestamp.wrap(uint64(block.timestamp)), IDisputeGame(address(game))) abi.encode(GameType.wrap(0xFF), Timestamp.wrap(uint64(block.timestamp)), IDisputeGame(address(game)))
); );
vm.expectRevert("OptimismPortal: invalid game type"); vm.expectRevert(InvalidGameType.selector);
optimismPortal2.proveWithdrawalTransaction({ optimismPortal2.proveWithdrawalTransaction({
_tx: _defaultTx, _tx: _defaultTx,
_disputeGameIndex: _proposedGameIndex, _disputeGameIndex: _proposedGameIndex,
...@@ -796,7 +796,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -796,7 +796,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
emit WithdrawalFinalized(_withdrawalHash, true); emit WithdrawalFinalized(_withdrawalHash, true);
optimismPortal2.finalizeWithdrawalTransactionExternalProof(_defaultTx, address(0xb0b)); optimismPortal2.finalizeWithdrawalTransactionExternalProof(_defaultTx, address(0xb0b));
vm.expectRevert("OptimismPortal: withdrawal has already been finalized"); vm.expectRevert(AlreadyFinalized.selector);
optimismPortal2.finalizeWithdrawalTransactionExternalProof(_defaultTx, address(this)); optimismPortal2.finalizeWithdrawalTransactionExternalProof(_defaultTx, address(this));
assert(address(bob).balance == bobBalanceBefore + 100); assert(address(bob).balance == bobBalanceBefore + 100);
...@@ -879,7 +879,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -879,7 +879,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
// Ensure both proofs are registered successfully. // Ensure both proofs are registered successfully.
assertEq(optimismPortal2.numProofSubmitters(_withdrawalHash), 2); assertEq(optimismPortal2.numProofSubmitters(_withdrawalHash), 2);
vm.expectRevert("OptimismPortal: output proposal has not been validated"); vm.expectRevert(ProposalNotValidated.selector);
vm.prank(address(0xb0b)); vm.prank(address(0xb0b));
optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); optimismPortal2.finalizeWithdrawalTransaction(_defaultTx);
...@@ -927,7 +927,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -927,7 +927,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external { function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
vm.expectRevert("OptimismPortal: withdrawal has not been proven by proof submitter address yet"); vm.expectRevert(Unproven.selector);
optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); optimismPortal2.finalizeWithdrawalTransaction(_defaultTx);
assert(address(bob).balance == bobBalanceBefore); assert(address(bob).balance == bobBalanceBefore);
...@@ -1007,7 +1007,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -1007,7 +1007,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1);
// Attempt to finalize the withdrawal // Attempt to finalize the withdrawal
vm.expectRevert("OptimismPortal: output proposal has not been validated"); vm.expectRevert(ProposalNotValidated.selector);
optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); optimismPortal2.finalizeWithdrawalTransaction(_defaultTx);
// Ensure that bob's balance has remained the same // Ensure that bob's balance has remained the same
...@@ -1065,7 +1065,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -1065,7 +1065,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
emit WithdrawalFinalized(_withdrawalHash, true); emit WithdrawalFinalized(_withdrawalHash, true);
optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); optimismPortal2.finalizeWithdrawalTransaction(_defaultTx);
vm.expectRevert("OptimismPortal: withdrawal has already been finalized"); vm.expectRevert(AlreadyFinalized.selector);
optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); optimismPortal2.finalizeWithdrawalTransaction(_defaultTx);
} }
...@@ -1258,7 +1258,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -1258,7 +1258,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1);
vm.expectRevert("OptimismPortal: dispute game has been blacklisted"); vm.expectRevert(Blacklisted.selector);
optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); optimismPortal2.finalizeWithdrawalTransaction(_defaultTx);
} }
...@@ -1318,7 +1318,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -1318,7 +1318,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
vm.prank(optimismPortal2.guardian()); vm.prank(optimismPortal2.guardian());
optimismPortal2.setRespectedGameType(GameType.wrap(0xFF)); optimismPortal2.setRespectedGameType(GameType.wrap(0xFF));
vm.expectRevert("OptimismPortal: invalid game type"); vm.expectRevert(InvalidGameType.selector);
optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); optimismPortal2.finalizeWithdrawalTransaction(_defaultTx);
} }
...@@ -1376,7 +1376,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -1376,7 +1376,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
// Warp 1 second in the future, past the proof maturity delay, and attempt to finalize the withdrawal. // Warp 1 second in the future, past the proof maturity delay, and attempt to finalize the withdrawal.
// This should also fail, since the dispute game has not resolved yet. // This should also fail, since the dispute game has not resolved yet.
vm.warp(block.timestamp + 1 seconds); vm.warp(block.timestamp + 1 seconds);
vm.expectRevert("OptimismPortal: output proposal has not been validated"); vm.expectRevert(ProposalNotValidated.selector);
optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); optimismPortal2.finalizeWithdrawalTransaction(_defaultTx);
// Finalize the dispute game and attempt to finalize the withdrawal again. This should also fail, since the // Finalize the dispute game and attempt to finalize the withdrawal again. This should also fail, since the
......
...@@ -239,9 +239,10 @@ contract DeputyGuardianModule_NoPortalCollisions_Test is DeputyGuardianModule_Te ...@@ -239,9 +239,10 @@ contract DeputyGuardianModule_NoPortalCollisions_Test is DeputyGuardianModule_Te
/// @dev tests that no function selectors in the L1 contracts collide with the OptimismPortal2 functions called by /// @dev tests that no function selectors in the L1 contracts collide with the OptimismPortal2 functions called by
/// the DeputyGuardianModule. /// the DeputyGuardianModule.
function test_noPortalCollisions_succeeds() external { function test_noPortalCollisions_succeeds() external {
string[] memory excludes = new string[](2); string[] memory excludes = new string[](3);
excludes[0] = "src/L1/OptimismPortal2.sol"; excludes[0] = "src/L1/OptimismPortal2.sol";
excludes[1] = "src/dispute/lib/*"; excludes[1] = "src/dispute/lib/*";
excludes[2] = "src/L1/OptimismPortalInterop.sol";
Abi[] memory abis = ForgeArtifacts.getContractFunctionAbis("src/{L1,dispute,universal}", excludes); Abi[] memory abis = ForgeArtifacts.getContractFunctionAbis("src/{L1,dispute,universal}", excludes);
for (uint256 i; i < abis.length; i++) { for (uint256 i; i < abis.length; i++) {
for (uint256 j; j < abis[i].entries.length; j++) { for (uint256 j; j < abis[i].entries.length; j++) {
......
...@@ -279,27 +279,50 @@ contract Specification_Test is CommonTest { ...@@ -279,27 +279,50 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("donateETH()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("donateETH()") });
_addSpec({ _addSpec({
_name: "OptimismPortalInterop", _name: "OptimismPortalInterop",
_sel: OptimismPortal.finalizeWithdrawalTransaction.selector, _sel: OptimismPortal2.finalizeWithdrawalTransaction.selector,
_pausable: true
});
_addSpec({
_name: "OptimismPortalInterop",
_sel: OptimismPortal2.finalizeWithdrawalTransactionExternalProof.selector,
_pausable: true _pausable: true
}); });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("finalizedWithdrawals(bytes32)") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("finalizedWithdrawals(bytes32)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("guardian()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("guardian()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("initialize(address,address,address)") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("initialize(address,address,address,uint32)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("isOutputFinalized(uint256)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("l2Oracle()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("l2Sender()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("l2Sender()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("minimumGasLimit(uint64)") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("minimumGasLimit(uint64)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("params()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("params()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("paused()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("paused()") });
_addSpec({ _addSpec({
_name: "OptimismPortalInterop", _name: "OptimismPortalInterop",
_sel: OptimismPortal.proveWithdrawalTransaction.selector, _sel: OptimismPortal2.proveWithdrawalTransaction.selector,
_pausable: true _pausable: true
}); });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("provenWithdrawals(bytes32)") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("provenWithdrawals(bytes32,address)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("superchainConfig()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("superchainConfig()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("systemConfig()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("systemConfig()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("version()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("version()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("disputeGameFactory()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("disputeGameBlacklist(address)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("respectedGameType()") });
// Comment out the auth to not disturb the testDeputyGuardianAuth test. This code is not meant to run in
// production,
// and will be merged into the OptimismPortal2 contract itself in the future.
_addSpec({
_name: "OptimismPortalInterop",
_sel: _getSel("blacklistDisputeGame(address)") /*, _auth: Role.GUARDIAN*/
});
_addSpec({
_name: "OptimismPortalInterop",
_sel: _getSel("setRespectedGameType(uint32)") /*, _auth: Role.GUARDIAN*/
});
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("checkWithdrawal(bytes32,address)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("proofMaturityDelaySeconds()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("disputeGameFinalityDelaySeconds()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("respectedGameTypeUpdatedAt()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("proofSubmitters(bytes32,uint256)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("numProofSubmitters(bytes32)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("balance()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("balance()") });
_addSpec({ _addSpec({
_name: "OptimismPortalInterop", _name: "OptimismPortalInterop",
......
...@@ -16,6 +16,7 @@ import { Types } from "src/libraries/Types.sol"; ...@@ -16,6 +16,7 @@ import { Types } from "src/libraries/Types.sol";
import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol";
import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Types.sol";
import "src/libraries/PortalErrors.sol";
contract OptimismPortal2_Depositor is StdUtils, ResourceMetering { contract OptimismPortal2_Depositor is StdUtils, ResourceMetering {
Vm internal vm; Vm internal vm;
...@@ -209,7 +210,7 @@ contract OptimismPortal2_CannotFinalizeTwice is OptimismPortal2_Invariant_Harnes ...@@ -209,7 +210,7 @@ contract OptimismPortal2_CannotFinalizeTwice is OptimismPortal2_Invariant_Harnes
/// Ensures that there is no chain of calls that can be made that allows a withdrawal to be /// Ensures that there is no chain of calls that can be made that allows a withdrawal to be
/// finalized twice. /// finalized twice.
function invariant_cannotFinalizeTwice() external { function invariant_cannotFinalizeTwice() external {
vm.expectRevert("OptimismPortal: withdrawal has already been finalized"); vm.expectRevert(AlreadyFinalized.selector);
optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); optimismPortal2.finalizeWithdrawalTransaction(_defaultTx);
} }
} }
......
...@@ -31,7 +31,7 @@ contract DeploymentSummary is DeploymentSummaryCode { ...@@ -31,7 +31,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567; address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567;
address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB; address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB;
address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131; address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131;
address internal constant optimismPortal2Address = 0x542e5F5d3934b6A8A8B4219cbc99D3D87a7137E1; address internal constant optimismPortal2Address = 0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b;
address internal constant optimismPortalProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4; address internal constant optimismPortalProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4;
address internal constant preimageOracleAddress = 0x3bd7E801E51d48c5d94Ea68e8B801DFFC275De75; address internal constant preimageOracleAddress = 0x3bd7E801E51d48c5d94Ea68e8B801DFFC275De75;
address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F; address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -31,7 +31,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { ...@@ -31,7 +31,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567; address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567;
address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB; address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB;
address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131; address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131;
address internal constant optimismPortal2Address = 0x542e5F5d3934b6A8A8B4219cbc99D3D87a7137E1; address internal constant optimismPortal2Address = 0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b;
address internal constant optimismPortalProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4; address internal constant optimismPortalProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4;
address internal constant preimageOracleAddress = 0x3bd7E801E51d48c5d94Ea68e8B801DFFC275De75; address internal constant preimageOracleAddress = 0x3bd7E801E51d48c5d94Ea68e8B801DFFC275De75;
address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F; address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F;
...@@ -431,7 +431,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { ...@@ -431,7 +431,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
value = hex"0000000000000000000000000000000000000000000000000000000000000003"; value = hex"0000000000000000000000000000000000000000000000000000000000000003";
vm.store(systemOwnerSafeAddress, slot, value); vm.store(systemOwnerSafeAddress, slot, value);
slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
value = hex"000000000000000000000000542e5f5d3934b6a8a8b4219cbc99d3d87a7137e1"; value = hex"000000000000000000000000ae5dadfc48928543f706a9e6ce25c682aad2b63b";
vm.store(optimismPortalProxyAddress, slot, value); vm.store(optimismPortalProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001"; value = hex"0000000000000000000000000000000000000000000000000000000000000001";
......
...@@ -147,6 +147,7 @@ contract CommonTest is Test, Setup, Events { ...@@ -147,6 +147,7 @@ contract CommonTest is Test, Setup, Events {
revert("CommonTest: Cannot enable interop after deployment. Consider overriding `setUp`."); revert("CommonTest: Cannot enable interop after deployment. Consider overriding `setUp`.");
} }
useFaultProofs = true;
useInteropOverride = true; useInteropOverride = true;
} }
} }
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