Address Contract Partially Verified
Address
0xaD900dB30Bcdf84c38Df0067eA327bbEccCF071A
Balance
0 ETH
Nonce
1
Code Size
18880 bytes
Creator
0x2818a3aF...68ca at tx 0x27c9fc29...36a1e3
Indexed Transactions
0 (1 on-chain, 1.4% indexed)
Contract Bytecode
18880 bytes
0x608060405260043610610306575f3560e01c806388b1ea0911610191578063b3e0a509116100dc578063ddd8a3dc11610087578063e3fff1dd11610062578063e3fff1dd146109b1578063f2fde38b146109d0578063fb1e8b04146109ef575f80fd5b8063ddd8a3dc1461095e578063de8b30351461097d578063dff7827e1461099c575f80fd5b8063ce5db8d6116100b7578063ce5db8d614610917578063d279c1911461092c578063d63b35491461094b575f80fd5b8063b3e0a509146108c6578063bedb86fb146108e5578063cd4edc6914610904575f80fd5b8063a479265d1161013c578063b31a77d311610117578063b31a77d314610873578063b348442514610888578063b35dac4e146108a7575f80fd5b8063a479265d14610814578063a4f209b014610829578063abc8d68d14610848575f80fd5b8063910129d41161016c578063910129d41461079657806397fc007c146107c7578063a415d8dc146107e6575f80fd5b806388b1ea09146106b05780638da5cb5b146106c95780638f1d3776146106e6575f80fd5b80632b7ac3f3116102515780635f77cf1d116101fc5780636c578c1d116101d75780636c578c1d1461065e578063715018a61461067d578063728cdbca14610691575f80fd5b80635f77cf1d146105c8578063612672901461061457806368589dfa14610633575f80fd5b806357e0af6c1161022c57806357e0af6c146105325780635c975abb146105515780635ef7a94a14610568575f80fd5b80632b7ac3f3146104c75780633b70c18a146104fe5780633e001b661461051d575f80fd5b806313361101116102b157806321e2f9e01161028c57806321e2f9e0146104525780632362f03e146104715780632571098d1461049c575f80fd5b806313361101146103ee57806318463fb01461040d57806318af3b2b14610422575f80fd5b806310d44583116102e157806310d4458314610398578063116a1f42146103b7578063121dcd50146103d9575f80fd5b806304d7721514610311578063059def61146103545780630ceb678014610377575f80fd5b3661030d57005b5f80fd5b34801561031c575f80fd5b5061033f61032b3660046142d3565b60a36020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b34801561035f575f80fd5b50610369609d5481565b60405190815260200161034b565b348015610382575f80fd5b50610396610391366004614305565b610a04565b005b3480156103a3575f80fd5b506103966103b2366004614363565b610ad6565b3480156103c2575f80fd5b5061033f6103d13660046142d3565b609d54101590565b3480156103e4575f80fd5b50610369609e5481565b3480156103f9575f80fd5b506103966104083660046143ab565b610e2f565b348015610418575f80fd5b5061036960a75481565b34801561042d575f80fd5b5061033f61043c3660046142d3565b5f90815260a26020526040902060010154421090565b34801561045d575f80fd5b5061033f61046c3660046142d3565b611324565b34801561047c575f80fd5b5061036961048b3660046142d3565b60a16020525f908152604090205481565b3480156104a7575f80fd5b506103696104b63660046142d3565b60a06020525f908152604090205481565b3480156104d2575f80fd5b50609c546104e6906001600160a01b031681565b6040516001600160a01b03909116815260200161034b565b348015610509575f80fd5b50609b546104e6906001600160a01b031681565b348015610528575f80fd5b5061036960aa5481565b34801561053d575f80fd5b5061039661054c3660046142d3565b611352565b34801561055c575f80fd5b5060655460ff1661033f565b348015610573575f80fd5b506105a86105823660046142d3565b60a26020525f908152604090208054600182015460028301546003909301549192909184565b60408051948552602085019390935291830152606082015260800161034b565b3480156105d3575f80fd5b506105fb7f0000000000000000000000000000000000000000000000000000000000000b0281565b60405167ffffffffffffffff909116815260200161034b565b34801561061f575f80fd5b5061039661062e3660046142d3565b6113fd565b34801561063e575f80fd5b5061036961064d3660046142d3565b60ab6020525f908152604090205481565b348015610669575f80fd5b50610396610678366004614305565b611612565b348015610688575f80fd5b506103966116cf565b34801561069c575f80fd5b506103966106ab3660046143ea565b6116e2565b3480156106bb575f80fd5b5060a65461033f9060ff1681565b3480156106d4575f80fd5b506033546001600160a01b03166104e6565b3480156106f1575f80fd5b506107526107003660046142d3565b60a46020525f9081526040902080546001820154600283015460039093015467ffffffffffffffff831693680100000000000000009093046001600160a01b0316929060ff8082169161010090041686565b6040805167ffffffffffffffff90971687526001600160a01b03909516602087015293850192909252606084015215156080830152151560a082015260c00161034b565b3480156107a1575f80fd5b5061033f6107b03660046142d3565b5f90815260a4602052604090206003015460ff1690565b3480156107d2575f80fd5b506103966107e1366004614305565b611a25565b3480156107f1575f80fd5b5061033f610800366004614305565b609f6020525f908152604090205460ff1681565b34801561081f575f80fd5b5061036960995481565b348015610834575f80fd5b506103966108433660046142d3565b611b08565b348015610853575f80fd5b50610369610862366004614305565b60a56020525f908152604090205481565b34801561087e575f80fd5b5061036960a85481565b348015610893575f80fd5b506103966108a2366004614445565b611bb8565b3480156108b2575f80fd5b506103966108c1366004614305565b611dfd565b3480156108d1575f80fd5b506103966108e03660046143ab565b611e56565b3480156108f0575f80fd5b506103966108ff3660046144b9565b6121a6565b6103966109123660046144d4565b612301565b348015610922575f80fd5b5061036960985481565b348015610937575f80fd5b50610396610946366004614305565b6128cd565b61039661095936600461450a565b61298c565b348015610969575f80fd5b506097546104e6906001600160a01b031681565b348015610988575f80fd5b5061033f6109973660046142d3565b6132b6565b3480156109a7575f80fd5b50610369609a5481565b3480156109bc575f80fd5b506103966109cb3660046142d3565b613300565b3480156109db575f80fd5b506103966109ea366004614305565b6133a3565b3480156109fa575f80fd5b5061036960a95481565b610a0c613430565b6001600160a01b0381165f908152609f602052604090205460ff1615610a795760405162461bcd60e51b815260206004820152601f60248201527f6163636f756e7420697320616c72656164792061206368616c6c656e6765720060448201526064015b60405180910390fd5b6001600160a01b0381165f818152609f6020908152604091829020805460ff1916600190811790915591519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc00991015b60405180910390a250565b610ade613430565b5f8111610b2d5760405162461bcd60e51b815260206004820152601560248201527f636f756e74206d757374206265206e6f6e7a65726f00000000000000000000006044820152606401610a70565b5f80610b39858561348a565b915091505f610b4c836001015160c01c90565b5f81815260a160205260409020549091508214610bab5760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610a70565b5f60a181610bb987856145a4565b81526020019081526020015f205414610c395760405162461bcd60e51b8152602060048201526024808201527f726576657274696e67206d7573742073746172742066726f6d2074686520656e60448201527f64696e67000000000000000000000000000000000000000000000000000000006064820152608401610a70565b609d548111610cb05760405162461bcd60e51b815260206004820152602160248201527f63616e206f6e6c792072657665727420756e46696e616c697a6564206261746360448201527f68000000000000000000000000000000000000000000000000000000000000006064820152608401610a70565b610cbb6001826145b7565b609e555b8315610e2757604051829082907ecae2739091badfd91c373f0a16cede691e0cd25bb80cff77dd5caeb4710146905f90a35f81815260a16020526040812055610d07816132b6565b15610d62575f81815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a59092528220805491929091610d529084906145a4565b909155505060a6805460ff191690555b5f81815260a46020526040812080547fffffffff0000000000000000000000000000000000000000000000000000000016815560018101829055600281019190915560030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560a85415801590610ddf575060a85481145b15610de9575f60a8555b6001015f81815260a160205260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193915081610cbf575b505050505050565b60a85415610e7f5760405162461bcd60e51b815260206004820152600b60248201527f6e656564207265766572740000000000000000000000000000000000000000006044820152606401610a70565b610e876134a5565b5f80610e93848461348a565b915091505f610ea6836001015160c01c90565b5f81815260a160205260409020549091508214610f055760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610a70565b610f0e81611324565b610f5a5760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610a70565b610f63816132b6565b15610fb05760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610a70565b5f81815260a4602052604090206003015460ff16156110115760405162461bcd60e51b815260206004820152601660248201527f62617463682073686f756c6420626520726576657274000000000000000000006044820152606401610a70565b5f81815260a260205260409020600101544210156110715760405162461bcd60e51b815260206004820152601960248201527f626174636820696e206368616c6c656e67652077696e646f77000000000000006044820152606401610a70565b605983015160a05f6110846001856145b7565b81526020019081526020015f2054146110df5760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610a70565b5f81815260a060205260409020541561113a5760405162461bcd60e51b815260206004820152601660248201527f626174636820616c7265616479207665726966696564000000000000000000006044820152606401610a70565b80609d546001011461118e5760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610a70565b609d819055600160a35f6111a3866099015190565b815260208101919091526040015f20805460ff191691151591909117905560798301515f82815260a060205260409020556111f060f98401601185015160c01c600986015160c01c6134f8565b60a25f6111fe6001846145b7565b815260208101919091526040015f908120818155600180820183905560028201839055600390910182905560ab919061123790846145b7565b81526020019081526020015f205f905560a45f60018361125791906145b7565b815260208082019290925260409081015f90812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810182905560030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905583815260a1909252902054817f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d611300866079015190565b60998701516040805192835260208301919091520160405180910390a35050505050565b5f81815260a260205260408120541580159061134c57505f82815260a1602052604090205415155b92915050565b61135a613430565b5f8111801561136b57506099548114155b6113b75760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964206e65772070726f6f662077696e646f7700000000000000006044820152606401610a70565b609980549082905560408051828152602081018490527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a6191015b60405180910390a15050565b5f54600290610100900460ff1615801561141d57505f5460ff8083169116105b61148f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a70565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790556114ca5f5460ff1690565b60ff1660021461151c5760405162461bcd60e51b815260206004820152601660248201527f6d757374206861766520696e697469616c697a656421000000000000000000006044820152606401610a70565b8161158f5760405162461bcd60e51b815260206004820152602760248201527f63616e206e6f742073657420737461746520726f6f742077697468206279746560448201527f73333228302921000000000000000000000000000000000000000000000000006064820152608401610a70565b609e545f90815260ab60205260409020546115b857609e545f90815260ab602052604090208290555b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020016113f1565b61161a613430565b6001600160a01b0381165f908152609f602052604090205460ff166116815760405162461bcd60e51b815260206004820152601b60248201527f6163636f756e74206973206e6f742061206368616c6c656e67657200000000006044820152606401610a70565b6001600160a01b0381165f818152609f60209081526040808320805460ff19169055519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc0099101610acb565b6116d7613430565b6116e05f6135c1565b565b5f54610100900460ff161580801561170057505f54600160ff909116105b806117195750303b15801561171957505f5460ff166001145b61178b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610a70565b5f805460ff1916600117905580156117c9575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6001600160a01b03861615806117e657506001600160a01b038516155b1561181d576040517fecc6fdf000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0387166118735760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206c31207374616b696e6720636f6e747261637400000000006044820152606401610a70565b61187b61362a565b6118836136ae565b609780546001600160a01b03808a167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255609b8054898416908316179055609c805492881692909116821790556098859055609984905560a98390556040515f907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96908290a3604080515f8152602081018690527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a437910160405180910390a1604080515f8152602081018590527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a61910160405180910390a1604080515f8152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b0223910160405180910390a18015611a1c575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b611a2d613430565b6001600160a01b03811615801590611a535750609c546001600160a01b03828116911614155b611a9f5760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206e65772076657269666965720000000000000000000000006044820152606401610a70565b609c80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96905f90a35050565b611b10613430565b5f81118015611b20575060648111155b8015611b2e575060a9548114155b611b7a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c69642070726f6f66207265776172642070657263656e74616765006044820152606401610a70565b60a980549082905560408051828152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b022391016113f1565b60a85415611c085760405162461bcd60e51b815260206004820152600b60248201527f6e656564207265766572740000000000000000000000000000000000000000006044820152606401610a70565b611c106134a5565b5f80611c1c868661348a565b915091505f611c2f836001015160c01c90565b5f81815260a160205260409020549091508214611c8e5760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610a70565b611c97816132b6565b611ce35760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610a70565b5f81815260a4602052604090206003810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010017905560a6805460ff191690556099546002909101544291611d3c916145a4565b11611db2575f81815260a4602090815260408083206003908101805460ff1916600117905560a2835292819020909201548251808401909352600783527f54696d656f75740000000000000000000000000000000000000000000000000091830191909152611dad91839190613732565b611a1c565b611dbd83868661388e565b611a1c81336040518060400160405280600d81526020017f50726f6f66207375636365737300000000000000000000000000000000000000815250613a41565b611e05613430565b60aa80545f909155611e178282613b0d565b604080516001600160a01b0384168152602081018390527fb1b2058a6969e2d25e47bcaebe8ae21c29a23b2752429315b75e2f4f285f3d8791016113f1565b611e5e613430565b5f805260a06020527fb84a74ec6ef4d0e83b6006dfaa014ab4026f9f3b97d186e604d29998a4e808ea5415611ed55760405162461bcd60e51b815260206004820152601660248201527f67656e6573697320626174636820696d706f72746564000000000000000000006044820152606401610a70565b5f80611ee1848461348a565b915091505f611ef4836001015160c01c90565b90508015611f445760405162461bcd60e51b815260206004820152601360248201527f696e76616c696420626174636820696e646578000000000000000000000000006044820152606401610a70565b5f611f50846079015190565b905080611f9f5760405162461bcd60e51b815260206004820152600f60248201527f7a65726f20737461746520726f6f7400000000000000000000000000000000006044820152606401610a70565b600984015160c01c15611ff45760405162461bcd60e51b815260206004820152601d60248201527f6c31206d65737361676520706f707065642073686f756c6420626520300000006044820152606401610a70565b5f612000856019015190565b0361204d5760405162461bcd60e51b815260206004820152600e60248201527f7a65726f206461746120686173680000000000000000000000000000000000006044820152606401610a70565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014612079856039015190565b146120c65760405162461bcd60e51b815260206004820152601660248201527f696e76616c69642076657273696f6e65642068617368000000000000000000006044820152606401610a70565b5f82815260a1602090815260408083208690558051608081018252428082528184019081528183018581526060830186815288875260a2865284872093518455915160018401555160028301555160039091015560ab825280832084905560a0909152808220839055609e849055609d84905551849184917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3604080518281525f6020820152849184917f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d910160405180910390a3505050505050565b6121ae613430565b80156122cf576121bc613bb8565b60a65460ff161561228e5760a7545f90815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a590925282208054919290916122109084906145a4565b909155505060a7545f90815260a46020526040812080547fffffffff0000000000000000000000000000000000000000000000000000000016815560018101829055600281019190915560030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560a6805460ff191690555b7f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a150565b6122d7613c12565b7f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336122b1565b50565b335f908152609f602052604090205460ff1661235f5760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206368616c6c656e67657220616c6c6f776564000000000000006044820152606401610a70565b60a854156123af5760405162461bcd60e51b815260206004820152600b60248201527f6e656564207265766572740000000000000000000000000000000000000000006044820152606401610a70565b6123b76134a5565b60a65460ff161561240a5760405162461bcd60e51b815260206004820152601460248201527f616c726561647920696e206368616c6c656e67650000000000000000000000006044820152606401610a70565b8167ffffffffffffffff16609d54106124655760405162461bcd60e51b815260206004820152601760248201527f626174636820616c72656164792066696e616c697a65640000000000000000006044820152606401610a70565b67ffffffffffffffff82165f90815260a1602052604090205481146124cc5760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610a70565b6124df8267ffffffffffffffff16611324565b61252b5760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610a70565b67ffffffffffffffff82165f90815260a460205260409020546801000000000000000090046001600160a01b0316156125a65760405162461bcd60e51b815260206004820152601860248201527f626174636820616c7265616479206368616c6c656e67656400000000000000006044820152606401610a70565b67ffffffffffffffff82165f90815260a2602052604090206001015442106126365760405162461bcd60e51b815260206004820152603360248201527f63616e6e6f74206368616c6c656e6765206261746368206f757473696465207460448201527f6865206368616c6c656e67652077696e646f77000000000000000000000000006064820152608401610a70565b60975f9054906101000a90046001600160a01b03166001600160a01b0316630d13fd7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612686573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126aa91906145ca565b3410156126f95760405162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742076616c756500000000000000000000000000006044820152606401610a70565b67ffffffffffffffff82811660a78190556040805160c0810182528281523360208083018281523484860190815242606086019081525f6080870181815260a0880182815299825260a4909552969096209451855492516001600160a01b031668010000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909316981697909717178355945160018301559151600282015592516003909301805492511515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff941515949094167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092179290921790556001600160a01b03168267ffffffffffffffff167f3a6ea19df25b49e7624e313ce7c1ab23984238e93727260db56a81735b1b99763460405161284b91815260200190565b60405180910390a35f609d54600161286391906145a4565b90505b609e5481116128bb578267ffffffffffffffff1681146128a9576099545f82815260a26020526040812060010180549091906128a39084906145a4565b90915550505b806128b3816145e1565b915050612866565b505060a6805460ff1916600117905550565b335f90815260a560205260408120549081900361292c5760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642062617463684368616c6c656e6765526577617264000000006044820152606401610a70565b335f90815260a560205260408120556129458282613b0d565b816001600160a01b03167f9c25fa83f414ed363c8d39c98fb3e17567b3431cede71eb062c49d2a63ce247a8260405161298091815260200190565b60405180910390a25050565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156129f8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a1c9190614618565b612a685760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610a70565b60a85415612ab85760405162461bcd60e51b815260206004820152600b60248201527f6e656564207265766572740000000000000000000000000000000000000000006044820152606401610a70565b612ac06134a5565b612acd6020830183614633565b60ff1615612b1d5760405162461bcd60e51b815260206004820152600f60248201527f696e76616c69642076657273696f6e00000000000000000000000000000000006044820152606401610a70565b5f612b2b6040840184614653565b91505080612b7b5760405162461bcd60e51b815260206004820152600e60248201527f626174636820697320656d7074790000000000000000000000000000000000006044820152606401610a70565b6080830135612bcc5760405162461bcd60e51b815260206004820152601b60248201527f70726576696f757320737461746520726f6f74206973207a65726f00000000006044820152606401610a70565b60a0830135612c1d5760405162461bcd60e51b815260206004820152601660248201527f6e657720737461746520726f6f74206973207a65726f000000000000000000006044820152606401610a70565b5f80612c34612c2f6020870187614653565b61348a565b915091505f612c47836001015160c01c90565b90505f60a181612c588460016145a4565b81526020019081526020015f205414612cb35760405162461bcd60e51b815260206004820152601760248201527f626174636820616c726561647920636f6d6d69747465640000000000000000006044820152606401610a70565b609e548114612d045760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610a70565b5f81815260a160205260409020548214612d605760405162461bcd60e51b815260206004820152601b60248201527f696e636f727265637420706172656e74206261746368206861736800000000006044820152606401610a70565b5f81815260ab6020526040902054608087013514612dc05760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610a70565b5f612dcf846011015160c01c90565b90505f8080612e2e612de460408c018c614653565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250879250889150612e29905060608f018f614653565b613c4b565b948501949384019392509050612e4760608b018b614653565b905061010060ff85010460200214612ea15760405162461bcd60e51b815260206004820152601360248201527f77726f6e67206269746d6170206c656e677468000000000000000000000000006044820152606401610a70565b600194909401935f804915612eb7575f49612ed9565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b90505f612ee960608d018d614653565b612ef5915060f96145a4565b90506040519850602081028901604052612f23898d5f016020810190612f1b9190614633565b60ff16613dcc565b60c087811b60018b015285811b60098b015286811b60118b015260198a0184905260808d013560598b015260a08d013560798b01528c013560998a0152612f9089612f7160208e018e614653565b604051612f7f9291906146b4565b604051809103902060b99190910152565b60d98901889052612fad89612fa860608f018f614653565b613dd3565b603989018290528089205f88815260a1602090815260408083209390935560ab905290812060a08e0135905560a65460ff16156130135760a7545f90815260a460205260409020600201546099544291613006916145a4565b61301091906145b7565b90505b6040518060800160405280428152602001826098544261303391906145a4565b61303d91906145a4565b815260200161308e8f80604001906130559190614653565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250613ddf92505050565b81526097546020909101906001600160a01b031663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613102573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061312691906145ca565b90525f89815260a2602090815260409182902083518155838201516001820155918301516002830155606090920151600390910155609e8990556097546001600160a01b031692506374fe27b791508c359061318e90613188908f018f614653565b5f613e36565b5f8e806040019061319f9190614653565b6040518663ffffffff1660e01b81526004016131bf95949392919061470a565b602060405180830381865afa1580156131da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131fe9190614618565b6132705760405162461bcd60e51b815260206004820152602160248201527f746865207369676e617475726520766572696669636174696f6e206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610a70565b5f86815260a16020526040808220549051909188917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a35050505050505050505050565b5f81815260a460205260408120546801000000000000000090046001600160a01b03161580159061134c5750505f90815260a46020526040902060030154610100900460ff161590565b613308613430565b5f8111801561331957506098548114155b6133655760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206e65772066696e616c697a6520706572696f6400000000006044820152606401610a70565b609880549082905560408051828152602081018490527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a43791016113f1565b6133ab613430565b6001600160a01b0381166134275760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a70565b6122fe816135c1565b6033546001600160a01b031633146116e05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a70565b5f805f6134978585613e8a565b812090969095509350505050565b60655460ff16156116e05760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610a70565b805f0361350457505050565b8082035f805b83811015610e275761010081850381111561352457508084035b8651609b546040517f55f613ce0000000000000000000000000000000000000000000000000000000081526004810187905260248101849052604481018390526020909901989194506001600160a01b0316906355f613ce906064015f604051808303815f87803b158015613597575f80fd5b505af11580156135a9573d5f803e3d5ffd5b5050505061010084019350506101008101905061350a565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff166136a65760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a70565b6116e0613f61565b5f54610100900460ff1661372a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a70565b6116e0613fe9565b60a88390555f83815260a460205260408082205460975491517f45bc4d1000000000000000000000000000000000000000000000000000000000815260048101869052680100000000000000009091046001600160a01b03908116939216906345bc4d10906024016020604051808303815f875af11580156137b6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906137da91906145ca565b5f86815260a460205260409020600101549091506137f99082906145a4565b5f86815260a460209081526040808320546801000000000000000090046001600160a01b0316835260a5909152812080549091906138389084906145a4565b909155505060405161384b90849061477d565b604051908190038120906001600160a01b0384169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b806138db5760405162461bcd60e51b815260206004820152601360248201527f496e76616c69642062617463682070726f6f66000000000000000000000000006044820152606401610a70565b5f6138ea846001015160c01c90565b90505f6138f8856039015190565b90505f7f0000000000000000000000000000000000000000000000000000000000000b02613927876059015190565b6079880151609989015160b98a015160198b015160405160c09690961b7fffffffffffffffff000000000000000000000000000000000000000000000000166020870152602886019490945260488501929092526068840152608883015260a882015260c8810183905260e801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609c549091506001600160a01b0316632c09a8486139e9885160f81c90565b858888866040518663ffffffff1660e01b8152600401613a0d9594939291906147a9565b5f6040518083038186803b158015613a23575f80fd5b505afa158015613a35573d5f803e3d5ffd5b50505050505050505050565b5f83815260a4602052604081206001015460a954909190606490613a6590846147da565b613a6f91906147f1565b9050613a7b81836145b7565b60aa5f828254613a8b91906145a4565b90915550506001600160a01b0384165f90815260a5602052604081208054839290613ab79084906145a4565b9091555050604051613aca90849061477d565b604051908190038120906001600160a01b0386169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b8015613bb4575f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114613b5c576040519150601f19603f3d011682016040523d82523d5f602084013e613b61565b606091505b5050905080613bb25760405162461bcd60e51b815260206004820152601b60248201527f526f6c6c75703a20455448207472616e73666572206661696c656400000000006044820152606401610a70565b505b5050565b613bc06134a5565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613bf53390565b6040516001600160a01b03909116815260200160405180910390a1565b613c1a61406e565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33613bf5565b60405185515f91829160208901919081908490613c699085906140c0565b90506002840193505f5b81811015613ced57603c81028501805184526020908101517fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000001690840152603a830192505f613cc3603c836147da565b613ccd90876145a4565b90505f613cde82603a015160f01c90565b97909701965050600101613c73565b506020850282016040525b8015613db8575f613d0d85603a015160f01c90565b9050613d1d83828d8d8d8d614155565b92505f613d2e866038015160f01c90565b905081811015613d805760405162461bcd60e51b815260206004820152601d60248201527f6e756d20747873206c657373207468616e206e756d204c31206d7367730000006044820152606401610a70565b50998a01999890980197603c93909301927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613cf8565b508190039020989197509095505050505050565b8082535050565b808260f9850137505050565b5f805f6020840190506002810191505f613dfa8286516140c0565b90505f5b613e096001836145b7565b811015613e1f57603c9390930192600101613dfe565b505f613e2c845160c01c90565b9695505050505050565b60605f80808080613e49888a018a614916565b9550955095509550955050818710613e67579450613e839350505050565b838710613e7b578295505050505050613e83565b509293505050505b9392505050565b5f8160f9811015613edd5760405162461bcd60e51b815260206004820152601d60248201527f626174636820686561646572206c656e67746820746f6f20736d616c6c0000006044820152606401610a70565b6040519150808483378082016040525f613efb836009015160c01c90565b905061010060ff82010460200260f9018214613f595760405162461bcd60e51b815260206004820152601360248201527f77726f6e67206269746d6170206c656e677468000000000000000000000000006044820152606401610a70565b509250929050565b5f54610100900460ff16613fdd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a70565b6065805460ff19169055565b5f54610100900460ff166140655760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a70565b6116e0336135c1565b60655460ff166116e05760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610a70565b5f6140cc835160f01c90565b9050805f03614107576040517f5168407700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614112603c826147da565b61411d9060026145a4565b821461134c576040517f4a969e2d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f855f03614164575085613e2c565b609b546001600160a01b03165f80805b8981101561424a5760ff89169150600889901c811580614192575082155b156141a1578060200288013593505b600184841c165f03614239576040517fae453cd5000000000000000000000000000000000000000000000000000000008152600481018a90525f906001600160a01b0387169063ae453cd590602401602060405180830381865afa15801561420b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061422f91906145ca565b8d52506020909b019a5b506001988901989788019701614174565b505060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff88011681811c600116156142c55760405162461bcd60e51b815260206004820152601b60248201527f63616e6e6f7420736b6970206c617374204c31206d65737361676500000000006044820152606401610a70565b509798975050505050505050565b5f602082840312156142e3575f80fd5b5035919050565b80356001600160a01b0381168114614300575f80fd5b919050565b5f60208284031215614315575f80fd5b613e83826142ea565b5f8083601f84011261432e575f80fd5b50813567ffffffffffffffff811115614345575f80fd5b60208301915083602082850101111561435c575f80fd5b9250929050565b5f805f60408486031215614375575f80fd5b833567ffffffffffffffff81111561438b575f80fd5b6143978682870161431e565b909790965060209590950135949350505050565b5f80602083850312156143bc575f80fd5b823567ffffffffffffffff8111156143d2575f80fd5b6143de8582860161431e565b90969095509350505050565b5f805f805f8060c087890312156143ff575f80fd5b614408876142ea565b9550614416602088016142ea565b9450614424604088016142ea565b9350606087013592506080870135915060a087013590509295509295509295565b5f805f8060408587031215614458575f80fd5b843567ffffffffffffffff8082111561446f575f80fd5b61447b8883890161431e565b90965094506020870135915080821115614493575f80fd5b506144a08782880161431e565b95989497509550505050565b80151581146122fe575f80fd5b5f602082840312156144c9575f80fd5b8135613e83816144ac565b5f80604083850312156144e5575f80fd5b823567ffffffffffffffff811681146144fc575f80fd5b946020939093013593505050565b5f806040838503121561451b575f80fd5b823567ffffffffffffffff80821115614532575f80fd5b9084019060e08287031215614545575f80fd5b9092506020840135908082111561455a575f80fd5b5083016060818603121561456c575f80fd5b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561134c5761134c614577565b8181038181111561134c5761134c614577565b5f602082840312156145da575f80fd5b5051919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361461157614611614577565b5060010190565b5f60208284031215614628575f80fd5b8151613e83816144ac565b5f60208284031215614643575f80fd5b813560ff81168114613e83575f80fd5b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614686575f80fd5b83018035915067ffffffffffffffff8211156146a0575f80fd5b60200191503681900382131561435c575f80fd5b818382375f9101908152919050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f6080820187835260206080602085015281885180845260a08601915060208a0193505f5b818110156147545784516001600160a01b03168352938301939183019160010161472f565b5050876040860152848103606086015261476f8187896146c3565b9a9950505050505050505050565b5f82515f5b8181101561479c5760208186018101518583015201614782565b505f920191825250919050565b858152846020820152608060408201525f6147c86080830185876146c3565b90508260608301529695505050505050565b808202811582820484141761134c5761134c614577565b5f82614824577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112614865575f80fd5b8135602067ffffffffffffffff8083111561488257614882614829565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811084821117156148c5576148c5614829565b60405293845260208187018101949081019250878511156148e4575f80fd5b6020870191505b8482101561490b576148fc826142ea565b835291830191908301906148eb565b979650505050505050565b5f805f805f8060c0878903121561492b575f80fd5b86359550602087013567ffffffffffffffff80821115614949575f80fd5b6149558a838b01614856565b9650604089013595506060890135915080821115614971575f80fd5b61497d8a838b01614856565b94506080890135935060a0890135915080821115614999575f80fd5b506149a689828a01614856565b915050929550929550929556fea164736f6c6343000818000a
Verified Source Code Partial Match
Compiler: v0.8.24+commit.e11b9ed9
EVM: cancun
Optimization: Yes (10000 runs)
IL1MessageQueue.sol 144 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
interface IL1MessageQueue {
/**********
* Errors *
**********/
/// @dev Thrown when the given address is `address(0)`.
error ErrZeroAddress();
/**********
* Events *
**********/
/// @notice Emitted when a new L1 => L2 transaction is appended to the queue.
/// @param sender The address of account who initiates the transaction.
/// @param target The address of account who will receive the transaction.
/// @param value The value passed with the transaction.
/// @param queueIndex The index of this transaction in the queue.
/// @param gasLimit Gas limit required to complete the message relay on L2.
/// @param data The calldata of the transaction.
event QueueTransaction(
address indexed sender,
address indexed target,
uint256 value,
uint64 queueIndex,
uint256 gasLimit,
bytes data
);
/// @notice Emitted when some L1 => L2 transactions are included in L1.
/// @param startIndex The start index of messages popped.
/// @param count The number of messages popped.
/// @param skippedBitmap A bitmap indicates whether a message is skipped.
event DequeueTransaction(uint256 startIndex, uint256 count, uint256 skippedBitmap);
/// @notice Emitted when a message is dropped from L1.
/// @param index The index of message dropped.
event DropTransaction(uint256 index);
/// @notice Emitted when owner updates gas oracle contract.
/// @param _oldGasOracle The address of old gas oracle contract.
/// @param _newGasOracle The address of new gas oracle contract.
event UpdateGasOracle(address indexed _oldGasOracle, address indexed _newGasOracle);
/// @notice Emitted when owner updates EnforcedTxGateway contract.
/// @param _oldGateway The address of old EnforcedTxGateway contract.
/// @param _newGateway The address of new EnforcedTxGateway contract.
event UpdateEnforcedTxGateway(address indexed _oldGateway, address indexed _newGateway);
/// @notice Emitted when owner updates max gas limit.
/// @param _oldMaxGasLimit The old max gas limit.
/// @param _newMaxGasLimit The new max gas limit.
event UpdateMaxGasLimit(uint256 _oldMaxGasLimit, uint256 _newMaxGasLimit);
/*************************
* Public View Functions *
*************************/
/// @notice The start index of all pending inclusion messages.
function pendingQueueIndex() external view returns (uint256);
/// @notice Return the index of next appended message.
/// @dev Also the total number of appended messages.
function nextCrossDomainMessageIndex() external view returns (uint256);
/// @notice Return the message of in `queueIndex`.
/// @param queueIndex The index to query.
function getCrossDomainMessage(uint256 queueIndex) external view returns (bytes32);
/// @notice Return the amount of ETH should pay for cross domain message.
/// @param sender The address of the message sender.
/// @param gasLimit Gas limit required to complete the message relay on L2.
/// @dev Estimates the fee for a cross-domain message.
function estimateCrossDomainMessageFee(address sender, uint256 gasLimit) external view returns (uint256);
/// @notice Return the amount of intrinsic gas fee should pay for cross domain message.
/// @param _calldata The calldata of L1-initiated transaction.
function calculateIntrinsicGasFee(bytes memory _calldata) external view returns (uint256);
/// @notice Return the hash of a L1 message.
/// @param sender The address of sender.
/// @param queueIndex The queue index of this message.
/// @param value The amount of Ether transfer to target.
/// @param target The address of target.
/// @param gasLimit The gas limit provided.
/// @param data The calldata passed to target address.
function computeTransactionHash(
address sender,
uint256 queueIndex,
uint256 value,
address target,
uint256 gasLimit,
bytes calldata data
) external view returns (bytes32);
/// @notice Return whether the message is skipped.
/// @param queueIndex The queue index of the message to check.
function isMessageSkipped(uint256 queueIndex) external view returns (bool);
/// @notice Return whether the message is dropped.
/// @param queueIndex The queue index of the message to check.
function isMessageDropped(uint256 queueIndex) external view returns (bool);
/*****************************
* Public Mutating Functions *
*****************************/
/// @notice Append a L1 to L2 message into this contract.
/// @param target The address of target contract to call in L2.
/// @param gasLimit The maximum gas should be used for relay this message in L2.
/// @param data The calldata passed to target contract.
function appendCrossDomainMessage(address target, uint256 gasLimit, bytes calldata data) external;
/// @notice Append an enforced transaction to this contract.
/// @dev The address of sender should be an EOA.
/// @param sender The address of sender who will initiate this transaction in L2.
/// @param target The address of target contract to call in L2.
/// @param value The value passed
/// @param gasLimit The maximum gas should be used for this transaction in L2.
/// @param data The calldata passed to target contract.
function appendEnforcedTransaction(
address sender,
address target,
uint256 value,
uint256 gasLimit,
bytes calldata data
) external;
/// @notice Pop finalized messages from queue.
///
/// @dev We can pop at most 256 messages each time. And if the message is not skipped,
/// the corresponding entry will be cleared.
///
/// @param startIndex The start index to pop.
/// @param count The number of messages to pop.
/// @param skippedBitmap A bitmap indicates whether a message is skipped.
function popCrossDomainMessage(uint256 startIndex, uint256 count, uint256 skippedBitmap) external;
/// @notice Drop a skipped message from the queue.
function dropCrossDomainMessage(uint256 index) external;
}
IRollup.sol 194 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
interface IRollup {
/***********
* Structs *
***********/
/// @param version The version of current batch.
/// @param parentBatchHeader The header of parent batch, see the comments of `BatchHeaderV0Codec`.
/// @param blockContexts The block contexts of current batch.
/// @param skippedL1MessageBitmap The bitmap indicates whether each L1 message is skipped or not.
/// @param prevStateRoot The state root of parent batch.
/// @param postStateRoot The state root of current batch.
/// @param withdrawalRoot The withdraw trie root of current batch.
struct BatchDataInput {
uint8 version;
bytes parentBatchHeader;
bytes blockContexts;
bytes skippedL1MessageBitmap;
bytes32 prevStateRoot;
bytes32 postStateRoot;
bytes32 withdrawalRoot;
}
/// @param signedSequencers The bitmap of signed sequencers
/// @param sequencerSets The latest 3 sequencer sets
/// @param signature The BLS signature
struct BatchSignatureInput {
uint256 signedSequencersBitmap;
bytes sequencerSets;
bytes signature;
}
/// @param originTimestamp
/// @param finalizeTimestamp
/// @param blockNumber
struct BatchData {
uint256 originTimestamp;
uint256 finalizeTimestamp;
uint256 blockNumber;
uint256 signedSequencersBitmap;
}
/// @dev Structure to store information about a batch challenge.
/// @param batchIndex The index of the challenged batch.
/// @param challenger The address of the challenger.
/// @param challengeDeposit The amount of deposit put up by the challenger.
/// @param startTime The timestamp when the challenge started.
/// @param challengeSuccess Flag indicating whether the challenge was successful.
/// @param finished Flag indicating whether the challenge has been resolved.
struct BatchChallenge {
uint64 batchIndex;
address challenger;
uint256 challengeDeposit;
uint256 startTime;
bool challengeSuccess;
bool finished;
}
/// @param receiver
/// @param amount
struct BatchChallengeReward {
address receiver;
uint256 amount;
}
/***********
* Errors *
***********/
/// @notice error zero address
error ErrZeroAddress();
/**********
* Events *
**********/
/// @notice Emitted when a new batch is committed.
/// @param batchIndex The index of the batch.
/// @param batchHash The hash of the batch.
event CommitBatch(uint256 indexed batchIndex, bytes32 indexed batchHash);
/// @notice revert a pending batch.
/// @param batchIndex The index of the batch.
/// @param batchHash The hash of the batch
event RevertBatch(uint256 indexed batchIndex, bytes32 indexed batchHash);
/// @notice Emitted when a batch is finalized.
/// @param batchIndex The index of the batch.
/// @param batchHash The hash of the batch
/// @param stateRoot The state root on layer 2 after this batch.
/// @param withdrawRoot The merkle root on layer2 after this batch.
event FinalizeBatch(uint256 indexed batchIndex, bytes32 indexed batchHash, bytes32 stateRoot, bytes32 withdrawRoot);
/// @notice Emitted when owner updates the proofWindow parameter.
/// @param oldWindow The old proofWindow.
/// @param newWindow The new proofWindow.
event UpdateProofWindow(uint256 oldWindow, uint256 newWindow);
/// @notice Emitted when owner updates the finalizationPeriodSeconds parameter.
/// @param oldPeriod The old finalizationPeriodSeconds.
/// @param newPeriod The new finalizationPeriodSeconds.
event UpdateFinalizationPeriodSeconds(uint256 oldPeriod, uint256 newPeriod);
/// @notice Emitted when owner updates the status of challenger.
/// @param account The address of account updated.
/// @param status The status of the account updated.
event UpdateChallenger(address indexed account, bool status);
/// @notice Emitted when the address of rollup verifier is updated.
/// @param oldVerifier The address of old rollup verifier.
/// @param newVerifier The address of new rollup verifier.
event UpdateVerifier(address indexed oldVerifier, address indexed newVerifier);
/// @notice Emitted when the proof reward percent is updated.
/// @param oldPercent The old proofRewardPercent.
/// @param newPercent The new proofRewardPercent.
event UpdateProofRewardPercent(uint256 oldPercent, uint256 newPercent);
/// @notice Emit when prove remaining claimed.
/// @param receiver receiver address.
/// @param amount claimed amount.
event ProveRemainingClaimed(address receiver, uint256 amount);
/// @notice Emitted when the state of Challenge is updated.
/// @param batchIndex The index of the batch.
/// @param challenger The address of challenger.
/// @param challengeDeposit The deposit of challenger.
event ChallengeState(uint64 indexed batchIndex, address indexed challenger, uint256 challengeDeposit);
/// @notice Emitted when the result of Challenge is updated.
/// @param batchIndex The index of the batch.
/// @param winner The address of winner.
/// @param res The result of challenge.
event ChallengeRes(uint256 indexed batchIndex, address indexed winner, string indexed res);
/// @notice Emitted when the challenger claim the challenge reward.
/// @param receiver receiver address
/// @param amount claimed amount
event ChallengeRewardClaim(address indexed receiver, uint256 amount);
/*************************
* Public View Functions *
*************************/
/// @notice The latest finalized batch index.
function lastFinalizedBatchIndex() external view returns (uint256);
/// @notice The latest finalized batch index.
function lastCommittedBatchIndex() external view returns (uint256);
/// @notice Return the batch hash of a committed batch.
/// @param batchIndex The index of the batch.
function committedBatches(uint256 batchIndex) external view returns (bytes32);
/// @notice Return the state root of a committed batch.
/// @param batchIndex The index of the batch.
function finalizedStateRoots(uint256 batchIndex) external view returns (bytes32);
/// @notice Return the the committed batch of withdrawalRoot.
/// @param withdrawalRoot The withdrawal root.
function withdrawalRoots(bytes32 withdrawalRoot) external view returns (bool);
/// @notice Return whether the batch is finalized by batch index.
/// @param batchIndex The index of the batch.
function isBatchFinalized(uint256 batchIndex) external view returns (bool);
/// @notice Return the rollup config of finalizationPeriodSeconds.
function finalizationPeriodSeconds() external view returns (uint256);
/*****************************
* Public Mutating Functions *
*****************************/
/// @notice Commit a batch of transactions on layer 1.
///
/// @param batchDataInput The BatchDataInput struct
/// @param batchSignatureInput The BatchSignatureInput struct
function commitBatch(
BatchDataInput calldata batchDataInput,
BatchSignatureInput calldata batchSignatureInput
) external payable;
/// @notice Revert a pending batch.
/// @dev one can only revert unfinalized batches.
/// @param batchHeader The header of current batch, see the encoding in comments of `commitBatch`.
/// @param count The number of subsequent batches to revert, including current batch.
function revertBatch(bytes calldata batchHeader, uint256 count) external;
/// @notice Claim challenge reward
/// @param receiver The receiver address
function claimReward(address receiver) external;
}
Rollup.sol 877 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
import {OwnableUpgradeable} from "node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {PausableUpgradeable} from "node_modules/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {BatchHeaderCodecV0} from "../../libraries/codec/BatchHeaderCodecV0.sol";
import {BatchCodecV0} from "../../libraries/codec/BatchCodecV0.sol";
import {IRollupVerifier} from "../../libraries/verifier/IRollupVerifier.sol";
import {IL1MessageQueue} from "./IL1MessageQueue.sol";
import {IRollup} from "./IRollup.sol";
import {IL1Staking} from "../staking/IL1Staking.sol";
// solhint-disable no-inline-assembly
// solhint-disable reason-string
/// @title Rollup
/// @notice This contract maintains data for the Morph rollup.
contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable {
/*************
* Constants *
*************/
/// @notice The zero versioned hash.
bytes32 internal constant ZERO_VERSIONED_HASH = 0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014;
/// @notice The BLS MODULUS. Deprecated.
uint256 internal constant __BLS_MODULUS =
52435875175126190479447740508185965837690552500527637822603658699938581184513;
/// @dev Address of the point evaluation precompile used for EIP-4844 blob verification.
address internal constant POINT_EVALUATION_PRECOMPILE_ADDR = address(0x0A);
/// @notice The chain id of the corresponding layer 2 chain.
uint64 public immutable LAYER_2_CHAIN_ID;
/*************
* Variables *
*************/
/// @notice L1 staking contract
address public l1StakingContract;
/// @notice Batch challenge time.
uint256 public finalizationPeriodSeconds;
/// @notice The time when zkProof was generated and executed.
uint256 public proofWindow;
/// @notice The maximum number of transactions allowed in each chunk. Deprecated.
uint256 public __maxNumTxInChunk;
/// @notice The address of L1MessageQueue.
address public messageQueue;
/// @notice The address of RollupVerifier.
address public verifier;
/// @inheritdoc IRollup
uint256 public override lastFinalizedBatchIndex;
/// @inheritdoc IRollup
uint256 public override lastCommittedBatchIndex;
/// @notice Whether an account is a challenger.
mapping(address challengerAddress => bool isChallenger) public isChallenger;
/// @inheritdoc IRollup
mapping(uint256 batchIndex => bytes32 stateRoot) public override finalizedStateRoots;
/// @notice Store committed batch hash.
mapping(uint256 batchIndex => bytes32 batchHash) public override committedBatches;
/// @notice Store committed batch base.
mapping(uint256 batchIndex => BatchData) public batchDataStore;
/// @notice Store the withdrawalRoot.
mapping(bytes32 withdrawalRoot => bool exist) public withdrawalRoots;
/// @notice Store Challenge Information.
mapping(uint256 batchIndex => BatchChallenge) public challenges;
/// @notice Store Challenge reward information.
mapping(address owner => uint256 amount) public batchChallengeReward;
/// @notice Whether in challenge
bool public inChallenge;
/// @notice The batch being challenged
uint256 public batchChallenged;
/// @notice The index of the revert request.
uint256 public revertReqIndex;
/// @notice percentage awarded to prover
uint256 public proofRewardPercent;
/// @notice prove remaining
uint256 public proveRemaining;
/// @notice committedStateRoots
mapping(uint256 batchIndex => bytes32 stateRoot) public committedStateRoots;
/**********************
* Function Modifiers *
**********************/
/// @notice Only active staker allowed.
modifier onlyActiveStaker() {
require(IL1Staking(l1StakingContract).isActiveStaker(_msgSender()), "only active staker allowed");
_;
}
/// @notice Only challenger allowed.
modifier onlyChallenger() {
require(isChallenger[_msgSender()], "caller challenger allowed");
_;
}
/// @notice Modifier to ensure that there is no pending revert request.
modifier nonReqRevert() {
require(revertReqIndex == 0, "need revert");
_;
}
/***************
* Constructor *
***************/
/// @notice constructor
/// @param _chainID The chain ID
constructor(uint64 _chainID) {
LAYER_2_CHAIN_ID = _chainID;
_disableInitializers();
}
/// @notice Allow the contract to receive ETH.
receive() external payable {}
/***************
* Initializer *
***************/
/// @notice initializer
/// @param _l1StakingContract l1 staking contract
/// @param _messageQueue message queue
/// @param _verifier verifier
/// @param _finalizationPeriodSeconds finalization period seconds
/// @param _proofWindow proof window
function initialize(
address _l1StakingContract,
address _messageQueue,
address _verifier,
uint256 _finalizationPeriodSeconds,
uint256 _proofWindow,
uint256 _proofRewardPercent
) public initializer {
if (_messageQueue == address(0) || _verifier == address(0)) {
revert ErrZeroAddress();
}
require(_l1StakingContract != address(0), "invalid l1 staking contract");
__Pausable_init();
__Ownable_init();
l1StakingContract = _l1StakingContract;
messageQueue = _messageQueue;
verifier = _verifier;
finalizationPeriodSeconds = _finalizationPeriodSeconds;
proofWindow = _proofWindow;
proofRewardPercent = _proofRewardPercent;
emit UpdateVerifier(address(0), _verifier);
emit UpdateFinalizationPeriodSeconds(0, _finalizationPeriodSeconds);
emit UpdateProofWindow(0, _proofWindow);
emit UpdateProofRewardPercent(0, _proofRewardPercent);
}
function initialize2(bytes32 _prevStateRoot) external reinitializer(2) {
require(_getInitializedVersion() == 2, "must have initialized!");
require(_prevStateRoot != bytes32(0), "can not set state root with bytes32(0)!");
if (committedStateRoots[lastCommittedBatchIndex] == bytes32(0)) {
committedStateRoots[lastCommittedBatchIndex] = _prevStateRoot;
}
}
/************************
* Restricted Functions *
************************/
/// @notice Import layer 2 genesis block
function importGenesisBatch(bytes calldata _batchHeader) external onlyOwner {
// check whether the genesis batch is imported
require(finalizedStateRoots[0] == bytes32(0), "genesis batch imported");
(uint256 memPtr, bytes32 _batchHash) = _loadBatchHeader(_batchHeader);
uint256 _batchIndex = BatchHeaderCodecV0.getBatchIndex(memPtr);
// check batch index is 0
require(_batchIndex == 0, "invalid batch index");
bytes32 _postStateRoot = BatchHeaderCodecV0.getPostStateHash(memPtr);
require(_postStateRoot != bytes32(0), "zero state root");
// check all fields except `dataHash` and `lastBlockHash` are zero
require(BatchHeaderCodecV0.getL1MessagePopped(memPtr) == 0, "l1 message popped should be 0");
require(BatchHeaderCodecV0.getDataHash(memPtr) != bytes32(0), "zero data hash");
require(BatchHeaderCodecV0.getBlobVersionedHash(memPtr) == ZERO_VERSIONED_HASH, "invalid versioned hash");
committedBatches[_batchIndex] = _batchHash;
batchDataStore[_batchIndex] = BatchData(block.timestamp, block.timestamp, 0, 0);
committedStateRoots[_batchIndex] = _postStateRoot;
finalizedStateRoots[_batchIndex] = _postStateRoot;
lastCommittedBatchIndex = _batchIndex;
lastFinalizedBatchIndex = _batchIndex;
emit CommitBatch(_batchIndex, _batchHash);
emit FinalizeBatch(_batchIndex, _batchHash, _postStateRoot, bytes32(0));
}
/// @inheritdoc IRollup
function commitBatch(
BatchDataInput calldata batchDataInput,
BatchSignatureInput calldata batchSignatureInput
) external payable override onlyActiveStaker nonReqRevert whenNotPaused {
require(batchDataInput.version == 0, "invalid version");
// check whether the batch is empty
uint256 _blockContextsLength = batchDataInput.blockContexts.length;
require(_blockContextsLength > 0, "batch is empty");
require(batchDataInput.prevStateRoot != bytes32(0), "previous state root is zero");
require(batchDataInput.postStateRoot != bytes32(0), "new state root is zero");
// The overall memory layout in this function is organized as follows
// +---------------------+-------------------+------------------+
// | parent batch header | batch data hashes | new batch header |
// +---------------------+-------------------+------------------+
// ^ ^ ^
// batchPtr dataPtr newBatchPtr (re-use var batchPtr)
//
// 1. We copy the parent batch header from calldata to memory starting at batchPtr
// 2. we store the batch data hash
// 3. The memory starting at `newBatchPtr` is used to store the new batch header and compute
// the batch hash.
// the variable `batchPtr` will be reused later for the current batch
(uint256 _batchPtr, bytes32 _parentBatchHash) = _loadBatchHeader(batchDataInput.parentBatchHeader);
uint256 _batchIndex = BatchHeaderCodecV0.getBatchIndex(_batchPtr);
require(committedBatches[_batchIndex + 1] == bytes32(0), "batch already committed");
require(_batchIndex == lastCommittedBatchIndex, "incorrect batch index");
require(committedBatches[_batchIndex] == _parentBatchHash, "incorrect parent batch hash");
require(committedStateRoots[_batchIndex] == batchDataInput.prevStateRoot, "incorrect previous state root");
uint256 _totalL1MessagesPoppedOverall = BatchHeaderCodecV0.getTotalL1MessagePopped(_batchPtr);
// compute the data hash for batch
uint256 _totalL1MessagesPoppedInBatch;
uint256 _totalNumL1Messages;
bytes32 dataHash;
(dataHash, _totalNumL1Messages) = _commitBatch(
batchDataInput.blockContexts,
_totalL1MessagesPoppedInBatch,
_totalL1MessagesPoppedOverall,
batchDataInput.skippedL1MessageBitmap
);
unchecked {
_totalL1MessagesPoppedInBatch += _totalNumL1Messages;
_totalL1MessagesPoppedOverall += _totalNumL1Messages;
}
// check the length of bitmap
unchecked {
require(
((_totalL1MessagesPoppedInBatch + 255) / 256) * 32 == batchDataInput.skippedL1MessageBitmap.length,
"wrong bitmap length"
);
}
assembly {
_batchIndex := add(_batchIndex, 1) // increase batch index
}
bytes32 _blobVersionedHash = (blobhash(0) == bytes32(0)) ? ZERO_VERSIONED_HASH : blobhash(0);
{
uint256 _headerLength = BatchHeaderCodecV0.BATCH_HEADER_FIXED_LENGTH +
batchDataInput.skippedL1MessageBitmap.length;
assembly {
_batchPtr := mload(0x40)
mstore(0x40, add(_batchPtr, mul(_headerLength, 32)))
}
// store entries, the order matters
BatchHeaderCodecV0.storeVersion(_batchPtr, batchDataInput.version);
BatchHeaderCodecV0.storeBatchIndex(_batchPtr, _batchIndex);
BatchHeaderCodecV0.storeL1MessagePopped(_batchPtr, _totalL1MessagesPoppedInBatch);
BatchHeaderCodecV0.storeTotalL1MessagePopped(_batchPtr, _totalL1MessagesPoppedOverall);
BatchHeaderCodecV0.storeDataHash(_batchPtr, dataHash);
BatchHeaderCodecV0.storePrevStateHash(_batchPtr, batchDataInput.prevStateRoot);
BatchHeaderCodecV0.storePostStateHash(_batchPtr, batchDataInput.postStateRoot);
BatchHeaderCodecV0.storeWithdrawRootHash(_batchPtr, batchDataInput.withdrawalRoot);
BatchHeaderCodecV0.storeSequencerSetVerifyHash(_batchPtr, keccak256(batchSignatureInput.sequencerSets));
BatchHeaderCodecV0.storeParentBatchHash(_batchPtr, _parentBatchHash);
BatchHeaderCodecV0.storeSkippedBitmap(_batchPtr, batchDataInput.skippedL1MessageBitmap);
BatchHeaderCodecV0.storeBlobVersionedHash(_batchPtr, _blobVersionedHash);
committedBatches[_batchIndex] = BatchHeaderCodecV0.computeBatchHash(_batchPtr, _headerLength);
committedStateRoots[_batchIndex] = batchDataInput.postStateRoot;
uint256 proveRemainingTime = 0;
if (inChallenge) {
// Make the batch finalize time longer than the time required for the current challenge
proveRemainingTime = proofWindow + challenges[batchChallenged].startTime - block.timestamp;
}
// storage batch data for challenge status check
batchDataStore[_batchIndex] = BatchData(
block.timestamp,
block.timestamp + finalizationPeriodSeconds + proveRemainingTime,
_loadL2BlockNumber(batchDataInput.blockContexts),
// Before BLS is implemented, the accuracy of the sequencer set uploaded by rollup cannot be guaranteed.
// Therefore, if the batch is successfully challenged, only the submitter will be punished.
IL1Staking(l1StakingContract).getStakerBitmap(_msgSender()) // => batchSignature.signedSequencersBitmap
);
lastCommittedBatchIndex = _batchIndex;
}
// verify bls signature
require(
IL1Staking(l1StakingContract).verifySignature(
batchSignatureInput.signedSequencersBitmap,
_getValidSequencerSet(batchSignatureInput.sequencerSets, 0),
_getBLSMsgHash(batchDataInput),
batchSignatureInput.signature
),
"the signature verification failed"
);
emit CommitBatch(_batchIndex, committedBatches[_batchIndex]);
}
/// @inheritdoc IRollup
/// @dev If the owner wants to revert a sequence of batches by sending multiple transactions,
/// make sure to revert recent batches first.
function revertBatch(bytes calldata _batchHeader, uint256 _count) external onlyOwner {
require(_count > 0, "count must be nonzero");
(uint256 memPtr, bytes32 _batchHash) = _loadBatchHeader(_batchHeader);
// check batch hash
uint256 _batchIndex = BatchHeaderCodecV0.getBatchIndex(memPtr);
require(committedBatches[_batchIndex] == _batchHash, "incorrect batch hash");
// make sure no gap is left when reverting from the ending to the beginning.
require(committedBatches[_batchIndex + _count] == bytes32(0), "reverting must start from the ending");
// check finalization
require(_batchIndex > lastFinalizedBatchIndex, "can only revert unFinalized batch");
lastCommittedBatchIndex = _batchIndex - 1;
while (_count > 0) {
emit RevertBatch(_batchIndex, _batchHash);
committedBatches[_batchIndex] = bytes32(0);
// if challenge exist and not finished yet, return challenge deposit to challenger
if (batchInChallenge(_batchIndex)) {
batchChallengeReward[challenges[_batchIndex].challenger] += challenges[_batchIndex].challengeDeposit;
inChallenge = false;
}
delete challenges[_batchIndex];
if (revertReqIndex > 0 && _batchIndex == revertReqIndex) {
revertReqIndex = 0;
}
unchecked {
_batchIndex += 1;
_count -= 1;
}
_batchHash = committedBatches[_batchIndex];
if (_batchHash == bytes32(0)) {
break;
}
}
}
/// @dev challengeState challenges a batch by submitting a deposit.
function challengeState(
uint64 batchIndex,
bytes32 _batchHash
) external payable onlyChallenger nonReqRevert whenNotPaused {
require(!inChallenge, "already in challenge");
require(lastFinalizedBatchIndex < batchIndex, "batch already finalized");
require(committedBatches[batchIndex] == _batchHash, "incorrect batch hash");
require(batchExist(batchIndex), "batch not exist");
require(challenges[batchIndex].challenger == address(0), "batch already challenged");
// check challenge window
require(batchInsideChallengeWindow(batchIndex), "cannot challenge batch outside the challenge window");
// check challenge amount
require(msg.value >= IL1Staking(l1StakingContract).challengeDeposit(), "insufficient value");
batchChallenged = batchIndex;
challenges[batchIndex] = BatchChallenge(batchIndex, _msgSender(), msg.value, block.timestamp, false, false);
emit ChallengeState(batchIndex, _msgSender(), msg.value);
for (uint256 i = lastFinalizedBatchIndex + 1; i <= lastCommittedBatchIndex; i++) {
if (i != batchIndex) {
batchDataStore[i].finalizeTimestamp += proofWindow;
}
}
inChallenge = true;
}
/// @notice Update proofWindow.
/// @param _newWindow New proof window.
function updateProofWindow(uint256 _newWindow) external onlyOwner {
require(_newWindow > 0 && _newWindow != proofWindow, "invalid new proof window");
uint256 _oldProofWindow = proofWindow;
proofWindow = _newWindow;
emit UpdateProofWindow(_oldProofWindow, proofWindow);
}
/// @notice Update finalizationPeriodSeconds.
/// @param _newPeriod New finalize period seconds.
function updateFinalizePeriodSeconds(uint256 _newPeriod) external onlyOwner {
require(_newPeriod > 0 && _newPeriod != finalizationPeriodSeconds, "invalid new finalize period");
uint256 _oldFinalizationPeriodSeconds = finalizationPeriodSeconds;
finalizationPeriodSeconds = _newPeriod;
emit UpdateFinalizationPeriodSeconds(_oldFinalizationPeriodSeconds, finalizationPeriodSeconds);
}
/// @notice Add an account to the challenger list.
/// @param _account The address of account to add.
function addChallenger(address _account) external onlyOwner {
require(!isChallenger[_account], "account is already a challenger");
isChallenger[_account] = true;
emit UpdateChallenger(_account, true);
}
/// @notice Remove an account from the challenger list.
/// @param _account The address of account to remove.
function removeChallenger(address _account) external onlyOwner {
require(isChallenger[_account], "account is not a challenger");
isChallenger[_account] = false;
emit UpdateChallenger(_account, false);
}
/// @notice Update the address verifier contract.
/// @param _newVerifier The address of new verifier contract.
function updateVerifier(address _newVerifier) external onlyOwner {
require(_newVerifier != address(0) && _newVerifier != verifier, "invalid new verifier");
address _oldVerifier = verifier;
verifier = _newVerifier;
emit UpdateVerifier(_oldVerifier, _newVerifier);
}
/// @notice Update proof reward percentage
/// @param _newProofRewardPercent Percentage awarded to prover
function updateRewardPercentage(uint256 _newProofRewardPercent) external onlyOwner {
require(
_newProofRewardPercent > 0 && _newProofRewardPercent <= 100 && _newProofRewardPercent != proofRewardPercent,
"invalid proof reward percentage"
);
uint256 _oldRewardPercentage = proofRewardPercent;
proofRewardPercent = _newProofRewardPercent;
emit UpdateProofRewardPercent(_oldRewardPercentage, _newProofRewardPercent);
}
/// @notice claim prove remaining
/// @param receiver receiver address
function claimProveRemaining(address receiver) external onlyOwner {
uint256 _proveRemaining = proveRemaining;
proveRemaining = 0;
_transfer(receiver, _proveRemaining);
emit ProveRemainingClaimed(receiver, _proveRemaining);
}
/// @notice Pause the contract
/// @param _status The pause status to update.
function setPause(bool _status) external onlyOwner {
if (_status) {
_pause();
// if challenge exist and not finished yet, return challenge deposit to challenger
if (inChallenge) {
batchChallengeReward[challenges[batchChallenged].challenger] += challenges[batchChallenged]
.challengeDeposit;
delete challenges[batchChallenged];
inChallenge = false;
}
emit Paused(_msgSender());
} else {
_unpause();
emit Unpaused(_msgSender());
}
}
/*****************************
* Public Mutating Functions *
*****************************/
/// @dev proveState proves a batch by submitting a proof.
function proveState(bytes calldata _batchHeader, bytes calldata _batchProof) external nonReqRevert whenNotPaused {
// get batch data from batch header
(uint256 memPtr, bytes32 _batchHash) = _loadBatchHeader(_batchHeader);
// check batch hash
uint256 _batchIndex = BatchHeaderCodecV0.getBatchIndex(memPtr);
require(committedBatches[_batchIndex] == _batchHash, "incorrect batch hash");
// Ensure challenge exists and is not finished
require(batchInChallenge(_batchIndex), "batch in challenge");
// Mark challenge as finished
challenges[_batchIndex].finished = true;
inChallenge = false;
// Check for timeout
if (challenges[_batchIndex].startTime + proofWindow <= block.timestamp) {
// set status
challenges[_batchIndex].challengeSuccess = true;
_challengerWin(_batchIndex, batchDataStore[_batchIndex].signedSequencersBitmap, "Timeout");
} else {
_verifyProof(memPtr, _batchProof);
// Record defender win
_defenderWin(_batchIndex, _msgSender(), "Proof success");
}
}
/// @dev finalize batch
function finalizeBatch(bytes calldata _batchHeader) public nonReqRevert whenNotPaused {
// get batch data from batch header
(uint256 memPtr, bytes32 _batchHash) = _loadBatchHeader(_batchHeader);
uint256 _batchIndex = BatchHeaderCodecV0.getBatchIndex(memPtr);
require(committedBatches[_batchIndex] == _batchHash, "incorrect batch hash");
require(batchExist(_batchIndex), "batch not exist");
require(!batchInChallenge(_batchIndex), "batch in challenge");
require(!batchChallengedSuccess(_batchIndex), "batch should be revert");
require(!batchInsideChallengeWindow(_batchIndex), "batch in challenge window");
// verify previous state root.
require(
finalizedStateRoots[_batchIndex - 1] == BatchHeaderCodecV0.getPrevStateHash(memPtr),
"incorrect previous state root"
);
// avoid duplicated verification
require(finalizedStateRoots[_batchIndex] == bytes32(0), "batch already verified");
// check and update lastFinalizedBatchIndex
unchecked {
require(lastFinalizedBatchIndex + 1 == _batchIndex, "incorrect batch index");
lastFinalizedBatchIndex = _batchIndex;
}
// record state root and withdraw root
withdrawalRoots[BatchHeaderCodecV0.getWithdrawRootHash(memPtr)] = true;
finalizedStateRoots[_batchIndex] = BatchHeaderCodecV0.getPostStateHash(memPtr);
// Pop finalized and non-skipped message from L1MessageQueue.
_popL1Messages(
BatchHeaderCodecV0.getSkippedBitmapPtr(memPtr),
BatchHeaderCodecV0.getTotalL1MessagePopped(memPtr),
BatchHeaderCodecV0.getL1MessagePopped(memPtr)
);
delete batchDataStore[_batchIndex - 1];
delete committedStateRoots[_batchIndex - 1];
delete challenges[_batchIndex - 1];
emit FinalizeBatch(
_batchIndex,
committedBatches[_batchIndex],
BatchHeaderCodecV0.getPostStateHash(memPtr),
BatchHeaderCodecV0.getWithdrawRootHash(memPtr)
);
}
/// @notice Claim challenge reward
/// @param receiver The receiver address
function claimReward(address receiver) external {
uint256 amount = batchChallengeReward[_msgSender()];
require(amount != 0, "invalid batchChallengeReward");
delete batchChallengeReward[_msgSender()];
_transfer(receiver, amount);
emit ChallengeRewardClaim(receiver, amount);
}
/*************************
* Public View Functions *
*************************/
/// @inheritdoc IRollup
function isBatchFinalized(uint256 _batchIndex) external view override returns (bool) {
return _batchIndex <= lastFinalizedBatchIndex;
}
/// @dev Public function to checks whether the batch is in challenge.
/// @param batchIndex The index of the batch to be checked.
function batchInChallenge(uint256 batchIndex) public view returns (bool) {
return challenges[batchIndex].challenger != address(0) && !challenges[batchIndex].finished;
}
/// @dev Retrieves the success status of a batch challenge.
/// @param batchIndex The index of the batch to check.
function batchChallengedSuccess(uint256 batchIndex) public view returns (bool) {
return challenges[batchIndex].challengeSuccess;
}
/// @dev Public function to checks whether batch exists.
/// @param batchIndex The index of the batch to be checked.
function batchExist(uint256 batchIndex) public view returns (bool) {
return batchDataStore[batchIndex].originTimestamp > 0 && committedBatches[batchIndex] != bytes32(0);
}
/// @dev Public function to checks whether the batch is in challengeWindow.
/// @param batchIndex The index of the batch to be checked.
function batchInsideChallengeWindow(uint256 batchIndex) public view returns (bool) {
return batchDataStore[batchIndex].finalizeTimestamp > block.timestamp;
}
/**********************
* Internal Functions *
**********************/
/// @dev Internal function to pop finalized l1 messages.
/// @param bitmapPtr The memory offset of `skippedL1MessageBitmap`.
/// @param totalL1MessagePopped The total number of L1 messages popped in all batches including current batch.
/// @param l1MessagePopped The number of L1 messages popped in current batch.
function _popL1Messages(uint256 bitmapPtr, uint256 totalL1MessagePopped, uint256 l1MessagePopped) internal {
if (l1MessagePopped == 0) return;
unchecked {
uint256 startIndex = totalL1MessagePopped - l1MessagePopped;
uint256 bitmap;
for (uint256 i = 0; i < l1MessagePopped; i += 256) {
uint256 _count = 256;
if (l1MessagePopped - i < _count) {
_count = l1MessagePopped - i;
}
assembly {
bitmap := mload(bitmapPtr)
bitmapPtr := add(bitmapPtr, 0x20)
}
IL1MessageQueue(messageQueue).popCrossDomainMessage(startIndex, _count, bitmap);
startIndex += 256;
}
}
}
/// @dev Internal function to verify the zk proof.
function _verifyProof(uint256 memPtr, bytes calldata _batchProof) private view {
// Check validity of proof
require(_batchProof.length > 0, "Invalid batch proof");
uint256 _batchIndex = BatchHeaderCodecV0.getBatchIndex(memPtr);
bytes32 _blobVersionedHash = BatchHeaderCodecV0.getBlobVersionedHash(memPtr);
bytes32 _publicInputHash = keccak256(
abi.encodePacked(
LAYER_2_CHAIN_ID,
BatchHeaderCodecV0.getPrevStateHash(memPtr),
BatchHeaderCodecV0.getPostStateHash(memPtr),
BatchHeaderCodecV0.getWithdrawRootHash(memPtr),
BatchHeaderCodecV0.getSequencerSetVerifyHash(memPtr),
BatchHeaderCodecV0.getDataHash(memPtr),
_blobVersionedHash
)
);
IRollupVerifier(verifier).verifyAggregateProof(
BatchHeaderCodecV0.getVersion(memPtr),
_batchIndex,
_batchProof,
_publicInputHash
);
}
/// @dev Internal function to compute BLS msg hash
function _getBLSMsgHash(
BatchDataInput calldata // batchDataInput
) internal pure returns (bytes32) {
// TODO compute bls message hash
return bytes32(0);
}
/// @dev todo
function _getValidSequencerSet(
bytes calldata sequencerSets,
uint256 blockHeight
) internal pure returns (address[] memory) {
// TODO require submitter was in valid sequencer set after BLS was implemented
(
,
address[] memory sequencerSet0,
uint256 blockHeight1,
address[] memory sequencerSet1,
uint256 blockHeight2,
address[] memory sequencerSet2
) = abi.decode(sequencerSets, (uint256, address[], uint256, address[], uint256, address[]));
if (blockHeight >= blockHeight2) {
return sequencerSet2;
}
if (blockHeight >= blockHeight1) {
return sequencerSet1;
}
return sequencerSet0;
}
/// @dev Internal function executed when the defender wins.
/// @param batchIndex The index of the batch indicating where the challenge occurred.
/// @param prover The zkProof prover address.
/// @param _type Description of the challenge type.
function _defenderWin(uint256 batchIndex, address prover, string memory _type) internal {
uint256 challengeDeposit = challenges[batchIndex].challengeDeposit;
uint256 reward = (challengeDeposit * proofRewardPercent) / 100;
proveRemaining += challengeDeposit - reward;
batchChallengeReward[prover] += reward;
emit ChallengeRes(batchIndex, prover, _type);
}
/// @dev Internal function executed when the challenger wins.
/// @param batchIndex The index of the batch indicating where the challenge occurred.
/// @param sequencersBitmap An array containing the sequencers to be slashed.
/// @param _type Description of the challenge type.
function _challengerWin(uint256 batchIndex, uint256 sequencersBitmap, string memory _type) internal {
revertReqIndex = batchIndex;
address challenger = challenges[batchIndex].challenger;
uint256 reward = IL1Staking(l1StakingContract).slash(sequencersBitmap);
batchChallengeReward[challenges[batchIndex].challenger] += (challenges[batchIndex].challengeDeposit + reward);
emit ChallengeRes(batchIndex, challenger, _type);
}
/// @dev Internal function to transfer ETH to a specified address.
/// @param _to The address to transfer ETH to.
/// @param _amount The amount of ETH to transfer.
function _transfer(address _to, uint256 _amount) internal {
if (_amount > 0) {
(bool success, ) = _to.call{value: _amount}("");
require(success, "Rollup: ETH transfer failed");
}
}
/// @dev Internal function to load batch header from calldata to memory.
/// @param _batchHeader The batch header in calldata.
/// @return _memPtr The start memory offset of loaded batch header.
/// @return _batchHash The hash of the loaded batch header.
function _loadBatchHeader(bytes calldata _batchHeader) internal pure returns (uint256 _memPtr, bytes32 _batchHash) {
// load to memory
uint256 _length;
(_memPtr, _length) = BatchHeaderCodecV0.loadAndValidate(_batchHeader);
// compute batch hash
_batchHash = BatchHeaderCodecV0.computeBatchHash(_memPtr, _length);
}
/// @dev Internal function to load the latestL2BlockNumber.
/// @param _blockContexts The batch block contexts in memory.
function _loadL2BlockNumber(bytes memory _blockContexts) internal pure returns (uint256) {
uint256 blockPtr;
uint256 batchPtr;
assembly {
batchPtr := add(_blockContexts, 0x20)
blockPtr := add(batchPtr, 2)
}
uint256 _numBlocks = BatchCodecV0.validateBatchLength(batchPtr, _blockContexts.length);
for (uint256 i = 0; i < _numBlocks - 1; i++) {
unchecked {
blockPtr += BatchCodecV0.BLOCK_CONTEXT_LENGTH;
}
}
uint256 l2BlockNumber = BatchCodecV0.getBlockNumber(blockPtr);
return l2BlockNumber;
}
/// @dev Internal function to commit a batch with version 0.
/// @param _blockContexts The encoded block contexts to commit.
/// @param _totalL1MessagesPoppedInBatch The total number of L1 messages popped in current batch.
/// @param _totalL1MessagesPoppedOverall The total number of L1 messages popped in all batches including current batch.
/// @param _skippedL1MessageBitmap The bitmap indicates whether each L1 message is skipped or not.
/// @return _dataHash The computed data hash for this batch.
/// @return _totalNumL1MessagesInBatch The total number of L1 message popped in current batch
function _commitBatch(
bytes memory _blockContexts,
uint256 _totalL1MessagesPoppedInBatch,
uint256 _totalL1MessagesPoppedOverall,
bytes calldata _skippedL1MessageBitmap
) internal view returns (bytes32 _dataHash, uint256 _totalNumL1MessagesInBatch) {
uint256 batchPtr;
uint256 startDataPtr;
uint256 dataPtr;
assembly {
dataPtr := mload(0x40)
startDataPtr := dataPtr
batchPtr := add(_blockContexts, 0x20) // skip batchContexts.length
}
uint256 _numBlocks = BatchCodecV0.validateBatchLength(batchPtr, _blockContexts.length);
assembly {
batchPtr := add(batchPtr, 2) // skip numBlocks
}
// concatenate block contexts, use scope to avoid stack too deep
for (uint256 i = 0; i < _numBlocks; i++) {
dataPtr = BatchCodecV0.copyBlockContext(batchPtr, dataPtr, i);
uint256 blockPtr = batchPtr + i * BatchCodecV0.BLOCK_CONTEXT_LENGTH;
uint256 _numL1MessagesInBlock = BatchCodecV0.getNumL1Messages(blockPtr);
unchecked {
_totalNumL1MessagesInBatch += _numL1MessagesInBlock;
}
}
assembly {
mstore(0x40, add(dataPtr, mul(_totalNumL1MessagesInBatch, 0x20))) // reserve memory for l1 message hashes
}
// concatenate tx hashes
while (_numBlocks > 0) {
// concatenate l1 message hashes
uint256 _numL1MessagesInBlock = BatchCodecV0.getNumL1Messages(batchPtr);
dataPtr = _loadL1MessageHashes(
dataPtr,
_numL1MessagesInBlock,
_totalL1MessagesPoppedInBatch,
_totalL1MessagesPoppedOverall,
_skippedL1MessageBitmap
);
uint256 _numTransactionsInBlock = BatchCodecV0.getNumTransactions(batchPtr);
require(_numTransactionsInBlock >= _numL1MessagesInBlock, "num txs less than num L1 msgs");
unchecked {
_totalL1MessagesPoppedInBatch += _numL1MessagesInBlock;
_totalL1MessagesPoppedOverall += _numL1MessagesInBlock;
_numBlocks -= 1;
batchPtr += BatchCodecV0.BLOCK_CONTEXT_LENGTH;
}
}
// compute data hash and store to memory
assembly {
_dataHash := keccak256(startDataPtr, sub(dataPtr, startDataPtr))
}
}
/// @dev Internal function to load L1 message hashes from the message queue.
/// @param _ptr The memory offset to store the transaction hash.
/// @param _numL1Messages The number of L1 messages to load.
/// @param _totalL1MessagesPoppedInBatch The total number of L1 messages popped in current batch.
/// @param _totalL1MessagesPoppedOverall The total number of L1 messages popped in all batches including current batch.
/// @param _skippedL1MessageBitmap The bitmap indicates whether each L1 message is skipped or not.
/// @return uint256 The new memory offset after loading.
function _loadL1MessageHashes(
uint256 _ptr,
uint256 _numL1Messages,
uint256 _totalL1MessagesPoppedInBatch,
uint256 _totalL1MessagesPoppedOverall,
bytes calldata _skippedL1MessageBitmap
) internal view returns (uint256) {
if (_numL1Messages == 0) {
return _ptr;
}
IL1MessageQueue _messageQueue = IL1MessageQueue(messageQueue);
unchecked {
uint256 _bitmap;
uint256 rem;
for (uint256 i = 0; i < _numL1Messages; i++) {
uint256 quo = _totalL1MessagesPoppedInBatch >> 8;
rem = _totalL1MessagesPoppedInBatch & 0xff;
// load bitmap every 256 bits
if (i == 0 || rem == 0) {
assembly {
_bitmap := calldataload(add(_skippedL1MessageBitmap.offset, mul(0x20, quo)))
}
}
if (((_bitmap >> rem) & 1) == 0) {
// message not skipped
bytes32 _hash = _messageQueue.getCrossDomainMessage(_totalL1MessagesPoppedOverall);
assembly {
mstore(_ptr, _hash)
_ptr := add(_ptr, 0x20)
}
}
_totalL1MessagesPoppedInBatch += 1;
_totalL1MessagesPoppedOverall += 1;
}
// check last L1 message is not skipped, _totalL1MessagesPoppedInBatch must > 0
rem = (_totalL1MessagesPoppedInBatch - 1) & 0xff;
require(((_bitmap >> rem) & 1) == 0, "cannot skip last L1 message");
}
return _ptr;
}
}
IL1Staking.sol 119 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
interface IL1Staking {
/**********
* Events *
**********/
/// @notice staker registered
/// @param addr staker address
/// @param tmKey tendermint pubkey
/// @param blsKey BLS pubkey
event Registered(address addr, bytes32 tmKey, bytes blsKey);
/// @notice stakers removed
/// @param stakers stakers removed
event StakersRemoved(address[] stakers);
/// @notice Withdrawn
/// @param addr staker address
/// @param unlockHeight unlock block height
event Withdrawn(address indexed addr, uint256 unlockHeight);
/// @notice staker claimed
/// @param staker staker claimed
/// @param receiver receiver address
event Claimed(address indexed staker, address receiver);
/// @notice stakers were slashed
/// @param stakers slashed stakers
event Slashed(address[] stakers);
/// @notice slash remaining claimed
/// @param receiver receiver address
/// @param amount claimed amount
event SlashRemainingClaimed(address receiver, uint256 amount);
/// @notice whitelist updated
/// @param add addresses added
/// @param remove addresses removed
event WhitelistUpdated(address[] add, address[] remove);
/// @notice staking value updated
/// @param oldStakingValue old staking value
/// @param newStakingValue new staking value
event StakingValueUpdated(uint256 oldStakingValue, uint256 newStakingValue);
/// @notice gas limit add staker updated
/// @param oldGasLimit old gas limit
/// @param newGasLimit new gas limit
event GasLimitAddStakerUpdated(uint256 oldGasLimit, uint256 newGasLimit);
/// @notice gas limit remove stakers updated
/// @param oldGasLimit old gas limit
/// @param newGasLimit new gas limit
event GasLimitRemoveStakersUpdated(uint256 oldGasLimit, uint256 newGasLimit);
/// @notice reward percentage updated
/// @param oldPercentage old percentage
/// @param newPercentage new percentage
event RewardPercentageUpdated(uint256 oldPercentage, uint256 newPercentage);
/// @notice challenge deposit value updated
/// @param oldChallengeDeposit old challengeDeposit
/// @param newChallengeDeposit new challengeDeposit
event ChallengeDepositUpdated(uint256 oldChallengeDeposit, uint256 newChallengeDeposit);
/*************************
* Public View Functions *
*************************/
/// @notice return all stakers
function getStakers() external view returns (address[255] memory);
/// @notice return active stakers
function getActiveStakers() external view returns (address[] memory);
/// @notice return staking value
function stakingValue() external view returns (uint256);
/// @notice return challenge deposit value
function challengeDeposit() external view returns (uint256);
/// @notice whether address is staker
/// @param addr the address to check
function isStaker(address addr) external view returns (bool);
/// @notice whether address is active staker
/// @param addr the address to check
function isActiveStaker(address addr) external view returns (bool);
/// @notice get staker bitmap
/// @param staker the staker address
function getStakerBitmap(address staker) external view returns (uint256);
/// @notice get stakers bitmap
/// @param stakers the staker address array
function getStakersBitmap(address[] calldata stakers) external view returns (uint256);
/// @notice verify BLS signature
/// @param signedSequencersBitmap bitmap of signed sequencers
/// @param sequencerSet sequencer set
/// @param msgHash bls message hash
/// @param signature batch signature
function verifySignature(
uint256 signedSequencersBitmap,
address[] calldata sequencerSet,
bytes32 msgHash,
bytes calldata signature
) external view returns (bool);
/*****************************
* Public Mutating Functions *
*****************************/
/// @notice challenger win, slash sequencers
/// @param sequencersBitmap the sequencers to slash
function slash(uint256 sequencersBitmap) external returns (uint256);
}
BatchCodecV0.sol 108 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
/* solhint-disable */
/// @dev Below is the encoding for `Batch`, total 60*n+1 bytes.
/// ```text
/// * Field Bytes Type Index Comments
/// * numBlocks 2 uint16 0 The number of blocks in this batch
/// * block[0] 60 BlockContext 1 The first block in this batch
/// * ......
/// * block[i] 60 BlockContext 60*i+1 The (i+1)'th block in this batch
/// * ......
/// * block[n-1] 60 BlockContext 60*n-59 The last block in this batch
/// ```
///
/// @dev Below is the encoding for `BlockContext`, total 60 bytes.
/// ```text
/// * Field Bytes Type Index Comments
/// * blockNumber 8 uint64 0 The height of this block.
/// * timestamp 8 uint64 8 The timestamp of this block.
/// * baseFee 32 uint256 16 The base fee of this block.
/// * gasLimit 8 uint64 48 The gas limit of this block.
/// * numTransactions 2 uint16 56 The number of transactions in this block, both L1 & L2 txs.
/// * numL1Messages 2 uint16 58 The number of l1 messages in this block.
/// ```
library BatchCodecV0 {
/// @dev Thrown when no blocks in batch.
error ErrorNoBlockInBatch();
/// @dev Thrown when the length of batch is incorrect.
error ErrorIncorrectBatchLength();
/// @dev The length of one block context.
uint256 internal constant BLOCK_CONTEXT_LENGTH = 60;
/// @notice Validate the length of batch.
/// @param batchPtr The start memory offset of the batch in memory.
/// @param _length The length of the batch.
/// @return _numBlocks The number of blocks in current batch.
function validateBatchLength(uint256 batchPtr, uint256 _length) internal pure returns (uint256 _numBlocks) {
_numBlocks = getNumBlocks(batchPtr);
// should contain at least one block
if (_numBlocks == 0) revert ErrorNoBlockInBatch();
// should contain the number of the blocks and block contexts
if (_length != 2 + _numBlocks * BLOCK_CONTEXT_LENGTH) revert ErrorIncorrectBatchLength();
}
/// @notice Return the number of blocks in current batch.
/// @param batchPtr The start memory offset of the batch in memory.
/// @return _numBlocks The number of blocks in current batch.
function getNumBlocks(uint256 batchPtr) internal pure returns (uint256 _numBlocks) {
assembly {
_numBlocks := shr(240, mload(batchPtr))
}
}
/// @notice Copy the block context to another memory.
/// @param blockPtr The start memory offset of the first block context in memory.
/// @param dstPtr The destination memory offset to store the block context.
/// @param index The index of block context to copy.
/// @return uint256 The new destination memory offset after copy.
function copyBlockContext(uint256 blockPtr, uint256 dstPtr, uint256 index) internal pure returns (uint256) {
// only first 58 bytes is needed.
assembly {
blockPtr := add(blockPtr, mul(BLOCK_CONTEXT_LENGTH, index))
mstore(dstPtr, mload(blockPtr)) // first 32 bytes
mstore(
add(dstPtr, 0x20),
and(mload(add(blockPtr, 0x20)), 0xffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000)
) // next 26 bytes
dstPtr := add(dstPtr, 58)
}
return dstPtr;
}
/// @notice Return the number of transactions in current block.
/// @param blockPtr The start memory offset of the block context in memory.
/// @return _numTransactions The number of transactions in current block.
function getNumTransactions(uint256 blockPtr) internal pure returns (uint256 _numTransactions) {
assembly {
_numTransactions := shr(240, mload(add(blockPtr, 56)))
}
}
/// @notice Return the number of L1 messages in current block.
/// @param blockPtr The start memory offset of the block context in memory.
/// @return _numL1Messages The number of L1 messages in current block.
function getNumL1Messages(uint256 blockPtr) internal pure returns (uint256 _numL1Messages) {
assembly {
_numL1Messages := shr(240, mload(add(blockPtr, 58)))
}
}
/// @notice Return the number of the block.
/// @param blockPtr The start memory offset of the block context in memory.
/// @return _blockNumber The block number of blockPtr in current block.
function getBlockNumber(uint256 blockPtr) internal pure returns (uint256 _blockNumber) {
assembly {
_blockNumber := shr(192, mload(blockPtr))
}
}
}
BatchHeaderCodecV0.sol 286 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
// solhint-disable no-inline-assembly
/// @dev Below is the encoding for `BatchHeader` V0, total 249 + ceil(l1MessagePopped / 256) * 32 bytes.
/// ```text
/// * Field Bytes Type Index Comments
/// * version 1 uint8 0 The batch version
/// * batchIndex 8 uint64 1 The index of the batch
/// * l1MessagePopped 8 uint64 9 Number of L1 messages popped in the batch
/// * totalL1MessagePopped 8 uint64 17 Number of total L1 messages popped after the batch
/// * dataHash 32 bytes32 25 The data hash of the batch
/// * blobVersionedHash 32 bytes32 57 The versioned hash of the blob with this batch’s data
/// * prevStateHash 32 bytes32 89 Preview state root
/// * postStateHash 32 bytes32 121 Post state root
/// * withdrawRootHash 32 bytes32 153 L2 withdrawal tree root hash
/// * sequencerSetVerifyHash 32 bytes32 185 L2 sequencers set verify hash
/// * parentBatchHash 32 bytes32 217 The parent batch hash
/// * skippedL1MessageBitmap dynamic uint256[] 249 A bitmap to indicate which L1 messages are skipped in the batch
/// ```
library BatchHeaderCodecV0 {
/// @dev The length of fixed parts of the batch header.
uint256 internal constant BATCH_HEADER_FIXED_LENGTH = 249;
/// @notice Load batch header in calldata to memory.
/// @param _batchHeader The encoded batch header bytes in calldata.
/// @return batchPtr The start memory offset of the batch header in memory.
/// @return length The length in bytes of the batch header.
function loadAndValidate(bytes calldata _batchHeader) internal pure returns (uint256 batchPtr, uint256 length) {
length = _batchHeader.length;
require(length >= BATCH_HEADER_FIXED_LENGTH, "batch header length too small");
// copy batch header to memory.
assembly {
batchPtr := mload(0x40)
calldatacopy(batchPtr, _batchHeader.offset, length)
mstore(0x40, add(batchPtr, length))
}
// check batch header length
uint256 _l1MessagePopped = getL1MessagePopped(batchPtr);
unchecked {
require(length == BATCH_HEADER_FIXED_LENGTH + ((_l1MessagePopped + 255) / 256) * 32, "wrong bitmap length");
}
}
/// @notice Get the version of the batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _version The version of the batch header.
function getVersion(uint256 batchPtr) internal pure returns (uint256 _version) {
assembly {
_version := shr(248, mload(batchPtr))
}
}
/// @notice Get the batch index of the batch.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _batchIndex The batch index of the batch.
function getBatchIndex(uint256 batchPtr) internal pure returns (uint256 _batchIndex) {
assembly {
_batchIndex := shr(192, mload(add(batchPtr, 1)))
}
}
/// @notice Get the number of L1 messages of the batch.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _l1MessagePopped The number of L1 messages of the batch.
function getL1MessagePopped(uint256 batchPtr) internal pure returns (uint256 _l1MessagePopped) {
assembly {
_l1MessagePopped := shr(192, mload(add(batchPtr, 9)))
}
}
/// @notice Get the number of L1 messages popped before this batch.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _totalL1MessagePopped The the number of L1 messages popped before this batch.
function getTotalL1MessagePopped(uint256 batchPtr) internal pure returns (uint256 _totalL1MessagePopped) {
assembly {
_totalL1MessagePopped := shr(192, mload(add(batchPtr, 17)))
}
}
/// @notice Get the data hash of the batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _dataHash The data hash of the batch header.
function getDataHash(uint256 batchPtr) internal pure returns (bytes32 _dataHash) {
assembly {
_dataHash := mload(add(batchPtr, 25))
}
}
/// @notice Get the blob versioned hash of the batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _blobVersionedHash The blob versioned hash of the batch header.
function getBlobVersionedHash(uint256 batchPtr) internal pure returns (bytes32 _blobVersionedHash) {
assembly {
_blobVersionedHash := mload(add(batchPtr, 57))
}
}
function getPrevStateHash(uint256 batchPtr) internal pure returns (bytes32 _prevStateHash) {
assembly {
_prevStateHash := mload(add(batchPtr, 89))
}
}
function getPostStateHash(uint256 batchPtr) internal pure returns (bytes32 _postStateHash) {
assembly {
_postStateHash := mload(add(batchPtr, 121))
}
}
function getWithdrawRootHash(uint256 batchPtr) internal pure returns (bytes32 _withdrawRootHash) {
assembly {
_withdrawRootHash := mload(add(batchPtr, 153))
}
}
function getSequencerSetVerifyHash(uint256 batchPtr) internal pure returns (bytes32 _sequencerSetVerifyHash) {
assembly {
_sequencerSetVerifyHash := mload(add(batchPtr, 185))
}
}
/// @notice Get the parent batch hash of the batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _parentBatchHash The parent batch hash of the batch header.
function getParentBatchHash(uint256 batchPtr) internal pure returns (bytes32 _parentBatchHash) {
assembly {
_parentBatchHash := mload(add(batchPtr, 217))
}
}
/// @notice Get the start memory offset for skipped L1 messages bitmap.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _bitmapPtr the start memory offset for skipped L1 messages bitmap.
function getSkippedBitmapPtr(uint256 batchPtr) internal pure returns (uint256 _bitmapPtr) {
assembly {
_bitmapPtr := add(batchPtr, BATCH_HEADER_FIXED_LENGTH)
}
}
/// @notice Get the skipped L1 messages bitmap.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param index The index of bitmap to load.
/// @return _bitmap The bitmap from bits `index * 256` to `index * 256 + 255`.
function getSkippedBitmap(uint256 batchPtr, uint256 index) internal pure returns (uint256 _bitmap) {
assembly {
batchPtr := add(batchPtr, BATCH_HEADER_FIXED_LENGTH)
_bitmap := mload(add(batchPtr, mul(index, 32)))
}
}
/// @notice Store the version of batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _version The version of batch header.
function storeVersion(uint256 batchPtr, uint256 _version) internal pure {
assembly {
mstore8(batchPtr, _version)
}
}
/// @notice Store the batch index of batch header.
/// @dev Because this function can overwrite the subsequent fields, it must be called before
/// `storeL1MessagePopped`, `storeTotalL1MessagePopped`, and `storeDataHash`.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _batchIndex The batch index.
function storeBatchIndex(uint256 batchPtr, uint256 _batchIndex) internal pure {
assembly {
mstore(add(batchPtr, 1), shl(192, _batchIndex))
}
}
/// @notice Store the number of L1 messages popped in current batch to batch header.
/// @dev Because this function can overwrite the subsequent fields, it must be called before
/// `storeTotalL1MessagePopped` and `storeDataHash`.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _l1MessagePopped The number of L1 messages popped in current batch.
function storeL1MessagePopped(uint256 batchPtr, uint256 _l1MessagePopped) internal pure {
assembly {
mstore(add(batchPtr, 9), shl(192, _l1MessagePopped))
}
}
/// @notice Store the total number of L1 messages popped after current batch to batch header.
/// @dev Because this function can overwrite the subsequent fields, it must be called before
/// `storeDataHash`.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _totalL1MessagePopped The total number of L1 messages popped after current batch.
function storeTotalL1MessagePopped(uint256 batchPtr, uint256 _totalL1MessagePopped) internal pure {
assembly {
mstore(add(batchPtr, 17), shl(192, _totalL1MessagePopped))
}
}
/// @notice Store the data hash of batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _dataHash The data hash.
function storeDataHash(uint256 batchPtr, bytes32 _dataHash) internal pure {
assembly {
mstore(add(batchPtr, 25), _dataHash)
}
}
/// @notice Store the parent batch hash of batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _blobVersionedHash The versioned hash of the blob with this batch’s data.
function storeBlobVersionedHash(uint256 batchPtr, bytes32 _blobVersionedHash) internal pure {
assembly {
mstore(add(batchPtr, 57), _blobVersionedHash)
}
}
/// @dev Stores the previous state hash.
/// @param batchPtr The memory pointer to the location where the previous state hash will be stored.
/// @param _prevStateHash The hash of the previous state to be stored.
function storePrevStateHash(uint256 batchPtr, bytes32 _prevStateHash) internal pure {
assembly {
mstore(add(batchPtr, 89), _prevStateHash)
}
}
/// @dev Stores the post-state hash.
/// @param batchPtr The memory pointer to the location where the post-state hash will be stored.
/// @param _postStateHash The hash of the post-state to be stored.
function storePostStateHash(uint256 batchPtr, bytes32 _postStateHash) internal pure {
assembly {
mstore(add(batchPtr, 121), _postStateHash)
}
}
/// @dev Stores the withdrawal root hash.
/// @param batchPtr The memory pointer to the location where the hash will be stored.
/// @param _withdrawRootHash The hash of the withdrawal root to be stored.
function storeWithdrawRootHash(uint256 batchPtr, bytes32 _withdrawRootHash) internal pure {
assembly {
mstore(add(batchPtr, 153), _withdrawRootHash)
}
}
/// @dev Stores the hash for verifying the sequencer set.
/// @param batchPtr The memory pointer to the batch data.
/// @param _sequencerSetVerifyHash The hash of the sequencer set to be stored.
function storeSequencerSetVerifyHash(uint256 batchPtr, bytes32 _sequencerSetVerifyHash) internal pure {
assembly {
mstore(add(batchPtr, 185), _sequencerSetVerifyHash)
}
}
/// @notice Store the parent batch hash of batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _parentBatchHash The parent batch hash.
function storeParentBatchHash(uint256 batchPtr, bytes32 _parentBatchHash) internal pure {
assembly {
mstore(add(batchPtr, 217), _parentBatchHash)
}
}
/// @notice Store the skipped L1 message bitmap of batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _skippedL1MessageBitmap The skipped L1 message bitmap.
function storeSkippedBitmap(uint256 batchPtr, bytes calldata _skippedL1MessageBitmap) internal pure {
assembly {
calldatacopy(
add(batchPtr, BATCH_HEADER_FIXED_LENGTH),
_skippedL1MessageBitmap.offset,
_skippedL1MessageBitmap.length
)
}
}
/// @notice Compute the batch hash.
/// @dev Caller should make sure that the encoded batch header is correct.
///
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param length The length of the batch.
/// @return _batchHash The hash of the corresponding batch.
function computeBatchHash(uint256 batchPtr, uint256 length) internal pure returns (bytes32 _batchHash) {
// in the current version, the hash is: keccak(BatchHeader without timestamp)
assembly {
_batchHash := keccak256(batchPtr, length)
}
}
}
IRollupVerifier.sol 17 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
interface IRollupVerifier {
/// @notice Verify aggregate zk proof.
/// @param _version The version of the verifier.
/// @param _batchIndex The batch index to verify.
/// @param _aggrProof The aggregated proof.
/// @param _publicInputHash The public input hash.
function verifyAggregateProof(
uint256 _version,
uint256 _batchIndex,
bytes calldata _aggrProof,
bytes32 _publicInputHash
) external view;
}
OwnableUpgradeable.sol 95 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
Initializable.sol 166 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
PausableUpgradeable.sol 117 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
AddressUpgradeable.sol 244 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
ContextUpgradeable.sol 41 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
Read Contract
LAYER_2_CHAIN_ID 0x5f77cf1d → uint64
__maxNumTxInChunk 0xdff7827e → uint256
batchChallengeReward 0xabc8d68d → uint256
batchChallenged 0x18463fb0 → uint256
batchChallengedSuccess 0x910129d4 → bool
batchDataStore 0x5ef7a94a → uint256, uint256, uint256, uint256
batchExist 0x21e2f9e0 → bool
batchInChallenge 0xde8b3035 → bool
batchInsideChallengeWindow 0x18af3b2b → bool
challenges 0x8f1d3776 → uint64, address, uint256, uint256, bool, bool
committedBatches 0x2362f03e → bytes32
committedStateRoots 0x68589dfa → bytes32
finalizationPeriodSeconds 0xce5db8d6 → uint256
finalizedStateRoots 0x2571098d → bytes32
inChallenge 0x88b1ea09 → bool
isBatchFinalized 0x116a1f42 → bool
isChallenger 0xa415d8dc → bool
l1StakingContract 0xddd8a3dc → address
lastCommittedBatchIndex 0x121dcd50 → uint256
lastFinalizedBatchIndex 0x059def61 → uint256
messageQueue 0x3b70c18a → address
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
proofRewardPercent 0xfb1e8b04 → uint256
proofWindow 0xa479265d → uint256
proveRemaining 0x3e001b66 → uint256
revertReqIndex 0xb31a77d3 → uint256
verifier 0x2b7ac3f3 → address
withdrawalRoots 0x04d77215 → bool
Write Contract 19 functions
These functions modify contract state and require a wallet transaction to execute.
addChallenger 0x0ceb6780
address _account
challengeState 0xcd4edc69
uint64 batchIndex
bytes32 _batchHash
claimProveRemaining 0xb35dac4e
address receiver
claimReward 0xd279c191
address receiver
commitBatch 0x9f53dbe4
tuple batchDataInput
tuple batchSignatureInput
finalizeBatch 0x13361101
bytes _batchHeader
importGenesisBatch 0xb3e0a509
bytes _batchHeader
initialize 0x728cdbca
address _l1StakingContract
address _messageQueue
address _verifier
uint256 _finalizationPeriodSeconds
uint256 _proofWindow
uint256 _proofRewardPercent
initialize2 0x61267290
bytes32 _prevStateRoot
proveState 0xb3484425
bytes _batchHeader
bytes _batchProof
removeChallenger 0x6c578c1d
address _account
renounceOwnership 0x715018a6
No parameters
revertBatch 0x10d44583
bytes _batchHeader
uint256 _count
setPause 0xbedb86fb
bool _status
transferOwnership 0xf2fde38b
address newOwner
updateFinalizePeriodSeconds 0xe3fff1dd
uint256 _newPeriod
updateProofWindow 0x57e0af6c
uint256 _newWindow
updateRewardPercentage 0xa4f209b0
uint256 _newProofRewardPercent
updateVerifier 0x97fc007c
address _newVerifier
Recent Transactions
This address has 1 on-chain transactions, but only 1.4% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →