diff --git a/bindings/go/sequencersoloclient/SequencerSoloClient.go b/bindings/go/sequencersoloclient/SequencerSoloClient.go index 130262dc..b9482d7b 100644 --- a/bindings/go/sequencersoloclient/SequencerSoloClient.go +++ b/bindings/go/sequencersoloclient/SequencerSoloClient.go @@ -51,7 +51,7 @@ type OpIcs23ProofPath struct { // SequencerSoloClientMetaData contains all meta data concerning the SequencerSoloClient contract. var SequencerSoloClientMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"verifier_\",\"type\":\"address\",\"internalType\":\"contractISignatureVerifier\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"LIGHT_CLIENT_TYPE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumLightClientType\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"consensusStates\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getState\",\"inputs\":[{\"name\":\"height\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"appHash\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"updateClient\",\"inputs\":[{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"peptideHeight\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"peptideAppHash\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"verifier\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractISignatureVerifier\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyMembership\",\"inputs\":[{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIcs23Proof\",\"components\":[{\"name\":\"proof\",\"type\":\"tuple[]\",\"internalType\":\"structOpIcs23Proof[]\",\"components\":[{\"name\":\"path\",\"type\":\"tuple[]\",\"internalType\":\"structOpIcs23ProofPath[]\",\"components\":[{\"name\":\"prefix\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"suffix\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"key\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"prefix\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"height\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"key\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"expectedValue\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyNonMembership\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIcs23Proof\",\"components\":[{\"name\":\"proof\",\"type\":\"tuple[]\",\"internalType\":\"structOpIcs23Proof[]\",\"components\":[{\"name\":\"path\",\"type\":\"tuple[]\",\"internalType\":\"structOpIcs23ProofPath[]\",\"components\":[{\"name\":\"prefix\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"suffix\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"key\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"prefix\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"height\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"error\",\"name\":\"AppHashHasNotPassedFraudProofWindow\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotUpdatePendingOptimisticConsensusState\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoConsensusStateAtHeight\",\"inputs\":[{\"name\":\"height\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"NonMembershipProofsNotYetImplemented\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"verifier_\",\"type\":\"address\",\"internalType\":\"contractISignatureVerifier\"},{\"name\":\"_l1BlockProvider\",\"type\":\"address\",\"internalType\":\"contractL1Block\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"LIGHT_CLIENT_TYPE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumLightClientType\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"consensusStates\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getState\",\"inputs\":[{\"name\":\"height\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"appHash\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"l1BlockProvider\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractL1Block\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"updateClient\",\"inputs\":[{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"peptideHeight\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"peptideAppHash\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"verifier\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractISignatureVerifier\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyMembership\",\"inputs\":[{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIcs23Proof\",\"components\":[{\"name\":\"proof\",\"type\":\"tuple[]\",\"internalType\":\"structOpIcs23Proof[]\",\"components\":[{\"name\":\"path\",\"type\":\"tuple[]\",\"internalType\":\"structOpIcs23ProofPath[]\",\"components\":[{\"name\":\"prefix\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"suffix\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"key\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"prefix\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"height\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"key\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"expectedValue\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyNonMembership\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIcs23Proof\",\"components\":[{\"name\":\"proof\",\"type\":\"tuple[]\",\"internalType\":\"structOpIcs23Proof[]\",\"components\":[{\"name\":\"path\",\"type\":\"tuple[]\",\"internalType\":\"structOpIcs23ProofPath[]\",\"components\":[{\"name\":\"prefix\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"suffix\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"key\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"prefix\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"height\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"error\",\"name\":\"AppHashHasNotPassedFraudProofWindow\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotUpdateClientWithDifferentAppHash\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidL1Origin\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoConsensusStateAtHeight\",\"inputs\":[{\"name\":\"height\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"NonMembershipProofsNotYetImplemented\",\"inputs\":[]}]", } // SequencerSoloClientABI is the input ABI used to generate the binding from. @@ -293,6 +293,37 @@ func (_SequencerSoloClient *SequencerSoloClientCallerSession) GetState(height *b return _SequencerSoloClient.Contract.GetState(&_SequencerSoloClient.CallOpts, height) } +// L1BlockProvider is a free data retrieval call binding the contract method 0xeb772058. +// +// Solidity: function l1BlockProvider() view returns(address) +func (_SequencerSoloClient *SequencerSoloClientCaller) L1BlockProvider(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _SequencerSoloClient.contract.Call(opts, &out, "l1BlockProvider") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// L1BlockProvider is a free data retrieval call binding the contract method 0xeb772058. +// +// Solidity: function l1BlockProvider() view returns(address) +func (_SequencerSoloClient *SequencerSoloClientSession) L1BlockProvider() (common.Address, error) { + return _SequencerSoloClient.Contract.L1BlockProvider(&_SequencerSoloClient.CallOpts) +} + +// L1BlockProvider is a free data retrieval call binding the contract method 0xeb772058. +// +// Solidity: function l1BlockProvider() view returns(address) +func (_SequencerSoloClient *SequencerSoloClientCallerSession) L1BlockProvider() (common.Address, error) { + return _SequencerSoloClient.Contract.L1BlockProvider(&_SequencerSoloClient.CallOpts) +} + // Verifier is a free data retrieval call binding the contract method 0x2b7ac3f3. // // Solidity: function verifier() view returns(address) diff --git a/contracts/core/SequencerSignatureVerifier.sol b/contracts/core/SequencerSignatureVerifier.sol index b6c6abc3..6cfca761 100644 --- a/contracts/core/SequencerSignatureVerifier.sol +++ b/contracts/core/SequencerSignatureVerifier.sol @@ -23,16 +23,17 @@ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {AppStateVerifier} from "../base/AppStateVerifier.sol"; /** - * @title OptimisticProofVerifier - * @notice Verifies proofs related to Optimistic Rollup state updates + * @title SequencerSignatureVerifier + * @notice Verifies ECDSA signatures from a sequencer for client updates. Is used by the SequencerSoloClient to verify + * signatures on client updates. * @author Polymer Labs */ contract SequencerSignatureVerifier is AppStateVerifier, ISignatureVerifier { using RLPReader for RLPReader.RLPItem; using RLPReader for bytes; - // @notice known L2 Output Oracle contract address to verify state update proofs against - address public immutable SEQUENCER; + address public immutable SEQUENCER; // The trusted sequencer address that polymer p2p signer holds the private key + // to bytes32 public immutable CHAIN_ID; // Chain ID of the L2 chain for which the sequencer signs over constructor(address sequencer_, bytes32 chainId_) { @@ -40,6 +41,14 @@ contract SequencerSignatureVerifier is AppStateVerifier, ISignatureVerifier { CHAIN_ID = chainId_; } + /** + * @notice Verifies that the sequencer signature is valid for a given l1 origin. This is used by the + * SequencerSoloClient update client method. + * @param l2BlockNumber The block number of the L2 block that the state update is for + * @param appHash The app hash of the state update to be saved in the parent soloClient contract + * @param l1BlockHash The hash of the L1 origin that the peptide height corresponds to + * @param signature The sequencer's ECDSA over the state update + */ function verifyStateUpdate(uint256 l2BlockNumber, bytes32 appHash, bytes32 l1BlockHash, bytes calldata signature) external view @@ -47,6 +56,10 @@ contract SequencerSignatureVerifier is AppStateVerifier, ISignatureVerifier { _verifySequencerSignature(l2BlockNumber, appHash, l1BlockHash, signature); } + /** + * @notice Verify the ECDSA signature of the sequencer over the given l2BLockNumber, peptideAppHash, and origin + * l1BlockHash + */ function _verifySequencerSignature( uint256 l2BlockNumber, bytes32 appHash, diff --git a/contracts/core/SequencerSoloClient.sol b/contracts/core/SequencerSoloClient.sol index 975503b4..464c68a4 100644 --- a/contracts/core/SequencerSoloClient.sol +++ b/contracts/core/SequencerSoloClient.sol @@ -20,45 +20,51 @@ pragma solidity 0.8.15; import {Ics23Proof} from "../interfaces/IProofVerifier.sol"; import {ISignatureVerifier} from "../interfaces/ISignatureVerifier.sol"; import {ILightClient, LightClientType} from "../interfaces/ILightClient.sol"; +import {L1Block} from "optimism/L2/L1Block.sol"; /** - * @title SubfinalityLightClient + * @title SequencerSoloClient * @author Polymer Labs - * @dev This specific light client implementation uses the same client that is used in the op-stack + * @dev This light client implementation verifies a single signature by the polymer p2p-signer, and updates the light + * client if valid signatures are provided. */ contract SequencerSoloClient is ILightClient { LightClientType public constant LIGHT_CLIENT_TYPE = LightClientType.SequencerLightClient; // Stored as a constant // for cheap on-chain use + + ISignatureVerifier public immutable verifier; + L1Block public immutable l1BlockProvider; + uint8 private _LightClientType = uint8(LIGHT_CLIENT_TYPE); // Also redundantly stored as a private mutable type in // case it needs to be accessed in any proofs - // consensusStates maps from the height to the appHash. + // consensusStates maps from the height to the appHash, and is modified during state updates if it is a valid state + // update. mapping(uint256 => uint256) public consensusStates; - ISignatureVerifier public immutable verifier; - - error CannotUpdatePendingOptimisticConsensusState(); + error InvalidL1Origin(); + error CannotUpdateClientWithDifferentAppHash(); error AppHashHasNotPassedFraudProofWindow(); error NonMembershipProofsNotYetImplemented(); error NoConsensusStateAtHeight(uint256 height); - constructor(ISignatureVerifier verifier_) { + constructor(ISignatureVerifier verifier_, L1Block _l1BlockProvider) { verifier = verifier_; + l1BlockProvider = _l1BlockProvider; } /** * @inheritdoc ILightClient * @param proof An array of bytes that contain the l1blockhash and the sequencer's signature. The first 32 bytes of - * this argument should be - * the l1BlockHash, and the remaining bytes should be the sequencer signature which attests to the peptide AppHash + * this argument should be the l1BlockHash, and the remaining bytes should be the sequencer signature which attests + * to the peptide AppHash * for that l1BlockHash */ function updateClient(bytes calldata proof, uint256 peptideHeight, uint256 peptideAppHash) external override { - if (consensusStates[peptideHeight] != 0) { - return; + if (l1BlockProvider.hash() != bytes32(proof[:32])) { + revert InvalidL1Origin(); } - verifier.verifyStateUpdate(peptideHeight, bytes32(peptideAppHash), bytes32(proof[:32]), proof[32:]); - consensusStates[peptideHeight] = peptideAppHash; + _updateClient(proof, peptideHeight, peptideAppHash); } /** @@ -67,10 +73,10 @@ contract SequencerSoloClient is ILightClient { function getState(uint256 height) external view returns (uint256 appHash) { return _getState(height); } + /** * @inheritdoc ILightClient */ - function verifyMembership(Ics23Proof calldata proof, bytes calldata key, bytes calldata expectedValue) external view @@ -88,6 +94,20 @@ contract SequencerSoloClient is ILightClient { revert NonMembershipProofsNotYetImplemented(); } + function _updateClient(bytes calldata proof, uint256 peptideHeight, uint256 peptideAppHash) internal { + if (consensusStates[peptideHeight] != 0) { + // Note: we don't cache consensusStates[peptideHeight] in mem for gas savings here because this if statement + // would not be triggered too often, and would make the more frequent branch more expensive due to mem + // allocation. + if (consensusStates[peptideHeight] != peptideAppHash) { + revert CannotUpdateClientWithDifferentAppHash(); + } + return; + } + verifier.verifyStateUpdate(peptideHeight, bytes32(peptideAppHash), bytes32(proof[:32]), proof[32:]); + consensusStates[peptideHeight] = peptideAppHash; + } + /** * @dev Returns the internal state of the light client at a given height. */ diff --git a/package.json b/package.json index b548ec70..2b7d2233 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@open-ibc/vibc-core-smart-contracts", - "version": "4.0.4", + "version": "4.0.5", "main": "dist/index.js", "bin": { "verify-vibc-core-smart-contracts": "./dist/scripts/verify-contract-script.js", diff --git a/specs/update.spec.yaml b/specs/update.spec.yaml index 6b6c43ce..d61b1572 100644 --- a/specs/update.spec.yaml +++ b/specs/update.spec.yaml @@ -65,6 +65,7 @@ deployer: 'KEY_DEPLOYER' deployArgs: - '{{SequencerSigVerifier}}' + - '{{L1BlockAddress}}' - name: DummyLightClient description: 'DummyLightClient' diff --git a/src/evm/contracts/SequencerSoloClient.ts b/src/evm/contracts/SequencerSoloClient.ts index 6489ce00..f7fb88c4 100644 --- a/src/evm/contracts/SequencerSoloClient.ts +++ b/src/evm/contracts/SequencerSoloClient.ts @@ -62,6 +62,7 @@ export interface SequencerSoloClientInterface extends Interface { | "LIGHT_CLIENT_TYPE" | "consensusStates" | "getState" + | "l1BlockProvider" | "updateClient" | "verifier" | "verifyMembership" @@ -80,6 +81,10 @@ export interface SequencerSoloClientInterface extends Interface { functionFragment: "getState", values: [BigNumberish] ): string; + encodeFunctionData( + functionFragment: "l1BlockProvider", + values?: undefined + ): string; encodeFunctionData( functionFragment: "updateClient", values: [BytesLike, BigNumberish, BigNumberish] @@ -103,6 +108,10 @@ export interface SequencerSoloClientInterface extends Interface { data: BytesLike ): Result; decodeFunctionResult(functionFragment: "getState", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "l1BlockProvider", + data: BytesLike + ): Result; decodeFunctionResult( functionFragment: "updateClient", data: BytesLike @@ -167,6 +176,8 @@ export interface SequencerSoloClient extends BaseContract { getState: TypedContractMethod<[height: BigNumberish], [bigint], "view">; + l1BlockProvider: TypedContractMethod<[], [string], "view">; + updateClient: TypedContractMethod< [ proof: BytesLike, @@ -204,6 +215,9 @@ export interface SequencerSoloClient extends BaseContract { getFunction( nameOrSignature: "getState" ): TypedContractMethod<[height: BigNumberish], [bigint], "view">; + getFunction( + nameOrSignature: "l1BlockProvider" + ): TypedContractMethod<[], [string], "view">; getFunction( nameOrSignature: "updateClient" ): TypedContractMethod< diff --git a/src/evm/contracts/factories/SequencerSignatureVerifier__factory.ts b/src/evm/contracts/factories/SequencerSignatureVerifier__factory.ts index ab64884e..a763ff53 100644 --- a/src/evm/contracts/factories/SequencerSignatureVerifier__factory.ts +++ b/src/evm/contracts/factories/SequencerSignatureVerifier__factory.ts @@ -292,7 +292,7 @@ const _abi = [ ] as const; const _bytecode = - "0x60c060405234801561001057600080fd5b50604051610e39380380610e3983398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a051610d896100b06000396000818160ba0152610584015260008181607601526105ee0152610d896000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632a6ded741461005c57806375fd4ca91461007157806385e1f4d0146100b5578063c2f0329f146100ea578063e8d90039146100fd575b600080fd5b61006f61006a3660046109a3565b610110565b005b6100987f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100dc7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100ac565b61006f6100f8366004610a16565b610129565b61006f61010b366004610ab2565b610313565b604051632974974360e01b815260040160405180910390fd5b6101338180610b13565b600081811061014457610144610b5d565b90506020028101906101569190610b73565b610164906020810190610b93565b604051610172929190610bda565b6040518091039020858560405161018a929190610bda565b6040518091039020146101b05760405163026a287560e51b815260040160405180910390fd5b6101ba8180610b13565b60008181106101cb576101cb610b5d565b90506020028101906101dd9190610b73565b6101eb906040810190610b93565b6040516101f9929190610bda565b60405180910390208383604051610211929190610bda565b604051809103902014610237576040516310d9300f60e11b815260040160405180910390fd5b61026c6102448280610b13565b600081811061025557610255610b5d565b90506020028101906102679190610b73565b610327565b6102768280610b13565b600181811061028757610287610b5d565b90506020028101906102999190610b73565b6102a7906040810190610b93565b6102b091610bea565b146102ce57604051636589f0e160e11b815260040160405180910390fd5b6102ec6102db8280610b13565b600181811061025557610255610b5d565b861461030b576040516392cb8fbb60e01b815260040160405180910390fd5b505050505050565b610320858585858561054b565b5050505050565b60008060026103396040850185610b93565b604051610347929190610bda565b602060405180830381855afa158015610364573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103879190610c08565b905060026103986060850185610b93565b6103af6103a86020880188610b93565b9050610659565b6103bc6020880188610b93565b6103c66020610659565b876040516020016103dd9796959493929190610c5c565b60408051601f19818403018152908290526103f791610ca0565b602060405180830381855afa158015610414573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104379190610c08565b915060005b6104468480610b13565b905081101561054457600261045b8580610b13565b8381811061046b5761046b610b5d565b905060200281019061047d9190610cb3565b6104879080610b93565b856104928880610b13565b868181106104a2576104a2610b5d565b90506020028101906104b49190610cb3565b6104c2906020810190610b93565b6040516020016104d6959493929190610cc9565b60408051601f19818403018152908290526104f091610ca0565b602060405180830381855afa15801561050d573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105309190610c08565b92508061053c81610cf1565b91505061043c565b5050919050565b604080516020808201889052818301879052606080830187905283518084039091018152608083018452805190820120600060a08401527f000000000000000000000000000000000000000000000000000000000000000060c084015260e080840191909152835180840390910181526101008301808552815191830191909120601f860183900490920283016101209081019094528481526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169361063293879187918291018382808284376000920191909152506106c892505050565b6001600160a01b031614610320576040516339e27c8560e21b815260040160405180910390fd5b6060805b6080831061069b578083607f1660801760f81b604051602001610681929190610d18565b60408051601f198184030190525260079290921c9161065d565b808360f81b6040516020016106b1929190610d18565b604051602081830303815290604052915050919050565b60008060006106d785856106ee565b915091506106e481610733565b5090505b92915050565b60008082516041036107245760208301516040840151606085015160001a61071887828585610885565b9450945050505061072c565b506000905060025b9250929050565b600081600481111561074757610747610d3d565b0361074f5750565b600181600481111561076357610763610d3d565b036107b55760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b60028160048111156107c9576107c9610d3d565b036108165760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016107ac565b600381600481111561082a5761082a610d3d565b036108825760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016107ac565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156108bc5750600090506003610940565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015610910573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661093957600060019250925050610940565b9150600090505b94509492505050565b60008083601f84011261095b57600080fd5b50813567ffffffffffffffff81111561097357600080fd5b60208301915083602082850101111561072c57600080fd5b60006040828403121561099d57600080fd5b50919050565b600080600080606085870312156109b957600080fd5b84359350602085013567ffffffffffffffff808211156109d857600080fd5b6109e488838901610949565b909550935060408701359150808211156109fd57600080fd5b50610a0a8782880161098b565b91505092959194509250565b60008060008060008060808789031215610a2f57600080fd5b86359550602087013567ffffffffffffffff80821115610a4e57600080fd5b610a5a8a838b01610949565b90975095506040890135915080821115610a7357600080fd5b610a7f8a838b01610949565b90955093506060890135915080821115610a9857600080fd5b50610aa589828a0161098b565b9150509295509295509295565b600080600080600060808688031215610aca57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115610af657600080fd5b610b0288828901610949565b969995985093965092949392505050565b6000808335601e19843603018112610b2a57600080fd5b83018035915067ffffffffffffffff821115610b4557600080fd5b6020019150600581901b360382131561072c57600080fd5b634e487b7160e01b600052603260045260246000fd5b60008235607e19833603018112610b8957600080fd5b9190910192915050565b6000808335601e19843603018112610baa57600080fd5b83018035915067ffffffffffffffff821115610bc557600080fd5b60200191503681900382131561072c57600080fd5b8183823760009101908152919050565b803560208310156106e857600019602084900360031b1b1692915050565b600060208284031215610c1a57600080fd5b5051919050565b6000815160005b81811015610c425760208185018101518683015201610c28565b81811115610c51576000828601525b509290920192915050565b86888237600087820160008152610c738189610c21565b9050858782376000908601908152610c8b8186610c21565b93845250506020909101979650505050505050565b6000610cac8284610c21565b9392505050565b60008235603e19833603018112610b8957600080fd5b8486823760008582018581528385602083013760009301602001928352509095945050505050565b600060018201610d1157634e487b7160e01b600052601160045260246000fd5b5060010190565b6000610d248285610c21565b6001600160f81b03199390931683525050600101919050565b634e487b7160e01b600052602160045260246000fdfea26469706673582212204c0012eebe28f63fe39b9984570299ceb809e22dea601def9f555ce47d4bfdc664736f6c634300080f0033"; + "0x60c060405234801561001057600080fd5b50604051610e39380380610e3983398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a051610d896100b06000396000818160ba0152610584015260008181607601526105ee0152610d896000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632a6ded741461005c57806375fd4ca91461007157806385e1f4d0146100b5578063c2f0329f146100ea578063e8d90039146100fd575b600080fd5b61006f61006a3660046109a3565b610110565b005b6100987f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100dc7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100ac565b61006f6100f8366004610a16565b610129565b61006f61010b366004610ab2565b610313565b604051632974974360e01b815260040160405180910390fd5b6101338180610b13565b600081811061014457610144610b5d565b90506020028101906101569190610b73565b610164906020810190610b93565b604051610172929190610bda565b6040518091039020858560405161018a929190610bda565b6040518091039020146101b05760405163026a287560e51b815260040160405180910390fd5b6101ba8180610b13565b60008181106101cb576101cb610b5d565b90506020028101906101dd9190610b73565b6101eb906040810190610b93565b6040516101f9929190610bda565b60405180910390208383604051610211929190610bda565b604051809103902014610237576040516310d9300f60e11b815260040160405180910390fd5b61026c6102448280610b13565b600081811061025557610255610b5d565b90506020028101906102679190610b73565b610327565b6102768280610b13565b600181811061028757610287610b5d565b90506020028101906102999190610b73565b6102a7906040810190610b93565b6102b091610bea565b146102ce57604051636589f0e160e11b815260040160405180910390fd5b6102ec6102db8280610b13565b600181811061025557610255610b5d565b861461030b576040516392cb8fbb60e01b815260040160405180910390fd5b505050505050565b610320858585858561054b565b5050505050565b60008060026103396040850185610b93565b604051610347929190610bda565b602060405180830381855afa158015610364573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103879190610c08565b905060026103986060850185610b93565b6103af6103a86020880188610b93565b9050610659565b6103bc6020880188610b93565b6103c66020610659565b876040516020016103dd9796959493929190610c5c565b60408051601f19818403018152908290526103f791610ca0565b602060405180830381855afa158015610414573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104379190610c08565b915060005b6104468480610b13565b905081101561054457600261045b8580610b13565b8381811061046b5761046b610b5d565b905060200281019061047d9190610cb3565b6104879080610b93565b856104928880610b13565b868181106104a2576104a2610b5d565b90506020028101906104b49190610cb3565b6104c2906020810190610b93565b6040516020016104d6959493929190610cc9565b60408051601f19818403018152908290526104f091610ca0565b602060405180830381855afa15801561050d573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105309190610c08565b92508061053c81610cf1565b91505061043c565b5050919050565b604080516020808201889052818301879052606080830187905283518084039091018152608083018452805190820120600060a08401527f000000000000000000000000000000000000000000000000000000000000000060c084015260e080840191909152835180840390910181526101008301808552815191830191909120601f860183900490920283016101209081019094528481526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169361063293879187918291018382808284376000920191909152506106c892505050565b6001600160a01b031614610320576040516339e27c8560e21b815260040160405180910390fd5b6060805b6080831061069b578083607f1660801760f81b604051602001610681929190610d18565b60408051601f198184030190525260079290921c9161065d565b808360f81b6040516020016106b1929190610d18565b604051602081830303815290604052915050919050565b60008060006106d785856106ee565b915091506106e481610733565b5090505b92915050565b60008082516041036107245760208301516040840151606085015160001a61071887828585610885565b9450945050505061072c565b506000905060025b9250929050565b600081600481111561074757610747610d3d565b0361074f5750565b600181600481111561076357610763610d3d565b036107b55760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b60028160048111156107c9576107c9610d3d565b036108165760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016107ac565b600381600481111561082a5761082a610d3d565b036108825760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016107ac565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156108bc5750600090506003610940565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015610910573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661093957600060019250925050610940565b9150600090505b94509492505050565b60008083601f84011261095b57600080fd5b50813567ffffffffffffffff81111561097357600080fd5b60208301915083602082850101111561072c57600080fd5b60006040828403121561099d57600080fd5b50919050565b600080600080606085870312156109b957600080fd5b84359350602085013567ffffffffffffffff808211156109d857600080fd5b6109e488838901610949565b909550935060408701359150808211156109fd57600080fd5b50610a0a8782880161098b565b91505092959194509250565b60008060008060008060808789031215610a2f57600080fd5b86359550602087013567ffffffffffffffff80821115610a4e57600080fd5b610a5a8a838b01610949565b90975095506040890135915080821115610a7357600080fd5b610a7f8a838b01610949565b90955093506060890135915080821115610a9857600080fd5b50610aa589828a0161098b565b9150509295509295509295565b600080600080600060808688031215610aca57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115610af657600080fd5b610b0288828901610949565b969995985093965092949392505050565b6000808335601e19843603018112610b2a57600080fd5b83018035915067ffffffffffffffff821115610b4557600080fd5b6020019150600581901b360382131561072c57600080fd5b634e487b7160e01b600052603260045260246000fd5b60008235607e19833603018112610b8957600080fd5b9190910192915050565b6000808335601e19843603018112610baa57600080fd5b83018035915067ffffffffffffffff821115610bc557600080fd5b60200191503681900382131561072c57600080fd5b8183823760009101908152919050565b803560208310156106e857600019602084900360031b1b1692915050565b600060208284031215610c1a57600080fd5b5051919050565b6000815160005b81811015610c425760208185018101518683015201610c28565b81811115610c51576000828601525b509290920192915050565b86888237600087820160008152610c738189610c21565b9050858782376000908601908152610c8b8186610c21565b93845250506020909101979650505050505050565b6000610cac8284610c21565b9392505050565b60008235603e19833603018112610b8957600080fd5b8486823760008582018581528385602083013760009301602001928352509095945050505050565b600060018201610d1157634e487b7160e01b600052601160045260246000fd5b5060010190565b6000610d248285610c21565b6001600160f81b03199390931683525050600101919050565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220fa89b329a79580f1febe5413c0bb8912ab9cb891a3e8ca344fb2e44cad4b41b464736f6c634300080f0033"; type SequencerSignatureVerifierConstructorParams = | [signer?: Signer] diff --git a/src/evm/contracts/factories/SequencerSoloClient__factory.ts b/src/evm/contracts/factories/SequencerSoloClient__factory.ts index 7f394b37..7451976c 100644 --- a/src/evm/contracts/factories/SequencerSoloClient__factory.ts +++ b/src/evm/contracts/factories/SequencerSoloClient__factory.ts @@ -28,6 +28,11 @@ const _abi = [ type: "address", internalType: "contract ISignatureVerifier", }, + { + name: "_l1BlockProvider", + type: "address", + internalType: "contract L1Block", + }, ], stateMutability: "nonpayable", }, @@ -82,6 +87,19 @@ const _abi = [ ], stateMutability: "view", }, + { + type: "function", + name: "l1BlockProvider", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract L1Block", + }, + ], + stateMutability: "view", + }, { type: "function", name: "updateClient", @@ -258,7 +276,12 @@ const _abi = [ }, { type: "error", - name: "CannotUpdatePendingOptimisticConsensusState", + name: "CannotUpdateClientWithDifferentAppHash", + inputs: [], + }, + { + type: "error", + name: "InvalidL1Origin", inputs: [], }, { @@ -280,7 +303,7 @@ const _abi = [ ] as const; const _bytecode = - "0x60a06040526000805460ff1916600217905534801561001d57600080fd5b5060405161090d38038061090d83398101604081905261003c9161004d565b6001600160a01b031660805261007d565b60006020828403121561005f57600080fd5b81516001600160a01b038116811461007657600080fd5b9392505050565b6080516108686100a56000396000818160ba0152818161018c015261024b01526108686000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806349ff245e1161005b57806349ff245e1461010757806357c1c5f41461011c578063cb535ab514610131578063fdaab4e51461014457600080fd5b80631b738a22146100825780632b7ac3f3146100b557806344c9af28146100f4575b600080fd5b6100a261009036600461030f565b60016020526000908152604090205481565b6040519081526020015b60405180910390f35b6100dc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100ac565b6100a261010236600461030f565b610157565b61011a610115366004610371565b61016d565b005b610124600281565b6040516100ac91906103c2565b61011a61013f366004610402565b610241565b61011a610152366004610497565b6102f6565b6000818152600160205260408120545b92915050565b600082815260016020526040812054900361023b576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e8d9003983836101c160206000898b610500565b6101ca9161052a565b6101d7886020818c610500565b6040518663ffffffff1660e01b81526004016101f7959493929190610571565b600060405180830381600087803b15801561021157600080fd5b505af1158015610225573d6000803e3d6000fd5b5050506000838152600160205260409020829055505b50505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663c2f0329f610294610282600160208a01356105a2565b60009081526001602052604090205490565b6040516001600160e01b031960e084901b1681526102bf919088908890889088908d90600401610656565b60006040518083038186803b1580156102d757600080fd5b505afa1580156102eb573d6000803e3d6000fd5b505050505050505050565b604051634dfb272b60e11b815260040160405180910390fd5b60006020828403121561032157600080fd5b5035919050565b60008083601f84011261033a57600080fd5b50813567ffffffffffffffff81111561035257600080fd5b60208301915083602082850101111561036a57600080fd5b9250929050565b6000806000806060858703121561038757600080fd5b843567ffffffffffffffff81111561039e57600080fd5b6103aa87828801610328565b90989097506020870135966040013595509350505050565b60208101600383106103e457634e487b7160e01b600052602160045260246000fd5b91905290565b6000604082840312156103fc57600080fd5b50919050565b60008060008060006060868803121561041a57600080fd5b853567ffffffffffffffff8082111561043257600080fd5b61043e89838a016103ea565b9650602088013591508082111561045457600080fd5b61046089838a01610328565b9096509450604088013591508082111561047957600080fd5b5061048688828901610328565b969995985093965092949392505050565b6000806000604084860312156104ac57600080fd5b833567ffffffffffffffff808211156104c457600080fd5b6104d0878388016103ea565b945060208601359150808211156104e657600080fd5b506104f386828701610328565b9497909650939450505050565b6000808585111561051057600080fd5b8386111561051d57600080fd5b5050820193919092039150565b8035602083101561016757600019602084900360031b1b1692915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b858152846020820152836040820152608060608201526000610597608083018486610548565b979650505050505050565b6000828210156105c257634e487b7160e01b600052601160045260246000fd5b500390565b6000808335601e198436030181126105de57600080fd5b830160208101925035905067ffffffffffffffff8111156105fe57600080fd5b8060051b360382131561036a57600080fd5b6000808335601e1984360301811261062757600080fd5b830160208101925035905067ffffffffffffffff81111561064757600080fd5b80360382131561036a57600080fd5b868152608060208201526000610670608083018789610548565b8281036040840152610683818688610548565b9050828103606084015261069784856105c7565b604083526040830181815260608401905060608260051b8501018360005b8481101561081357868303605f1901845236869003607e19018235126106da57600080fd5b858235016106e881826105c7565b608086526080860181815260a08701905060a08260051b8801018360005b8481101561078957898303609f1901845236869003603e190182351261072b57600080fd5b858235016107398182610610565b6040865261074b604087018284610548565b91505061075b6020830183610610565b92508582036020870152610770828483610548565b6020978801979096509490940193505050600101610706565b50506107986020860186610610565b9450925087810360208901526107af818585610548565b93505050506107c16040830183610610565b86830360408801526107d4838284610548565b925050506107e56060830183610610565b925085820360608701526107fa828483610548565b60209788019790965094909401935050506001016106b5565b505060208801356020860152809550505050505097965050505050505056fea2646970667358221220ba6ee2547b1e41dd85ba6cf68288a386d9b7c1eb518439f687e0b086fe8a6c7464736f6c634300080f0033"; + "0x60c06040526000805460ff1916600217905534801561001d57600080fd5b50604051610a88380380610a8883398101604081905261003c9161006b565b6001600160a01b039182166080521660a0526100a5565b6001600160a01b038116811461006857600080fd5b50565b6000806040838503121561007e57600080fd5b825161008981610053565b602084015190925061009a81610053565b809150509250929050565b60805160a0516109aa6100de6000396000818161015401526101b801526000818160c501528181610272015261038701526109aa6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806357c1c5f41161005b57806357c1c5f414610127578063cb535ab51461013c578063eb7720581461014f578063fdaab4e51461017657600080fd5b80631b738a221461008d5780632b7ac3f3146100c057806344c9af28146100ff57806349ff245e14610112575b600080fd5b6100ad61009b366004610438565b60016020526000908152604090205481565b6040519081526020015b60405180910390f35b6100e77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100b7565b6100ad61010d366004610438565b610189565b61012561012036600461049a565b61019f565b005b61012f600281565b6040516100b791906104eb565b61012561014a36600461052b565b610268565b6100e77f000000000000000000000000000000000000000000000000000000000000000081565b6101256101843660046105c0565b61031d565b6000818152600160205260408120545b92915050565b6101ad602060008587610629565b6101b691610653565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166309bd5a606040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610671565b1461025657604051632b56254960e01b815260040160405180910390fd5b61026284848484610336565b50505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663c2f0329f6102bb6102a9600160208a013561068a565b60009081526001602052604090205490565b6040516001600160e01b031960e084901b1681526102e6919088908890889088908d90600401610767565b60006040518083038186803b1580156102fe57600080fd5b505afa158015610312573d6000803e3d6000fd5b505050505050505050565b604051634dfb272b60e11b815260040160405180910390fd5b6000828152600160205260409020541561037d57600082815260016020526040902054811461037857604051631549535560e01b815260040160405180910390fd5b610262565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e8d9003983836103bc60206000898b610629565b6103c591610653565b6103d2886020818c610629565b6040518663ffffffff1660e01b81526004016103f2959493929190610943565b600060405180830381600087803b15801561040c57600080fd5b505af1158015610420573d6000803e3d6000fd5b50505060009283525060016020526040909120555050565b60006020828403121561044a57600080fd5b5035919050565b60008083601f84011261046357600080fd5b50813567ffffffffffffffff81111561047b57600080fd5b60208301915083602082850101111561049357600080fd5b9250929050565b600080600080606085870312156104b057600080fd5b843567ffffffffffffffff8111156104c757600080fd5b6104d387828801610451565b90989097506020870135966040013595509350505050565b602081016003831061050d57634e487b7160e01b600052602160045260246000fd5b91905290565b60006040828403121561052557600080fd5b50919050565b60008060008060006060868803121561054357600080fd5b853567ffffffffffffffff8082111561055b57600080fd5b61056789838a01610513565b9650602088013591508082111561057d57600080fd5b61058989838a01610451565b909650945060408801359150808211156105a257600080fd5b506105af88828901610451565b969995985093965092949392505050565b6000806000604084860312156105d557600080fd5b833567ffffffffffffffff808211156105ed57600080fd5b6105f987838801610513565b9450602086013591508082111561060f57600080fd5b5061061c86828701610451565b9497909650939450505050565b6000808585111561063957600080fd5b8386111561064657600080fd5b5050820193919092039150565b8035602083101561019957600019602084900360031b1b1692915050565b60006020828403121561068357600080fd5b5051919050565b6000828210156106aa57634e487b7160e01b600052601160045260246000fd5b500390565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000808335601e198436030181126106ef57600080fd5b830160208101925035905067ffffffffffffffff81111561070f57600080fd5b8060051b360382131561049357600080fd5b6000808335601e1984360301811261073857600080fd5b830160208101925035905067ffffffffffffffff81111561075857600080fd5b80360382131561049357600080fd5b8681526080602082015260006107816080830187896106af565b82810360408401526107948186886106af565b905082810360608401526107a884856106d8565b604083526040830181815260608401905060608260051b8501018360005b8481101561092457868303605f1901845236869003607e19018235126107eb57600080fd5b858235016107f981826106d8565b608086526080860181815260a08701905060a08260051b8801018360005b8481101561089a57898303609f1901845236869003603e190182351261083c57600080fd5b8582350161084a8182610721565b6040865261085c6040870182846106af565b91505061086c6020830183610721565b925085820360208701526108818284836106af565b6020978801979096509490940193505050600101610817565b50506108a96020860186610721565b9450925087810360208901526108c08185856106af565b93505050506108d26040830183610721565b86830360408801526108e58382846106af565b925050506108f66060830183610721565b9250858203606087015261090b8284836106af565b60209788019790965094909401935050506001016107c6565b5050602088013560208601528095505050505050979650505050505050565b8581528460208201528360408201526080606082015260006109696080830184866106af565b97965050505050505056fea2646970667358221220b47ba4090acd6cbc3c0fdd2515a036c0fb41d8fb506c1f7dcd2d63664ac2065f64736f6c634300080f0033"; type SequencerSoloClientConstructorParams = | [signer?: Signer] @@ -301,15 +324,25 @@ export class SequencerSoloClient__factory extends ContractFactory { override getDeployTransaction( verifier_: AddressLike, + _l1BlockProvider: AddressLike, overrides?: NonPayableOverrides & { from?: string } ): Promise { - return super.getDeployTransaction(verifier_, overrides || {}); + return super.getDeployTransaction( + verifier_, + _l1BlockProvider, + overrides || {} + ); } override deploy( verifier_: AddressLike, + _l1BlockProvider: AddressLike, overrides?: NonPayableOverrides & { from?: string } ) { - return super.deploy(verifier_, overrides || {}) as Promise< + return super.deploy( + verifier_, + _l1BlockProvider, + overrides || {} + ) as Promise< SequencerSoloClient & { deploymentTransaction(): ContractTransactionResponse; } diff --git a/test/SequencerSoloClient.t.sol b/test/SequencerSoloClient.t.sol new file mode 100644 index 00000000..056ec52c --- /dev/null +++ b/test/SequencerSoloClient.t.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import "forge-std/Test.sol"; +import {SequencerSoloClient} from "../contracts/core/SequencerSoloClient.sol"; +import {SequencerSignatureVerifier, ISignatureVerifier} from "../contracts/core/SequencerSignatureVerifier.sol"; +import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import {SigningBase} from "./utils/SigningClient.base.t.sol"; + +contract OptimisticLightClientWithRealVerifierTest is SigningBase { + SequencerSoloClient sequencerClient; + bytes32 ancestorBlockPayloadHash; + bytes validChildSignature; + bytes validAncestorSignature; + bytes invalidSignature; + + function setUp() public { + sequencerClient = new SequencerSoloClient(sigVerifier, l1BlockProvider); + + // Used for l1 origin check tests, represents the child block. + bytes32 ancestorPayloadHash = + keccak256(bytes.concat(bytes32(peptideBlockNumber), peptideAppHash, l1AncestorBlockHash)); + bytes32 ancestorHashToSign = keccak256(bytes.concat(domain, PEPTIDE_CHAIN_ID, ancestorPayloadHash)); + (uint8 v0, bytes32 r0, bytes32 s0) = vm.sign(sequencerPkey, ancestorHashToSign); + validAncestorSignature = abi.encodePacked(r0, s0, v0); // Annoingly, v, r, s are in a different order than those + + (uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(notSequencerPkey, ancestorHashToSign); + invalidSignature = abi.encodePacked(r1, s1, v1); // Annoingly, v, r, s are in a different order than those + } + + function test_UpdateValidSequencerClientState() public { + // In this case, peptide l1 origin is ahead of dest chain's l1 origin. Relayer queries the + // signed block from sequencer and waits for dest chain to come to same l1 origin. + // We don't need a checkpointing solution in this case, so we call the update method directly. + + setBlockAttributesFromJson("/test/payload/l1_block_ancestor.json"); + sequencerClient.updateClient( + abi.encodePacked(l1AncestorBlockHash, validAncestorSignature), peptideBlockNumber, uint256(peptideAppHash) + ); + assertEq(sequencerClient.getState(peptideBlockNumber), uint256(peptideAppHash)); + + // A subsequent client update should be a noop and wouldn't revert even with an invalid sig + sequencerClient.updateClient( + abi.encodePacked(l1AncestorBlockHash, invalidSignature), peptideBlockNumber, uint256(peptideAppHash) + ); + assertEq(sequencerClient.getState(peptideBlockNumber), uint256(peptideAppHash)); + } + + // 1.) test that hte block update without the l1b lock header is invalid, or perhaps signatuer is invalid as well + function test_revert_invalidSequencerClientState() public { + // This mocks the dest chain moving ahead of the signed l1 origin, or a re-org occuring which means that the + // blockhash returned by l1 block info isn't equal to that of the signed blockhash. i.e. We'd expect this update + // client tx to revert. + setBlockAttributesFromJson("/test/payload/l1_block_child.json"); + console.logBytes32(l1BlockProvider.hash()); + vm.expectRevert(SequencerSoloClient.InvalidL1Origin.selector); + sequencerClient.updateClient( + abi.encodePacked(l1AncestorBlockHash, validAncestorSignature), peptideBlockNumber, uint256(peptideAppHash) + ); + assertEq(sequencerClient.getState(peptideBlockNumber), 0); + + setBlockAttributesFromJson("/test/payload/l1_block_ancestor.json"); + // Peptide l1 origin being the same as dest chain l1 origin is necessary but not sufficient. We also need to + // check that the signature is valid as well, and it will revert if it isn't valid. + vm.expectRevert(ISignatureVerifier.InvalidSequencerSignature.selector); + sequencerClient.updateClient( + abi.encodePacked(l1AncestorBlockHash, invalidSignature), peptideBlockNumber, uint256(peptideAppHash) + ); + assertEq(sequencerClient.getState(peptideBlockNumber), 0); + } +} diff --git a/test/payload/l1_block_ancestor.json b/test/payload/l1_block_ancestor.json new file mode 100644 index 00000000..902fe8f7 --- /dev/null +++ b/test/payload/l1_block_ancestor.json @@ -0,0 +1,29 @@ +{ + "jsonrpc": "2.0", + "id": "1", + "result":{ + "hash": "0x911faba7371dde57a5650b304ef8fd70f0059f5e23cc8ca305a54ae101329c5e", + "parentHash": "0xfd0cf75c3395e8e31a8a66484d1fdc337ae06548e0389576ce1342c24cfc4c0c", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97", + "stateRoot": "0x5b5aa7b9d9b48ecc9e1a5acd52c99a4b7368392bc88719e8adcd002666b4ff00", + "transactionsRoot": "0x1ca62b0feca24a6363ed60d8a22ce5dff0360345f784193eadaa71b0bbad02ba", + "receiptsRoot": "0x5dc05f27d790f10ed41b577adf202bb8784a0cef4bc25d2a510d766f6cbeef55", + "logsBloom": "0x392f5158c9016dcd1d268bd496a8a81c0b294a01fc014002269940b626722d800012159ac608800ac08a7316023c8114df2da7459ed32f3b1984286aa9aab90b09321ea8750b19980c6ee3a89186cee4980112b102c24c956011767090660224042531a50ef205ab6a5e43a3e3a54ee1f47b18af8e1a266ec2032b91300a22428b62875852a1a6f820cb2965a3728c65ae01287b8b30d4ad5c3200f00733d94b2bcc35400a83f2024e8e11e608a79e6e24008da9160172a214e904f258f80d75a856845fe10a8f1347428673438e8bdbabd4059274a02a90c48745f2652baa4a2c79e2c010820f8089049da704e559862a1d1bc163802cd86009b31242019e0b", + "difficulty": "0x0", + "number": "0x1403e78", + "gasLimit": "0x1c9c380", + "gasUsed": "0x119c8ab", + "timestamp": "0x67116bcf", + "totalDifficulty": "0xc70d815d562d3cfa955", + "extraData": "0x546974616e2028746974616e6275696c6465722e78797a29", + "mixHash": "0x99de1f7d00918a47a9909bd6bb8ea30c47f0c823e6ed014b70049576a0df6de7", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x47fe26383", + "withdrawalsRoot": "0x52b2e029af917cce9f73904f2046b8e9e33749bcdc23885d89daaf33af9f7fe0", + "blobGasUsed": "0x0", + "excessBlobGas": "0xa0000", + "parentBeaconBlockRoot": "0x61c7198bbdc252979973e408dedbcddc7aacdf78459d69a3e95aa35e3249ed50", + "uncles": [] + } +} diff --git a/test/payload/l1_block_child.json b/test/payload/l1_block_child.json new file mode 100644 index 00000000..4d9c626e --- /dev/null +++ b/test/payload/l1_block_child.json @@ -0,0 +1,29 @@ +{ + "jsonrpc": "2.0", + "id": "1", + "result":{ + "hash": "0xb4ebc467e644b0d3b855a71305bdeb1fef88e761976f2a6ea2f75b4c82b0acd5", + "parentHash": "0xabbe2e82802e00a1caa3996470825a4ce61d7137d359cb5e8f36261b8f2fdd38", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5", + "stateRoot": "0x4e96a5c64d8866f8dab8ec7acca71ca9594336670573d1de1cd7a9c419272f15", + "transactionsRoot": "0x53cbb89954c8ee1623d139c5848cfab350ca5c5687497f7d3b9e813634bc20fb", + "receiptsRoot": "0xa072f434d74313444e47d269c1530cdda9694178cc4281d9e683efd7d9b730d4", + "logsBloom": "0x3dabf73f7f454f7655aeec519bbf9a83fdeb1b70d67b76c2726b414d77a6288ff3f37f2fbf71a597ff1d7fd9feb7df91d73fcb6dfff37db557ed7fdef4bf4bf3bcf69cafd10caa7beaf77fbef96eebefdd1646f9bff54f9df7bf0debf2f5bef74eaef7f7aa7afae784dfd7f77949ff672f6d6b5b1f7ff67b90cef0b6591f9df3aef7fb587b33f6699a4d256aefee9ee7e653ff77fdb1d87dcc3c2d57ef785dfcebb7f772ed9bfadf1f0671d6c987bfcafdf756d9dffdf6ef4d6fcbf3ecbfe9f5cd977a7ab55ffffb7dcb8935c6eaff454fdff77245ff2df744dbf5efe94af49729fbbd51f99c347757fdf78eb2f917479f7fd94d6d3ab6fb3d0ca1787ff8fccf", + "difficulty": "0x0", + "number": "0x1403e80", + "gasLimit": "0x1c9c380", + "gasUsed": "0x1842e76", + "timestamp": "0x67116c2f", + "totalDifficulty": "0xc70d815d562d3cfa955", + "extraData": "0x6265617665726275696c642e6f7267", + "mixHash": "0x1dd88cf475dd30d18ca90277a91458626d76f2debcb280e6fd13eaf923d12437", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x3a5b90cbb", + "withdrawalsRoot": "0xf2fa7fc5d5c8045c5174e53c774e0a4e5b78019670d069f715b75caada2e7a34", + "blobGasUsed": "0x80000", + "excessBlobGas": "0x40000", + "parentBeaconBlockRoot": "0x0a1ccf62294537ea20b53fe2a3df1b5a11fc29d8105d42b9517d0857cdafbc58", + "uncles": [] + } +} diff --git a/test/utils/Dispatcher.base.t.sol b/test/utils/Dispatcher.base.t.sol index 9d020c48..52ab3ea9 100644 --- a/test/utils/Dispatcher.base.t.sol +++ b/test/utils/Dispatcher.base.t.sol @@ -64,7 +64,7 @@ contract Base is IbcEventsEmitter, ProofBase, TestUtilsTest { ILightClient opLightClient = new OptimisticLightClient(1800, opProofVerifier, l1BlockProvider); ISignatureVerifier sequencerSignatureVerifier = new SequencerSignatureVerifier(sequencer, PEPTIDE_CHAIN_ID); - ILightClient sequencerLightClient = new SequencerSoloClient(sequencerSignatureVerifier); + ILightClient sequencerLightClient = new SequencerSoloClient(sequencerSignatureVerifier, l1BlockProvider); ILightClient dummyLightClient = new DummyLightClient(); IFeeVault feeVault = new FeeVault(); diff --git a/test/utils/SigningClient.base.t.sol b/test/utils/SigningClient.base.t.sol index 33920eb7..1000c1e9 100644 --- a/test/utils/SigningClient.base.t.sol +++ b/test/utils/SigningClient.base.t.sol @@ -6,6 +6,7 @@ import "../../contracts/libs/Ibc.sol"; import "../../contracts/interfaces/IProofVerifier.sol"; import "../../contracts/core/SequencerSignatureVerifier.sol"; import {RLPWriter} from "optimism/libraries/rlp/RLPWriter.sol"; +import {L1Block} from "optimism/L2/L1Block.sol"; contract SigningBase is Test { using stdJson for string; @@ -13,9 +14,11 @@ contract SigningBase is Test { string rootDir = vm.projectRoot(); bytes32 l1BlockHash; + bytes32 l1AncestorBlockHash; bytes32 peptideAppHash; uint256 public peptideBlockNumber; uint256 public sequencerPkey; + uint256 public notSequencerPkey; address public sequencer; bytes32 hashToSign; bytes32 domain; // Domain will be empty so we can leave it as initialized to default 0x 32 bytes @@ -23,8 +26,16 @@ contract SigningBase is Test { SequencerSignatureVerifier public sigVerifier; bytes32 PEPTIDE_CHAIN_ID = bytes32(uint256(444)); + L1Header childl1Block; // Child block, represents the l1 origin of dest chain when peptide catches up to ancestor L1 + // block + L1Header ancestorL1Block; // Ancestor block, represents the l1 origin of dest chain when peptide wants to submit a + + // client update but is behind, so we need to checkpoint this block + L1Block l1BlockProvider = new L1Block(); + constructor() { (sequencer, sequencerPkey) = makeAddrAndKey("alice"); + (, notSequencerPkey) = makeAddrAndKey(unicode"bob😈"); sigVerifier = new SequencerSignatureVerifier(sequencer, PEPTIDE_CHAIN_ID); // generate the channel_proof.hex file with the following command: @@ -36,6 +47,10 @@ contract SigningBase is Test { ); l1BlockHash = keccak256(RLPWriter.writeList(l1header.header)); // Blockhash that will be signed by sequencer + + // Set l1 child block hash which is used to verify signature against + l1AncestorBlockHash = readBytes32FromJson("/test/payload/l1_block_ancestor.json", ".result.hash"); + peptideBlockNumber = 101; // this happens to be the polymer height when the L2OO was updated with the output proposal @@ -46,4 +61,37 @@ contract SigningBase is Test { bytes32 payloadHash = keccak256(abi.encodePacked(peptideBlockNumber, peptideAppHash, l1BlockHash)); hashToSign = keccak256(bytes.concat(domain, PEPTIDE_CHAIN_ID, payloadHash)); } + + // Read a specific bytes32 json property from a json file + function readBytes32FromJson(string memory fileName, string memory property) public view returns (bytes32) { + string memory blockJson = vm.readFile(string.concat(rootDir, fileName)); + return abi.decode(blockJson.parseRaw(property), (bytes32)); + } + + // Read a specific uint64 json property from a json file + function readUint64FromJson(string memory fileName, string memory property) public view returns (uint64) { + string memory blockJson = vm.readFile(string.concat(rootDir, fileName)); + return abi.decode(blockJson.parseRaw(property), (uint64)); + } + + // Set the block attributes on the l1 block info to that from a json file + function setBlockAttributesFromJson(string memory fileName) public { + bytes32 hash = readBytes32FromJson(fileName, ".result.hash"); + uint64 number = readUint64FromJson(fileName, ".result.number"); + setL1BlockAttributes(hash, number); + } + + function setL1BlockAttributes(bytes32 hash, uint64 number) public { + vm.prank(l1BlockProvider.DEPOSITOR_ACCOUNT()); + l1BlockProvider.setL1BlockValues( + number, + 0, // timestamp + 0, // basefee + hash, + 0, // sequenceNumber + bytes32(0), // batcherHash + 0, // l1FeeOverhead + 0 // l1FeeScalar + ); + } }