github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/evm/emulator/config.go (about)

     1  package emulator
     2  
     3  import (
     4  	"math"
     5  	"math/big"
     6  
     7  	gethCommon "github.com/onflow/go-ethereum/common"
     8  	gethCore "github.com/onflow/go-ethereum/core"
     9  	gethVM "github.com/onflow/go-ethereum/core/vm"
    10  	gethParams "github.com/onflow/go-ethereum/params"
    11  
    12  	"github.com/onflow/flow-go/fvm/evm/types"
    13  )
    14  
    15  var (
    16  	DefaultBlockLevelGasLimit = uint64(math.MaxUint64)
    17  	DefaultBaseFee            = big.NewInt(0)
    18  	zero                      = uint64(0)
    19  	bigZero                   = big.NewInt(0)
    20  )
    21  
    22  // Config sets the required parameters
    23  type Config struct {
    24  	// Chain Config
    25  	ChainConfig *gethParams.ChainConfig
    26  	// EVM config
    27  	EVMConfig gethVM.Config
    28  	// block context
    29  	BlockContext *gethVM.BlockContext
    30  	// transaction context
    31  	TxContext *gethVM.TxContext
    32  	// base unit of gas for direct calls
    33  	DirectCallBaseGasUsage uint64
    34  }
    35  
    36  func (c *Config) ChainRules() gethParams.Rules {
    37  	return c.ChainConfig.Rules(
    38  		c.BlockContext.BlockNumber,
    39  		c.BlockContext.Random != nil,
    40  		c.BlockContext.Time)
    41  }
    42  
    43  // DefaultChainConfig is the default chain config which
    44  // considers majority of EVM upgrades (e.g. Shanghai update) already been applied
    45  // this has done through setting the height of these changes
    46  // to zero nad setting the time for some other changes to zero
    47  // For the future changes of EVM, we need to update the EVM go mod version
    48  // and set a proper height for the specific release based on the Flow EVM heights
    49  // so it could gets activated at a desired time.
    50  var DefaultChainConfig = &gethParams.ChainConfig{
    51  	ChainID: types.FlowEVMPreviewNetChainID,
    52  
    53  	// Fork scheduling based on block heights
    54  	HomesteadBlock:      bigZero,
    55  	DAOForkBlock:        bigZero,
    56  	DAOForkSupport:      false,
    57  	EIP150Block:         bigZero,
    58  	EIP155Block:         bigZero,
    59  	EIP158Block:         bigZero,
    60  	ByzantiumBlock:      bigZero, // already on Byzantium
    61  	ConstantinopleBlock: bigZero, // already on Constantinople
    62  	PetersburgBlock:     bigZero, // already on Petersburg
    63  	IstanbulBlock:       bigZero, // already on Istanbul
    64  	BerlinBlock:         bigZero, // already on Berlin
    65  	LondonBlock:         bigZero, // already on London
    66  	MuirGlacierBlock:    bigZero, // already on MuirGlacier
    67  
    68  	// Fork scheduling based on timestamps
    69  	ShanghaiTime: &zero, // already on Shanghai
    70  	CancunTime:   &zero, // already on Cancun
    71  	PragueTime:   &zero, // already on Prague
    72  }
    73  
    74  // Default config supports the dynamic fee structure (EIP-1559)
    75  // so it accepts both legacy transactions with a fixed gas price
    76  // and dynamic transactions with tip and cap.
    77  // Yet default config keeps the base fee to zero (no automatic adjustment)
    78  func defaultConfig() *Config {
    79  	return &Config{
    80  		ChainConfig: DefaultChainConfig,
    81  		EVMConfig: gethVM.Config{
    82  			// setting this flag let us we force the base fee to zero (coinbase will collect)
    83  			NoBaseFee: true,
    84  		},
    85  		TxContext: &gethVM.TxContext{
    86  			GasPrice:   new(big.Int),
    87  			BlobFeeCap: new(big.Int),
    88  		},
    89  		BlockContext: &gethVM.BlockContext{
    90  			CanTransfer: gethCore.CanTransfer,
    91  			Transfer:    gethCore.Transfer,
    92  			GasLimit:    DefaultBlockLevelGasLimit,
    93  			BaseFee:     DefaultBaseFee,
    94  			GetHash: func(n uint64) gethCommon.Hash {
    95  				return gethCommon.Hash{}
    96  			},
    97  			GetPrecompile: gethCore.GetPrecompile,
    98  		},
    99  	}
   100  }
   101  
   102  // NewConfig initializes a new config
   103  func NewConfig(opts ...Option) *Config {
   104  	ctx := defaultConfig()
   105  	for _, applyOption := range opts {
   106  		ctx = applyOption(ctx)
   107  	}
   108  	return ctx
   109  }
   110  
   111  type Option func(*Config) *Config
   112  
   113  // WithChainID sets the evm chain ID
   114  func WithChainID(chainID *big.Int) Option {
   115  	return func(c *Config) *Config {
   116  		c.ChainConfig.ChainID = chainID
   117  		return c
   118  	}
   119  }
   120  
   121  // WithOrigin sets the origin of the transaction (signer)
   122  func WithOrigin(origin gethCommon.Address) Option {
   123  	return func(c *Config) *Config {
   124  		c.TxContext.Origin = origin
   125  		return c
   126  	}
   127  }
   128  
   129  // WithGasPrice sets the gas price for the transaction (usually the one sets by the sender)
   130  func WithGasPrice(gasPrice *big.Int) Option {
   131  	return func(c *Config) *Config {
   132  		c.TxContext.GasPrice = gasPrice
   133  		return c
   134  	}
   135  }
   136  
   137  // WithGasLimit sets the gas limit of the transaction
   138  func WithGasLimit(gasLimit uint64) Option {
   139  	return func(c *Config) *Config {
   140  		c.BlockContext.GasLimit = gasLimit
   141  		return c
   142  	}
   143  }
   144  
   145  // WithCoinbase sets the coinbase of the block where the fees are collected in
   146  func WithCoinbase(coinbase gethCommon.Address) Option {
   147  	return func(c *Config) *Config {
   148  		c.BlockContext.Coinbase = coinbase
   149  		return c
   150  	}
   151  }
   152  
   153  // WithBlockNumber sets the block height in the block context
   154  func WithBlockNumber(blockNumber *big.Int) Option {
   155  	return func(c *Config) *Config {
   156  		c.BlockContext.BlockNumber = blockNumber
   157  		return c
   158  	}
   159  }
   160  
   161  // WithBlockTime sets the block time in the block context
   162  func WithBlockTime(time uint64) Option {
   163  	return func(c *Config) *Config {
   164  		c.BlockContext.Time = time
   165  		return c
   166  	}
   167  }
   168  
   169  // WithGetBlockHashFunction sets the functionality to look up block hash by height
   170  func WithGetBlockHashFunction(getHash gethVM.GetHashFunc) Option {
   171  	return func(c *Config) *Config {
   172  		c.BlockContext.GetHash = getHash
   173  		return c
   174  	}
   175  }
   176  
   177  // WithDirectCallBaseGasUsage sets the base direct call gas usage
   178  func WithDirectCallBaseGasUsage(gas uint64) Option {
   179  	return func(c *Config) *Config {
   180  		c.DirectCallBaseGasUsage = gas
   181  		return c
   182  	}
   183  }
   184  
   185  // WithExtraPrecompiles appends precompile list with extra precompiles
   186  func WithExtraPrecompiles(precompiles []types.Precompile) Option {
   187  	return func(c *Config) *Config {
   188  		extraPreCompMap := make(map[gethCommon.Address]gethVM.PrecompiledContract)
   189  		for _, pc := range precompiles {
   190  			extraPreCompMap[pc.Address().ToCommon()] = pc
   191  		}
   192  		c.BlockContext.GetPrecompile = func(rules gethParams.Rules, addr gethCommon.Address) (gethVM.PrecompiledContract, bool) {
   193  			prec, found := extraPreCompMap[addr]
   194  			if found {
   195  				return prec, true
   196  			}
   197  			return gethCore.GetPrecompile(rules, addr)
   198  		}
   199  		return c
   200  	}
   201  }
   202  
   203  // WithRandom sets the block context random field
   204  func WithRandom(rand *gethCommon.Hash) Option {
   205  	return func(c *Config) *Config {
   206  		c.BlockContext.Random = rand
   207  		return c
   208  	}
   209  }