@ -120,7 +120,7 @@ func (result *ExecutionResult) Revert() []byte {
}
}
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
func IntrinsicGas ( data [ ] byte , accessList types . AccessList , isContractCreation bool , isHomestead , isEIP2028 bool ) ( uint64 , error ) {
func IntrinsicGas ( data [ ] byte , accessList types . AccessList , isContractCreation bool , isHomestead , isEIP2028 bool , isEIP3860 bool ) ( uint64 , error ) {
// Set the starting gas for the raw transaction
// Set the starting gas for the raw transaction
var gas uint64
var gas uint64
if isContractCreation && isHomestead {
if isContractCreation && isHomestead {
@ -128,8 +128,9 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation b
} else {
} else {
gas = params . TxGas
gas = params . TxGas
}
}
dataLen := uint64 ( len ( data ) )
// Bump the required gas by the amount of transactional data
// Bump the required gas by the amount of transactional data
if len ( data ) > 0 {
if dataLen > 0 {
// Zero and non-zero bytes are priced differently
// Zero and non-zero bytes are priced differently
var nz uint64
var nz uint64
for _ , byt := range data {
for _ , byt := range data {
@ -147,11 +148,19 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation b
}
}
gas += nz * nonZeroGas
gas += nz * nonZeroGas
z := uint64 ( len ( data ) ) - nz
z := dataLen - nz
if ( math . MaxUint64 - gas ) / params . TxDataZeroGas < z {
if ( math . MaxUint64 - gas ) / params . TxDataZeroGas < z {
return 0 , ErrGasUintOverflow
return 0 , ErrGasUintOverflow
}
}
gas += z * params . TxDataZeroGas
gas += z * params . TxDataZeroGas
if isContractCreation && isEIP3860 {
lenWords := toWordSize ( dataLen )
if ( math . MaxUint64 - gas ) / params . InitCodeWordGas < lenWords {
return 0 , ErrGasUintOverflow
}
gas += lenWords * params . InitCodeWordGas
}
}
}
if accessList != nil {
if accessList != nil {
gas += uint64 ( len ( accessList ) ) * params . TxAccessListAddressGas
gas += uint64 ( len ( accessList ) ) * params . TxAccessListAddressGas
@ -160,6 +169,15 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation b
return gas , nil
return gas , nil
}
}
// toWordSize returns the ceiled word size required for init code payment calculation.
func toWordSize ( size uint64 ) uint64 {
if size > math . MaxUint64 - 31 {
return math . MaxUint64 / 32 + 1
}
return ( size + 31 ) / 32
}
// NewStateTransition initialises and returns a new state transition object.
// NewStateTransition initialises and returns a new state transition object.
func NewStateTransition ( evm * vm . EVM , msg Message , gp * GasPool ) * StateTransition {
func NewStateTransition ( evm * vm . EVM , msg Message , gp * GasPool ) * StateTransition {
return & StateTransition {
return & StateTransition {
@ -305,7 +323,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
)
)
// Check clauses 4-5, subtract intrinsic gas if everything is correct
// Check clauses 4-5, subtract intrinsic gas if everything is correct
gas , err := IntrinsicGas ( st . data , st . msg . AccessList ( ) , contractCreation , rules . IsHomestead , rules . IsIstanbul )
gas , err := IntrinsicGas ( st . data , st . msg . AccessList ( ) , contractCreation , rules . IsHomestead , rules . IsIstanbul , rules . IsShanghai )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
@ -319,6 +337,11 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
return nil , fmt . Errorf ( "%w: address %v" , ErrInsufficientFundsForTransfer , msg . From ( ) . Hex ( ) )
return nil , fmt . Errorf ( "%w: address %v" , ErrInsufficientFundsForTransfer , msg . From ( ) . Hex ( ) )
}
}
// Check whether the init code size has been exceeded.
if rules . IsShanghai && contractCreation && len ( st . data ) > params . MaxInitCodeSize {
return nil , fmt . Errorf ( "%w: code size %v limit %v" , ErrMaxInitCodeSizeExceeded , len ( st . data ) , params . MaxInitCodeSize )
}
// Execute the preparatory steps for state transition which includes:
// Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin)
// - prepare accessList(post-berlin)
// - reset transient storage(eip 1153)
// - reset transient storage(eip 1153)