diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 922d10648e5e..2f237110ddbb 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -152,6 +152,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, if chainConfig.CurieBlock != nil && chainConfig.CurieBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 { misc.ApplyCurieHardFork(statedb) } + // Apply Feynman hard fork + if chainConfig.IsFeynmanTransitionBlock(pre.Env.Timestamp, pre.Env.ParentTimestamp) { + misc.ApplyFeynmanHardFork(statedb) + } // Apply EIP-2935 if pre.Env.BlockHashes != nil && chainConfig.IsFeynman(pre.Env.Timestamp) { var ( diff --git a/consensus/misc/feynman.go b/consensus/misc/feynman.go new file mode 100644 index 000000000000..b933187cf9ee --- /dev/null +++ b/consensus/misc/feynman.go @@ -0,0 +1,22 @@ +package misc + +import ( + "github.com/scroll-tech/go-ethereum/common" + "github.com/scroll-tech/go-ethereum/core/state" + "github.com/scroll-tech/go-ethereum/log" + "github.com/scroll-tech/go-ethereum/rollup/rcfg" +) + +// ApplyFeynmanHardFork modifies the state database according to the Feynman hard-fork rules, +// updating the bytecode and storage of the L1GasPriceOracle contract. +func ApplyFeynmanHardFork(statedb *state.StateDB) { + log.Info("Applying Feynman hard fork") + + // update contract byte code + statedb.SetCode(rcfg.L1GasPriceOracleAddress, rcfg.FeynmanL1GasPriceOracleBytecode) + + // initialize new storage slots + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.IsFeynmanSlot, common.BytesToHash([]byte{1})) + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.PenaltyThresholdSlot, common.BigToHash(rcfg.InitialPenaltyThreshold)) + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.PenaltyFactorSlot, common.BigToHash(rcfg.InitialPenaltyFactor)) +} diff --git a/core/chain_makers.go b/core/chain_makers.go index 47a7d9fab847..b37ed9c3eeec 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -249,6 +249,9 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse if config.CurieBlock != nil && config.CurieBlock.Cmp(b.header.Number) == 0 { misc.ApplyCurieHardFork(statedb) } + if config.IsFeynmanTransitionBlock(b.Time(), parent.Time()) { + misc.ApplyFeynmanHardFork(statedb) + } // Execute any user modifications to the block if gen != nil { gen(i, b) diff --git a/core/state_processor.go b/core/state_processor.go index ddbc9d43bd43..d031bc848adf 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -91,6 +91,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if p.config.CurieBlock != nil && p.config.CurieBlock.Cmp(block.Number()) == 0 { misc.ApplyCurieHardFork(statedb) } + // Apply Feynman hard fork + parent := p.bc.GetHeaderByHash(block.ParentHash()) + if p.config.IsFeynmanTransitionBlock(block.Time(), parent.Time) { + misc.ApplyFeynmanHardFork(statedb) + } blockContext := NewEVMBlockContext(header, p.bc, p.config, nil) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) processorBlockTransactionGauge.Update(int64(block.Transactions().Len())) diff --git a/eth/api.go b/eth/api.go index 0752a3cb158c..cac47bce5258 100644 --- a/eth/api.go +++ b/eth/api.go @@ -362,6 +362,11 @@ func generateWitness(blockchain *core.BlockChain, block *types.Block) (*stateles // Collect storage locations that prover needs but sequencer might not touch necessarily statedb.GetState(rcfg.L2MessageQueueAddress, rcfg.WithdrawTrieRootSlot) + // Note: scroll-revm detects the Feynman transition block using this storage slot, + // since it does not have access to the parent block timestamp. We need to make + // sure that this is always present in the execution witness. + statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.IsFeynmanSlot) + receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, *blockchain.GetVMConfig()) if err != nil { return nil, fmt.Errorf("failed to process block %d: %w", block.Number(), err) diff --git a/miner/scroll_worker.go b/miner/scroll_worker.go index 8af97f1cd7a9..56b458e4d5a7 100644 --- a/miner/scroll_worker.go +++ b/miner/scroll_worker.go @@ -464,8 +464,7 @@ func (w *worker) collectPendingL1Messages(startIndex uint64) []types.L1MessageTx } // newWork -func (w *worker) newWork(now time.Time, parentHash common.Hash, reorging bool, reorgReason error) error { - parent := w.chain.GetBlockByHash(parentHash) +func (w *worker) newWork(now time.Time, parent *types.Block, reorging bool, reorgReason error) error { header := &types.Header{ ParentHash: parent.Hash(), Number: new(big.Int).Add(parent.Number(), common.Big1), @@ -586,13 +585,14 @@ func (w *worker) newWork(now time.Time, parentHash common.Hash, reorging bool, r } // tryCommitNewWork -func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorging bool, reorgReason error) (common.Hash, error) { +func (w *worker) tryCommitNewWork(now time.Time, parentHash common.Hash, reorging bool, reorgReason error) (common.Hash, error) { + parent := w.chain.GetBlockByHash(parentHash) err := w.newWork(now, parent, reorging, reorgReason) if err != nil { return common.Hash{}, fmt.Errorf("failed creating new work: %w", err) } - shouldCommit, err := w.handleForks() + shouldCommit, err := w.handleForks(parent) if err != nil { return common.Hash{}, fmt.Errorf("failed handling forks: %w", err) } @@ -626,17 +626,16 @@ func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorging bo } // handleForks -func (w *worker) handleForks() (bool, error) { +func (w *worker) handleForks(parent *types.Block) (bool, error) { // Apply Curie predeployed contract update if w.chainConfig.CurieBlock != nil && w.chainConfig.CurieBlock.Cmp(w.current.header.Number) == 0 { misc.ApplyCurieHardFork(w.current.state) return true, nil } - // Stop/start miner at Euclid fork boundary on zktrie/mpt nodes - if w.chainConfig.IsEuclid(w.current.header.Time) { - parent := w.chain.GetBlockByHash(w.current.header.ParentHash) - return parent != nil && !w.chainConfig.IsEuclid(parent.Time()), nil + // Apply Feynman hard fork + if w.chainConfig.IsFeynmanTransitionBlock(w.current.header.Time, parent.Time()) { + misc.ApplyFeynmanHardFork(w.current.state) } // Apply EIP-2935 @@ -646,6 +645,12 @@ func (w *worker) handleForks() (bool, error) { core.ProcessParentBlockHash(w.current.header.ParentHash, vmenv, w.current.state) } + // Stop/start miner at Euclid fork boundary on zktrie/mpt nodes + if w.chainConfig.IsEuclid(w.current.header.Time) { + parent := w.chain.GetBlockByHash(w.current.header.ParentHash) + return parent != nil && !w.chainConfig.IsEuclid(parent.Time()), nil + } + return false, nil } diff --git a/params/config.go b/params/config.go index eda4340e80c4..d859f6384dea 100644 --- a/params/config.go +++ b/params/config.go @@ -1002,6 +1002,11 @@ func (c *ChainConfig) IsFeynman(now uint64) bool { return isForkedTime(now, c.FeynmanTime) } +// IsFeynmanTransitionBlock returns whether the given block timestamp corresponds to the first Feynman block. +func (c *ChainConfig) IsFeynmanTransitionBlock(blockTimestamp uint64, parentTimestamp uint64) bool { + return isForkedTime(blockTimestamp, c.FeynmanTime) && !isForkedTime(parentTimestamp, c.FeynmanTime) +} + // IsTerminalPoWBlock returns whether the given block is the last block of PoW stage. func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool { if c.TerminalTotalDifficulty == nil { diff --git a/params/version.go b/params/version.go index f8f2cbeb11ba..13fa655ad50b 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 5 // Major version component of the current release VersionMinor = 8 // Minor version component of the current release - VersionPatch = 57 // Patch version component of the current release + VersionPatch = 58 // Patch version component of the current release VersionMeta = "mainnet" // Version metadata to append to the version string ) diff --git a/rollup/rcfg/config.go b/rollup/rcfg/config.go index 3bac185c8302..68626f4f8650 100644 --- a/rollup/rcfg/config.go +++ b/rollup/rcfg/config.go @@ -6,9 +6,6 @@ import ( "github.com/scroll-tech/go-ethereum/common" ) -// TODO: -// verify in consensus layer when decentralizing sequencer - var ( // L2MessageQueueAddress is the address of the L2MessageQueue // predeploy @@ -20,24 +17,58 @@ var ( // predeploy // see scroll-tech/scroll/contracts/src/L2/predeploys/L2TxFeeVault.sol ScrollFeeVaultAddress = common.HexToAddress("0x5300000000000000000000000000000000000005") +) + +// L1GasPriceOracle constants. +var ( + // forge inspect src/L2/predeploys/L1GasPriceOracle.sol:L1GasPriceOracle storageLayout + // ╭------------------+---------------------+------+--------+-------╮ + // | Name | Type | Slot | Offset | Bytes | + // +================================================================+ + // | owner | address | 0 | 0 | 20 | + // |------------------+---------------------+------+--------+-------+ + // | l1BaseFee | uint256 | 1 | 0 | 32 | + // |------------------+---------------------+------+--------+-------+ + // | overhead | uint256 | 2 | 0 | 32 | + // |------------------+---------------------+------+--------+-------+ + // | scalar | uint256 | 3 | 0 | 32 | + // |------------------+---------------------+------+--------+-------+ + // | whitelist | contract IWhitelist | 4 | 0 | 20 | + // |------------------+---------------------+------+--------+-------+ + // | l1BlobBaseFee | uint256 | 5 | 0 | 32 | + // |------------------+---------------------+------+--------+-------+ + // | commitScalar | uint256 | 6 | 0 | 32 | + // |------------------+---------------------+------+--------+-------+ + // | blobScalar | uint256 | 7 | 0 | 32 | + // |------------------+---------------------+------+--------+-------+ + // | isCurie | bool | 8 | 0 | 1 | + // |------------------+---------------------+------+--------+-------+ + // | penaltyThreshold | uint256 | 9 | 0 | 32 | + // |------------------+---------------------+------+--------+-------+ + // | penaltyFactor | uint256 | 10 | 0 | 32 | + // |------------------+---------------------+------+--------+-------+ + // | isFeynman | bool | 11 | 0 | 1 | + // ╰------------------+---------------------+------+--------+-------╯ - // L1GasPriceOracleAddress is the address of the L1GasPriceOracle - // predeploy - // see scroll-tech/scroll/contracts/src/L2/predeploys/L1GasPriceOracle.sol L1GasPriceOracleAddress = common.HexToAddress("0x5300000000000000000000000000000000000002") Precision = new(big.Int).SetUint64(1e9) - L1BaseFeeSlot = common.BigToHash(big.NewInt(1)) - OverheadSlot = common.BigToHash(big.NewInt(2)) - ScalarSlot = common.BigToHash(big.NewInt(3)) - // New fields added in the Curie hard fork - L1BlobBaseFeeSlot = common.BigToHash(big.NewInt(5)) - CommitScalarSlot = common.BigToHash(big.NewInt(6)) - BlobScalarSlot = common.BigToHash(big.NewInt(7)) - IsCurieSlot = common.BigToHash(big.NewInt(8)) + // storage layout + L1BaseFeeSlot = common.BigToHash(big.NewInt(1)) + OverheadSlot = common.BigToHash(big.NewInt(2)) + ScalarSlot = common.BigToHash(big.NewInt(3)) + L1BlobBaseFeeSlot = common.BigToHash(big.NewInt(5)) // added in Curie upgrade + CommitScalarSlot = common.BigToHash(big.NewInt(6)) // added in Curie upgrade + BlobScalarSlot = common.BigToHash(big.NewInt(7)) // added in Curie upgrade + IsCurieSlot = common.BigToHash(big.NewInt(8)) // added in Curie upgrade + PenaltyThresholdSlot = common.BigToHash(big.NewInt(9)) // added in Feynman upgrade + PenaltyFactorSlot = common.BigToHash(big.NewInt(10)) // added in Feynman upgrade + IsFeynmanSlot = common.BigToHash(big.NewInt(11)) // added in Feynman upgrade - InitialCommitScalar = big.NewInt(230759955285) - InitialBlobScalar = big.NewInt(417565260) + InitialCommitScalar = big.NewInt(230759955285) + InitialBlobScalar = big.NewInt(417565260) + InitialPenaltyThreshold = new(big.Int).Set(Precision) // init to 1 + InitialPenaltyFactor = new(big.Int).Set(Precision) // init to 1 // CurieL1GasPriceOracleBytecode is the new (blob-enabled) gas price oracle after // the Curie hard fork. Run these commands in the monorepo to verify this bytecode: @@ -48,6 +79,15 @@ var ( // FOUNDRY_EVM_VERSION="cancun" forge build // cat artifacts/src/L1GasPriceOracle.sol/L1GasPriceOracle.json | jq -r .deployedBytecode.object CurieL1GasPriceOracleBytecode = common.Hex2Bytes("608060405234801561000f575f80fd5b5060043610610132575f3560e01c8063715018a6116100b4578063a911d77f11610079578063a911d77f1461024c578063bede39b514610254578063de26c4a114610267578063e88a60ad1461027a578063f2fde38b1461028d578063f45e65d8146102a0575f80fd5b8063715018a6146101eb57806384189161146101f35780638da5cb5b146101fc57806393e59dc114610226578063944b247f14610239575f80fd5b80633d0f963e116100fa5780633d0f963e146101a057806349948e0e146101b3578063519b4bd3146101c65780636a5e67e5146101cf57806370465597146101d8575f80fd5b80630c18c1621461013657806313dad5be1461015257806323e524ac1461016f5780633577afc51461017857806339455d3a1461018d575b5f80fd5b61013f60025481565b6040519081526020015b60405180910390f35b60085461015f9060ff1681565b6040519015158152602001610149565b61013f60065481565b61018b6101863660046109b3565b6102a9565b005b61018b61019b3660046109ca565b61033b565b61018b6101ae3660046109ea565b610438565b61013f6101c1366004610a2b565b6104bb565b61013f60015481565b61013f60075481565b61018b6101e63660046109b3565b6104e0565b61018b61056e565b61013f60055481565b5f5461020e906001600160a01b031681565b6040516001600160a01b039091168152602001610149565b60045461020e906001600160a01b031681565b61018b6102473660046109b3565b6105a2565b61018b61062e565b61018b6102623660046109b3565b61068a565b61013f610275366004610a2b565b610747565b61018b6102883660046109b3565b610764565b61018b61029b3660046109ea565b6107f0565b61013f60035481565b5f546001600160a01b031633146102db5760405162461bcd60e51b81526004016102d290610ad6565b60405180910390fd5b621c9c388111156102ff57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa158015610382573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a69190610b0d565b6103c3576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b031633146104615760405162461bcd60e51b81526004016102d290610ad6565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f7910161042c565b6008545f9060ff16156104d7576104d18261087b565b92915050565b6104d1826108c1565b5f546001600160a01b031633146105095760405162461bcd60e51b81526004016102d290610ad6565b610519633b9aca006103e8610b40565b81111561053957604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a90602001610330565b5f546001600160a01b031633146105975760405162461bcd60e51b81526004016102d290610ad6565b6105a05f610904565b565b5f546001600160a01b031633146105cb5760405162461bcd60e51b81526004016102d290610ad6565b6105d9633b9aca0080610b40565b8111156105f95760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a10890602001610330565b5f546001600160a01b031633146106575760405162461bcd60e51b81526004016102d290610ad6565b60085460ff161561067b576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa1580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190610b0d565b610712576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c4490602001610330565b6008545f9060ff161561075b57505f919050565b6104d182610953565b5f546001600160a01b0316331461078d5760405162461bcd60e51b81526004016102d290610ad6565b61079b633b9aca0080610b40565b8111156107bb5760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa90602001610330565b5f546001600160a01b031633146108195760405162461bcd60e51b81526004016102d290610ad6565b6001600160a01b03811661086f5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f206164647265737300000060448201526064016102d2565b61087881610904565b50565b5f633b9aca0060055483516007546108939190610b40565b61089d9190610b40565b6001546006546108ad9190610b40565b6108b79190610b57565b6104d19190610b6a565b5f806108cc83610953565b90505f600154826108dd9190610b40565b9050633b9aca00600354826108f29190610b40565b6108fc9190610b6a565b949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b818110156109a45784818151811061097557610975610b89565b01602001516001600160f81b0319165f036109955760048301925061099c565b6010830192505b60010161095b565b50506002540160400192915050565b5f602082840312156109c3575f80fd5b5035919050565b5f80604083850312156109db575f80fd5b50508035926020909101359150565b5f602082840312156109fa575f80fd5b81356001600160a01b0381168114610a10575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610a3b575f80fd5b813567ffffffffffffffff80821115610a52575f80fd5b818401915084601f830112610a65575f80fd5b813581811115610a7757610a77610a17565b604051601f8201601f19908116603f01168101908382118183101715610a9f57610a9f610a17565b81604052828152876020848701011115610ab7575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610b1d575f80fd5b81518015158114610a10575f80fd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176104d1576104d1610b2c565b808201808211156104d1576104d1610b2c565b5f82610b8457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212200c2ac583f18be4f94ab169ae6f2ea3a708a7c0d4424746b120b177adb39e626064736f6c63430008180033") + + // FeynmanL1GasPriceOracleBytecode is the new (compression-penalty-enabled) gas price oracle after + // the Feynman hard fork. Run these commands in the scroll-contracts repo to verify this bytecode: + // + // git checkout 0f922b92675ddf0e8ec7f680de85f6d76f98c577 + // yarn + // forge build + // cat artifacts/src/L1GasPriceOracle.sol/L1GasPriceOracle.json | jq -r .deployedBytecode.object + FeynmanL1GasPriceOracleBytecode = common.Hex2Bytes("608060405234801561000f575f80fd5b50600436106101a1575f3560e01c806384189161116100f3578063c63b9e2d11610093578063e88a60ad1161006e578063e88a60ad1461032e578063f2fde38b14610341578063f45e65d814610354578063fe5b04151461035d575f80fd5b8063c63b9e2d146102ff578063c91e514914610312578063de26c4a11461031b575f80fd5b8063944b247f116100ce578063944b247f146102be578063a911d77f146102d1578063aa5e9334146102d9578063bede39b5146102ec575f80fd5b806384189161146102785780638da5cb5b1461028157806393e59dc1146102ab575f80fd5b80633d0f963e1161015e5780636112d6db116101395780636112d6db1461024b5780636a5e67e514610254578063704655971461025d578063715018a614610270575f80fd5b80633d0f963e1461021c57806349948e0e1461022f578063519b4bd314610242575f80fd5b80630c18c162146101a557806313dad5be146101c157806323e524ac146101de5780633577afc5146101e757806339455d3a146101fc5780633b7656bb1461020f575b5f80fd5b6101ae60025481565b6040519081526020015b60405180910390f35b6008546101ce9060ff1681565b60405190151581526020016101b8565b6101ae60065481565b6101fa6101f5366004610c73565b610365565b005b6101fa61020a366004610c8a565b6103f7565b600b546101ce9060ff1681565b6101fa61022a366004610caa565b6104f4565b6101ae61023d366004610ceb565b610577565b6101ae60015481565b6101ae600a5481565b6101ae60075481565b6101fa61026b366004610c73565b6105b0565b6101fa61063e565b6101ae60055481565b5f54610293906001600160a01b031681565b6040516001600160a01b0390911681526020016101b8565b600454610293906001600160a01b031681565b6101fa6102cc366004610c73565b610672565b6101fa6106fe565b6101fa6102e7366004610c73565b61075a565b6101fa6102fa366004610c73565b6107f4565b6101fa61030d366004610c73565b6108b1565b6101ae60095481565b6101ae610329366004610ceb565b61094a565b6101fa61033c366004610c73565b610974565b6101fa61034f366004610caa565b610a00565b6101ae60035481565b6101fa610a8b565b5f546001600160a01b031633146103975760405162461bcd60e51b815260040161038e90610d96565b60405180910390fd5b621c9c388111156103bb57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561043e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104629190610dcd565b61047f576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b0316331461051d5760405162461bcd60e51b815260040161038e90610d96565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f791016104e8565b600b545f9060ff16156105935761058d82610ae7565b92915050565b60085460ff16156105a75761058d82610b45565b61058d82610b81565b5f546001600160a01b031633146105d95760405162461bcd60e51b815260040161038e90610d96565b6105e9633b9aca006103e8610e00565b81111561060957604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a906020016103ec565b5f546001600160a01b031633146106675760405162461bcd60e51b815260040161038e90610d96565b6106705f610bc4565b565b5f546001600160a01b0316331461069b5760405162461bcd60e51b815260040161038e90610d96565b6106a9633b9aca0080610e00565b8111156106c95760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a108906020016103ec565b5f546001600160a01b031633146107275760405162461bcd60e51b815260040161038e90610d96565b60085460ff161561074b576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b5f546001600160a01b031633146107835760405162461bcd60e51b815260040161038e90610d96565b633b9aca008110806107a1575061079e633b9aca0080610e00565b81115b156107bf5760405163d9b5dcdf60e01b815260040160405180910390fd5b60098190556040518181527fd50d3079c77df569cd58d55d4e5614bfe7066449009425d22bde8e75242f50bb906020016103ec565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561083b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085f9190610dcd565b61087c576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c44906020016103ec565b5f546001600160a01b031633146108da5760405162461bcd60e51b815260040161038e90610d96565b633b9aca008110806108f857506108f5633b9aca0080610e00565b81115b156109155760405162ae184360e01b815260040160405180910390fd5b600a8190556040518181527f8647cebb7e57360673a28415c0bed2f68c42a86c5035f1c9b2eda2b09509288a906020016103ec565b600b545f9060ff168061095f575060085460ff165b1561096b57505f919050565b61058d82610c13565b5f546001600160a01b0316331461099d5760405162461bcd60e51b815260040161038e90610d96565b6109ab633b9aca0080610e00565b8111156109cb5760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa906020016103ec565b5f546001600160a01b03163314610a295760405162461bcd60e51b815260040161038e90610d96565b6001600160a01b038116610a7f5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f2061646472657373000000604482015260640161038e565b610a8881610bc4565b50565b5f546001600160a01b03163314610ab45760405162461bcd60e51b815260040161038e90610d96565b600b5460ff1615610ad857604051631a7c228b60e21b815260040160405180910390fd5b600b805460ff19166001179055565b5f633b9aca0080600a548451600554600754610b039190610e00565b600154600654610b139190610e00565b610b1d9190610e17565b610b279190610e00565b610b319190610e00565b610b3b9190610e2a565b61058d9190610e2a565b5f633b9aca006005548351600754610b5d9190610e00565b610b679190610e00565b600154600654610b779190610e00565b610b3b9190610e17565b5f80610b8c83610c13565b90505f60015482610b9d9190610e00565b9050633b9aca0060035482610bb29190610e00565b610bbc9190610e2a565b949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b81811015610c6457848181518110610c3557610c35610e49565b01602001516001600160f81b0319165f03610c5557600483019250610c5c565b6010830192505b600101610c1b565b50506002540160400192915050565b5f60208284031215610c83575f80fd5b5035919050565b5f8060408385031215610c9b575f80fd5b50508035926020909101359150565b5f60208284031215610cba575f80fd5b81356001600160a01b0381168114610cd0575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610cfb575f80fd5b813567ffffffffffffffff80821115610d12575f80fd5b818401915084601f830112610d25575f80fd5b813581811115610d3757610d37610cd7565b604051601f8201601f19908116603f01168101908382118183101715610d5f57610d5f610cd7565b81604052828152876020848701011115610d77575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610ddd575f80fd5b81518015158114610cd0575f80fd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761058d5761058d610dec565b8082018082111561058d5761058d610dec565b5f82610e4457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea164736f6c6343000818000a") ) // L2SystemConfig constants.