diff --git a/common/constants.go b/common/constants.go index 71b1093cf05ec..7020e8fd682bf 100644 --- a/common/constants.go +++ b/common/constants.go @@ -45,6 +45,8 @@ var TIPXDCX = big.NewInt(38383838) var TIPXDCXLending = big.NewInt(38383838) var TIPXDCXCancellationFee = big.NewInt(38383838) var TIPXDCXCancellationFeeTestnet = big.NewInt(38383838) +var BerlinBlock = big.NewInt(9999999999) +var LondonBlock = big.NewInt(9999999999) var TIPXDCXTestnet = big.NewInt(38383838) var IsTestnet bool = false diff --git a/common/constants/constants.go.devnet b/common/constants/constants.go.devnet index c121d305239f7..58351e020bf0e 100644 --- a/common/constants/constants.go.devnet +++ b/common/constants/constants.go.devnet @@ -45,6 +45,8 @@ var TIPXDCX = big.NewInt(225000) var TIPXDCXLending = big.NewInt(225000) var TIPXDCXCancellationFee = big.NewInt(225000) var TIPXDCXCancellationFeeTestnet = big.NewInt(225000) +var BerlinBlock = big.NewInt(9999999999) +var LondonBlock = big.NewInt(9999999999) var TIPXDCXTestnet = big.NewInt(0) var IsTestnet bool = false diff --git a/common/constants/constants.go.testnet b/common/constants/constants.go.testnet index 0c1db046cfb8a..eae07aa116472 100644 --- a/common/constants/constants.go.testnet +++ b/common/constants/constants.go.testnet @@ -45,6 +45,8 @@ var TIPXDCX = big.NewInt(23779191) var TIPXDCXLending = big.NewInt(23779191) var TIPXDCXCancellationFee = big.NewInt(23779191) var TIPXDCXCancellationFeeTestnet = big.NewInt(23779191) +var BerlinBlock = big.NewInt(9999999999) +var LondonBlock = big.NewInt(9999999999) var TIPXDCXTestnet = big.NewInt(23779191) var IsTestnet bool = false diff --git a/core/vm/eips.go b/core/vm/eips.go index 6ba7bbd6ec7a3..77dc30a9100d9 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -19,6 +19,7 @@ package vm import ( "fmt" + "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/params" "github.com/holiman/uint256" ) @@ -28,6 +29,8 @@ import ( // defined jump tables are not polluted. func EnableEIP(eipNum int, jt *JumpTable) error { switch eipNum { + case 3898: + enable3198(jt) case 2200: enable2200(jt) case 1884: @@ -90,3 +93,22 @@ func enable2200(jt *JumpTable) { jt[SLOAD].constantGas = params.SloadGasEIP2200 jt[SSTORE].dynamicGas = gasSStoreEIP2200 } + +// enable3198 applies EIP-3198 (BASEFEE Opcode) +// - Adds an opcode that returns the current block's base fee. +func enable3198(jt *JumpTable) { + // New opcode + jt[BASEFEE] = &operation{ + execute: opBaseFee, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + } +} + +// opBaseFee implements BASEFEE opcode +func opBaseFee(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { + baseFee, _ := uint256.FromBig(common.MinGasPrice50x) + callContext.stack.push(baseFee) + return nil, nil +} diff --git a/core/vm/evm.go b/core/vm/evm.go index 284ea6768c962..576fbdd09436a 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -46,12 +46,14 @@ type ( // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) { if contract.CodeAddr != nil { - precompiles := PrecompiledContractsHomestead - if evm.chainRules.IsByzantium { - precompiles = PrecompiledContractsByzantium - } - if evm.chainRules.IsIstanbul { + var precompiles map[common.Address]PrecompiledContract + switch { + case evm.chainRules.IsIstanbul: precompiles = PrecompiledContractsIstanbul + case evm.chainRules.IsByzantium: + precompiles = PrecompiledContractsByzantium + default: + precompiles = PrecompiledContractsHomestead } if p := precompiles[*contract.CodeAddr]; p != nil { switch p.(type) { diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 59fbf21f7c5ad..92bed8e70865d 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -93,6 +93,10 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { // If jump table was not initialised we set the default one. if cfg.JumpTable == nil { switch { + case evm.chainRules.IsLondon: + cfg.JumpTable = &londonInstructionSet + case evm.chainRules.IsBerlin: + cfg.JumpTable = &berlinInstructionSet case evm.chainRules.IsIstanbul: cfg.JumpTable = &istanbulInstructionSet case evm.chainRules.IsConstantinople: diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 55ad78adc53fa..68b13fbe2f05e 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -50,11 +50,30 @@ var ( byzantiumInstructionSet = newByzantiumInstructionSet() constantinopleInstructionSet = newConstantinopleInstructionSet() istanbulInstructionSet = newIstanbulInstructionSet() + berlinInstructionSet = newBerlinInstructionSet() + londonInstructionSet = newLondonInstructionSet() ) // JumpTable contains the EVM opcodes supported at a given fork. type JumpTable [256]*operation +// newLondonInstructionSet returns the frontier, homestead, byzantium, +// constantinople, istanbul, petersburg, berlin and london instructions. +func newLondonInstructionSet() JumpTable { + instructionSet := newBerlinInstructionSet() + // enable3529(&instructionSet) // EIP-3529: Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529 + enable3198(&instructionSet) // Base fee opcode https://eips.ethereum.org/EIPS/eip-3198 + return instructionSet +} + +// newBerlinInstructionSet returns the frontier, homestead, byzantium, +// constantinople, istanbul, petersburg and berlin instructions. +func newBerlinInstructionSet() JumpTable { + instructionSet := newIstanbulInstructionSet() + // enable2929(&instructionSet) // Gas cost increases for state access opcodes https://eips.ethereum.org/EIPS/eip-2929 + return instructionSet +} + // newIstanbulInstructionSet returns the frontier, homestead // byzantium, contantinople and petersburg instructions. func newIstanbulInstructionSet() JumpTable { diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index b9001138b05a0..69b0436db45fa 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -101,6 +101,7 @@ const ( GASLIMIT OpCode = 0x45 CHAINID OpCode = 0x46 SELFBALANCE OpCode = 0x47 + BASEFEE OpCode = 0x48 ) // 0x50 range - 'storage' and execution. @@ -280,6 +281,7 @@ var opCodeToString = [256]string{ GASLIMIT: "GASLIMIT", CHAINID: "CHAINID", SELFBALANCE: "SELFBALANCE", + BASEFEE: "BASEFEE", // 0x50 range - 'storage' and execution. POP: "POP", @@ -445,6 +447,7 @@ var stringToOp = map[string]OpCode{ "DIFFICULTY": DIFFICULTY, "GASLIMIT": GASLIMIT, "SELFBALANCE": SELFBALANCE, + "BASEFEE": BASEFEE, "POP": POP, "MLOAD": MLOAD, "MSTORE": MSTORE, diff --git a/params/config.go b/params/config.go index a850bd54d063c..a75f7a40538a6 100644 --- a/params/config.go +++ b/params/config.go @@ -362,6 +362,8 @@ type ChainConfig struct { ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium) ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated) + BerlinBlock *big.Int `json:"berlinBlock,omitempty"` // Berlin switch block (nil = no fork, 0 = already on berlin) + LondonBlock *big.Int `json:"londonBlock,omitempty"` // London switch block (nil = no fork, 0 = already on london) // Various consensus engines Ethash *EthashConfig `json:"ethash,omitempty"` @@ -498,7 +500,7 @@ func (c *ChainConfig) String() string { default: engine = "unknown" } - return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Engine: %v}", + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v BerlinBlock: %v LondonBlock: %v Engine: %v}", c.ChainId, c.HomesteadBlock, c.DAOForkBlock, @@ -508,6 +510,8 @@ func (c *ChainConfig) String() string { c.EIP158Block, c.ByzantiumBlock, c.ConstantinopleBlock, + c.BerlinBlock, + c.LondonBlock, engine, ) } @@ -554,6 +558,16 @@ func (c *ChainConfig) IsIstanbul(num *big.Int) bool { return isForked(common.TIPXDCXCancellationFee, num) } +// IsBerlin returns whether num is either equal to the Berlin fork block or greater. +func (c *ChainConfig) IsBerlin(num *big.Int) bool { + return isForked(common.BerlinBlock, num) +} + +// IsLondon returns whether num is either equal to the London fork block or greater. +func (c *ChainConfig) IsLondon(num *big.Int) bool { + return isForked(common.LondonBlock, num) +} + func (c *ChainConfig) IsTIP2019(num *big.Int) bool { return isForked(common.TIP2019Block, num) } @@ -655,6 +669,13 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi if isForkIncompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, head) { return newCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock) } + if isForkIncompatible(c.BerlinBlock, newcfg.BerlinBlock, head) { + return newCompatError("Berlin fork block", c.BerlinBlock, newcfg.BerlinBlock) + } + if isForkIncompatible(c.LondonBlock, newcfg.LondonBlock, head) { + return newCompatError("London fork block", c.LondonBlock, newcfg.LondonBlock) + } + return nil } @@ -722,6 +743,7 @@ type Rules struct { ChainId *big.Int IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool + IsBerlin, IsLondon bool } func (c *ChainConfig) Rules(num *big.Int) Rules { @@ -739,5 +761,7 @@ func (c *ChainConfig) Rules(num *big.Int) Rules { IsConstantinople: c.IsConstantinople(num), IsPetersburg: c.IsPetersburg(num), IsIstanbul: c.IsIstanbul(num), + IsBerlin: c.IsBerlin(num), + IsLondon: c.IsLondon(num), } }