Skip to content

Commit

Permalink
diff from l2oo, tests still failing
Browse files Browse the repository at this point in the history
  • Loading branch information
zobront committed Jul 26, 2024
1 parent feff800 commit 44f611a
Show file tree
Hide file tree
Showing 11 changed files with 304 additions and 1,250 deletions.
13 changes: 8 additions & 5 deletions packages/contracts-bedrock/deploy-config/hardhat.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
"l2OutputOracleSubmissionInterval": 6,
"l2OutputOracleStartingTimestamp": 1,
"l2OutputOracleStartingBlockNumber": 1,
"l2OutputOracleSubmissionInterval": 900,
"l2OutputOracleStartingTimestamp": 1721925325,
"l2OutputOracleStartingBlockNumber": 123163274,
"gasPriceOracleBaseFeeScalar": 1368,
"gasPriceOracleBlobBaseFeeScalar": 810949,
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
Expand All @@ -35,7 +35,7 @@
"governanceTokenName": "Optimism",
"governanceTokenSymbol": "OP",
"governanceTokenOwner": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"finalizationPeriodSeconds": 36,
"finalizationPeriodSeconds": 0,
"eip1559Denominator": 50,
"eip1559DenominatorCanyon": 250,
"eip1559Elasticity": 10,
Expand All @@ -62,5 +62,8 @@
"daChallengeWindow": 100,
"daResolveWindow": 100,
"daBondSize": 1000,
"daResolverRefundPercentage": 50
"daResolverRefundPercentage": 50,
"zkVKey": "0x003de3cfc15f7b7e2844f33380b8dde65e0cc65de4f7a27e8b3422d376d982f4",
"l2OutputOracleStartingOutputRoot": "0xd1e578c114d50dbb4431e81f737481b7d07204a35d5968c4b911ec55ba038ed6",
"verifierGateway": "0x0000000000000000000000000000000000000000"
}
68 changes: 1 addition & 67 deletions packages/contracts-bedrock/scripts/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol";
import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { ZKL2OutputOracle } from "src/L1/ZKL2OutputOracle.sol";
import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol";
import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
Expand Down Expand Up @@ -285,7 +284,6 @@ contract Deploy is Deployer {

/// @notice Internal function containing the deploy logic.
function _run() internal virtual {
require(!(cfg.useZK() && cfg.useFaultProofs()), "Deploy: ZK and Fault Proofs are mutually exclusive. Please update config json.");
console.log("start of L1 Deploy!");
deploySafe("SystemOwnerSafe");
console.log("deployed Safe!");
Expand Down Expand Up @@ -386,7 +384,6 @@ contract Deploy is Deployer {
deployL1ERC721Bridge();
deployOptimismPortal();
deployL2OutputOracle();
deployZKL2OutputOracle();

// Fault proofs
deployOptimismPortal2();
Expand Down Expand Up @@ -414,12 +411,7 @@ contract Deploy is Deployer {
initializeL1ERC721Bridge();
initializeOptimismMintableERC20Factory();
initializeL1CrossDomainMessenger();
if (cfg.useZK()) {
console.log("ZK enabled. Initializing the L2OutputOracle proxy with the ZKL2OutputOracle.");
initializeZKL2OutputOracle();
} else {
initializeL2OutputOracle();
}
initializeL2OutputOracle();
initializeDisputeGameFactory();
initializeDelayedWETH();
initializeAnchorStateRegistry();
Expand Down Expand Up @@ -715,29 +707,6 @@ contract Deploy is Deployer {
addr_ = address(oracle);
}

/// @notice Deploy the L2OutputOracle
function deployZKL2OutputOracle() public broadcast returns (address addr_) {
console.log("Deploying ZKL2OutputOracle implementation");
ZKL2OutputOracle oracle = new ZKL2OutputOracle{ salt: _implSalt() }();

save("ZKL2OutputOracle", address(oracle));
console.log("ZKL2OutputOracle deployed at %s", address(oracle));

// Override the `L2OutputOracle` contract to the deployed implementation. This is necessary
// to check the `L2OutputOracle` implementation alongside dependent contracts, which
// are always proxies.
Types.ContractSet memory contracts = _proxiesUnstrict();
contracts.L2OutputOracle = address(oracle);
ChainAssertions.checkL2OutputOracle({
_contracts: contracts,
_cfg: cfg,
_l2OutputOracleStartingTimestamp: 0,
_isProxy: false
});

addr_ = address(oracle);
}

/// @notice Deploy the OptimismMintableERC20Factory
function deployOptimismMintableERC20Factory() public broadcast returns (address addr_) {
console.log("Deploying OptimismMintableERC20Factory implementation");
Expand Down Expand Up @@ -1232,41 +1201,6 @@ contract Deploy is Deployer {
_implementation: l2OutputOracle,
_innerCallData: abi.encodeCall(
L2OutputOracle.initialize,
(
cfg.l2OutputOracleSubmissionInterval(),
cfg.l2BlockTime(),
cfg.l2OutputOracleStartingBlockNumber(),
cfg.l2OutputOracleStartingTimestamp(),
cfg.l2OutputOracleProposer(),
cfg.l2OutputOracleChallenger(),
cfg.finalizationPeriodSeconds()
)
)
});

L2OutputOracle oracle = L2OutputOracle(l2OutputOracleProxy);
string memory version = oracle.version();
console.log("L2OutputOracle version: %s", version);

ChainAssertions.checkL2OutputOracle({
_contracts: _proxies(),
_cfg: cfg,
_l2OutputOracleStartingTimestamp: cfg.l2OutputOracleStartingTimestamp(),
_isProxy: true
});
}

/// @notice Initialize the L2OutputOracle
function initializeZKL2OutputOracle() public broadcast {
console.log("Upgrading and initializing L2OutputOracle proxy");
address l2OutputOracleProxy = mustGetAddress("L2OutputOracleProxy");
address l2OutputOracle = mustGetAddress("ZKL2OutputOracle");

_upgradeAndCallViaSafe({
_proxy: payable(l2OutputOracleProxy),
_implementation: l2OutputOracle,
_innerCallData: abi.encodeCall(
ZKL2OutputOracle.initialize,
(
cfg.l2OutputOracleSubmissionInterval(),
cfg.l2BlockTime(),
Expand Down
22 changes: 1 addition & 21 deletions packages/contracts-bedrock/scripts/DeployConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ contract DeployConfig is Script {
uint256 public daResolveWindow;
uint256 public daBondSize;
uint256 public daResolverRefundPercentage;
bool public useZK;
bytes32 public zkVKey;
bytes32 public l2OutputOracleStartingOutputRoot;
address public verifierGateway;
Expand Down Expand Up @@ -140,7 +139,6 @@ contract DeployConfig is Script {
disputeGameFinalityDelaySeconds = _readOr(_json, "$.disputeGameFinalityDelaySeconds", uint256(0));
respectedGameType = _readOr(_json, "$.respectedGameType", uint256(0));

useZK = _readOr(_json, "$.useZK", false);
zkVKey = _readOr(_json, "$.zkVKey", bytes32(0));
l2OutputOracleStartingOutputRoot = _readOr(_json, "$.l2OutputOracleStartingOutputRoot", bytes32(0));
verifierGateway = _readOr(_json, "$.verifierGateway", 0x3B6041173B80E77f038f3F2C0f9744f04837185e);
Expand Down Expand Up @@ -214,26 +212,8 @@ contract DeployConfig is Script {
}

/// @notice Allow the `useZK` config to be overridden in testing environments
function setUseZK(
bool _useZK,
bytes32 _zkVKey,
bytes32 _startingL2OutputRoot,
uint256 _startingL2OutputTimestamp,
uint256 _startingL2OutputBlockNumber,
uint256 _submissionInterval,
address _verifierGateway
) public {
useZK = _useZK;
zkVKey = _zkVKey;

l2OutputOracleStartingOutputRoot = _startingL2OutputRoot;
_l2OutputOracleStartingTimestamp = int256(_startingL2OutputTimestamp);
l2OutputOracleStartingBlockNumber = _startingL2OutputBlockNumber;

l2OutputOracleSubmissionInterval = _submissionInterval;
function setVerifierGateway(address _verifierGateway) public {
verifierGateway = _verifierGateway;

finalizationPeriodSeconds = 0;
}

/// @notice Allow the `fundDevAccounts` config to be overridden.
Expand Down
87 changes: 68 additions & 19 deletions packages/contracts-bedrock/src/L1/L2OutputOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable
import { ISemver } from "src/universal/ISemver.sol";
import { Types } from "src/libraries/Types.sol";
import { Constants } from "src/libraries/Constants.sol";
import { SP1VerifierGateway } from "@sp1-contracts/src/SP1VerifierGateway.sol";

/// @custom:proxied
/// @title L2OutputOracle
Expand Down Expand Up @@ -41,6 +42,21 @@ contract L2OutputOracle is Initializable, ISemver {
/// @custom:network-specific
uint256 public finalizationPeriodSeconds;

uint public chainId;

bytes32 public vkey;
SP1VerifierGateway public verifierGateway;

mapping (uint => bytes32) public historicBlockHashes;

struct PublicValuesStruct {
bytes32 l1Head;
bytes32 l2PreRoot;
bytes32 claimRoot;
uint256 claimBlockNum;
uint256 chainId;
}

/// @notice Emitted when an output is proposed.
/// @param outputRoot The output root.
/// @param l2OutputIndex The index of the output in the l2Outputs array.
Expand All @@ -57,7 +73,7 @@ contract L2OutputOracle is Initializable, ISemver {

/// @notice Semantic version.
/// @custom:semver 1.8.0
string public constant version = "1.8.0";
string public constant version = "1.0.0";

/// @notice Constructs the L2OutputOracle contract. Initializes variables to the same values as
/// in the getting-started config.
Expand All @@ -69,7 +85,11 @@ contract L2OutputOracle is Initializable, ISemver {
_startingTimestamp: 0,
_proposer: address(0),
_challenger: address(0),
_finalizationPeriodSeconds: 0
_finalizationPeriodSeconds: 0,
_chainId: 0,
_vkey: bytes32(0),
_startingOutputRoot: bytes32(0),
_verifierGateway: address(0)
});
}

Expand All @@ -82,14 +102,21 @@ contract L2OutputOracle is Initializable, ISemver {
/// @param _challenger The address of the challenger.
/// @param _finalizationPeriodSeconds The minimum time (in seconds) that must elapse before a withdrawal
/// can be finalized.
/// @param _chainId The chain ID of the L2 chain.
/// @param _vkey The verification key of the SP1 program.
/// @param _startingOutputRoot The output root of the starting block.
function initialize(
uint256 _submissionInterval,
uint256 _l2BlockTime,
uint256 _startingBlockNumber,
uint256 _startingTimestamp,
address _proposer,
address _challenger,
uint256 _finalizationPeriodSeconds
uint256 _finalizationPeriodSeconds,
uint256 _chainId,
bytes32 _vkey,
bytes32 _startingOutputRoot,
address _verifierGateway
)
public
initializer
Expand All @@ -108,6 +135,17 @@ contract L2OutputOracle is Initializable, ISemver {
proposer = _proposer;
challenger = _challenger;
finalizationPeriodSeconds = _finalizationPeriodSeconds;
chainId = _chainId;
vkey = _vkey;
verifierGateway = SP1VerifierGateway(_verifierGateway);

l2Outputs.push(
Types.OutputProposal({
outputRoot: _startingOutputRoot,
timestamp: uint128(_startingTimestamp),
l2BlockNumber: uint128(_startingBlockNumber)
})
);
}

/// @notice Getter for the submissionInterval.
Expand Down Expand Up @@ -189,12 +227,13 @@ contract L2OutputOracle is Initializable, ISemver {
bytes32 _outputRoot,
uint256 _l2BlockNumber,
bytes32 _l1BlockHash,
uint256 _l1BlockNumber
uint256 _l1BlockNumber,
bytes memory _proof
)
external
payable
{
require(msg.sender == proposer, "L2OutputOracle: only the proposer address can propose new outputs");
require(msg.sender == proposer || proposer == address(0), "L2OutputOracle: only the proposer address can propose new outputs");

require(
_l2BlockNumber == nextBlockNumber(),
Expand All @@ -208,20 +247,20 @@ contract L2OutputOracle is Initializable, ISemver {

require(_outputRoot != bytes32(0), "L2OutputOracle: L2 output proposal cannot be the zero hash");

if (_l1BlockHash != bytes32(0)) {
// This check allows the proposer to propose an output based on a given L1 block,
// without fear that it will be reorged out.
// It will also revert if the blockheight provided is more than 256 blocks behind the
// chain tip (as the hash will return as zero). This does open the door to a griefing
// attack in which the proposer's submission is censored until the block is no longer
// retrievable, if the proposer is experiencing this attack it can simply leave out the
// blockhash value, and delay submission until it is confident that the L1 block is
// finalized.
require(
blockhash(_l1BlockNumber) == _l1BlockHash,
"L2OutputOracle: block hash does not match the hash at the expected height"
);
}
require(
historicBlockHashes[_l1BlockNumber] == _l1BlockHash,
"L2OutputOracle: block hash does not match the hash at the expected height"
);

PublicValuesStruct memory publicValues = PublicValuesStruct({
l1Head: _l1BlockHash,
l2PreRoot: l2Outputs[nextOutputIndex() - 1].outputRoot,
claimRoot: _outputRoot,
claimBlockNum: _l2BlockNumber,
chainId: chainId
});

verifierGateway.verifyProof(vkey, abi.encode(publicValues), _proof);

emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp);

Expand All @@ -234,6 +273,16 @@ contract L2OutputOracle is Initializable, ISemver {
);
}

// TODO: This should be safe against reorgs because if the block is reorged out, this will be too.
// Think more about this to confirm.
function checkpointBlockHash(uint256 _blockNumber, bytes32 _blockHash) external {
require(
blockhash(_blockNumber) == _blockHash,
"L2OutputOracle: block hash does not match the hash at the expected height"
);
historicBlockHashes[_blockNumber] = _blockHash;
}

/// @notice Returns an output by index. Needed to return a struct instead of a tuple.
/// @param _l2OutputIndex Index of the output to return.
/// @return The output at the given index.
Expand Down
Loading

0 comments on commit 44f611a

Please sign in to comment.