2017-04-14 11:29:00 +03:00
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
2017-01-05 13:52:10 +03:00
package vm
import (
"github.com/ethereum/go-ethereum/common"
2017-01-04 22:17:24 +03:00
"github.com/ethereum/go-ethereum/common/math"
2017-01-05 13:52:10 +03:00
"github.com/ethereum/go-ethereum/params"
)
2019-01-24 14:14:02 +03:00
// memoryGasCost calculates the quadratic gas for memory expansion. It does so
2017-01-04 22:17:24 +03:00
// only for the memory region that is expanded, not the total memory.
func memoryGasCost ( mem * Memory , newMemSize uint64 ) ( uint64 , error ) {
if newMemSize == 0 {
return 0 , nil
2017-02-02 17:25:42 +03:00
}
2017-06-28 10:51:31 +03:00
// The maximum that will fit in a uint64 is max_word_count - 1
// anything above that will result in an overflow.
// Additionally, a newMemSize which results in a
2019-03-29 00:04:31 +03:00
// newMemSizeWords larger than 0xFFFFFFFF will cause the square operation
2017-06-28 10:51:31 +03:00
// to overflow.
2019-03-29 00:04:31 +03:00
// The constant 0x1FFFFFFFE0 is the highest number that can be used without
2017-06-28 10:51:31 +03:00
// overflowing the gas calculation
2019-03-29 00:04:31 +03:00
if newMemSize > 0x1FFFFFFFE0 {
2017-06-28 10:51:31 +03:00
return 0 , errGasUintOverflow
}
2017-01-04 22:17:24 +03:00
newMemSizeWords := toWordSize ( newMemSize )
newMemSize = newMemSizeWords * 32
if newMemSize > uint64 ( mem . Len ( ) ) {
square := newMemSizeWords * newMemSizeWords
linCoef := newMemSizeWords * params . MemoryGas
quadCoef := square / params . QuadCoeffDiv
newTotalFee := linCoef + quadCoef
fee := newTotalFee - mem . lastGasCost
mem . lastGasCost = newTotalFee
return fee , nil
}
return 0 , nil
2017-01-05 13:52:10 +03:00
}
2017-08-16 13:36:48 +03:00
func gasCallDataCopy ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
2017-08-16 13:07:33 +03:00
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
var overflow bool
if gas , overflow = math . SafeAdd ( gas , GasFastestStep ) ; overflow {
return 0 , errGasUintOverflow
}
words , overflow := bigUint64 ( stack . Back ( 2 ) )
if overflow {
return 0 , errGasUintOverflow
}
if words , overflow = math . SafeMul ( toWordSize ( words ) , params . CopyGas ) ; overflow {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , words ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
}
func gasReturnDataCopy ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
2017-01-04 22:17:24 +03:00
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
var overflow bool
if gas , overflow = math . SafeAdd ( gas , GasFastestStep ) ; overflow {
return 0 , errGasUintOverflow
}
2017-01-05 13:52:10 +03:00
2017-01-04 22:17:24 +03:00
words , overflow := bigUint64 ( stack . Back ( 2 ) )
if overflow {
return 0 , errGasUintOverflow
}
if words , overflow = math . SafeMul ( toWordSize ( words ) , params . CopyGas ) ; overflow {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , words ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2018-08-12 15:47:03 +03:00
func gasSStore ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
2018-08-12 00:03:54 +03:00
var (
2018-08-12 15:47:03 +03:00
y , x = stack . Back ( 1 ) , stack . Back ( 0 )
current = evm . StateDB . GetState ( contract . Address ( ) , common . BigToHash ( x ) )
2018-08-12 00:03:54 +03:00
)
2018-09-18 16:24:35 +03:00
// The legacy gas metering only takes into consideration the current state
2019-01-24 13:36:30 +03:00
// Legacy rules should be applied if we are in Petersburg (removal of EIP-1283)
// OR Constantinople is not active
if evm . chainRules . IsPetersburg || ! evm . chainRules . IsConstantinople {
2018-09-18 16:24:35 +03:00
// This checks for 3 scenario's and calculates gas accordingly:
//
// 1. From a zero-value address to a non-zero value (NEW VALUE)
// 2. From a non-zero value address to a zero-value address (DELETE)
// 3. From a non-zero to a non-zero (CHANGE)
switch {
case current == ( common . Hash { } ) && y . Sign ( ) != 0 : // 0 => non 0
return params . SstoreSetGas , nil
case current != ( common . Hash { } ) && y . Sign ( ) == 0 : // non 0 => 0
evm . StateDB . AddRefund ( params . SstoreRefundGas )
return params . SstoreClearGas , nil
default : // non 0 => non 0 (or 0 => 0)
return params . SstoreResetGas , nil
}
}
// The new gas metering is based on net gas costs (EIP-1283):
//
// 1. If current value equals new value (this is a no-op), 200 gas is deducted.
// 2. If current value does not equal new value
// 2.1. If original value equals current value (this storage slot has not been changed by the current execution context)
// 2.1.1. If original value is 0, 20000 gas is deducted.
// 2.1.2. Otherwise, 5000 gas is deducted. If new value is 0, add 15000 gas to refund counter.
// 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses.
// 2.2.1. If original value is not 0
// 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0.
// 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter.
// 2.2.2. If original value equals new value (this storage slot is reset)
// 2.2.2.1. If original value is 0, add 19800 gas to refund counter.
// 2.2.2.2. Otherwise, add 4800 gas to refund counter.
value := common . BigToHash ( y )
if current == value { // noop (1)
return params . NetSstoreNoopGas , nil
}
original := evm . StateDB . GetCommittedState ( contract . Address ( ) , common . BigToHash ( x ) )
if original == current {
if original == ( common . Hash { } ) { // create slot (2.1.1)
return params . NetSstoreInitGas , nil
2018-08-12 00:03:54 +03:00
}
2018-09-18 16:24:35 +03:00
if value == ( common . Hash { } ) { // delete slot (2.1.2b)
evm . StateDB . AddRefund ( params . NetSstoreClearRefund )
2018-08-12 00:03:54 +03:00
}
2018-09-18 16:24:35 +03:00
return params . NetSstoreCleanGas , nil // write existing slot (2.1.2)
}
if original != ( common . Hash { } ) {
if current == ( common . Hash { } ) { // recreate slot (2.2.1.1)
evm . StateDB . SubRefund ( params . NetSstoreClearRefund )
} else if value == ( common . Hash { } ) { // delete slot (2.2.1.2)
evm . StateDB . AddRefund ( params . NetSstoreClearRefund )
2018-08-12 00:03:54 +03:00
}
}
2018-09-18 16:24:35 +03:00
if original == value {
if original == ( common . Hash { } ) { // reset to original inexistent slot (2.2.2.1)
evm . StateDB . AddRefund ( params . NetSstoreResetClearRefund )
} else { // reset to original existing slot (2.2.2.2)
evm . StateDB . AddRefund ( params . NetSstoreResetRefund )
2018-08-12 00:03:54 +03:00
}
}
2018-09-18 16:24:35 +03:00
return params . NetSstoreDirtyGas , nil
2018-08-12 00:03:54 +03:00
}
2017-01-04 22:17:24 +03:00
func makeGasLog ( n uint64 ) gasFunc {
return func ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
requestedSize , overflow := bigUint64 ( stack . Back ( 1 ) )
if overflow {
return 0 , errGasUintOverflow
}
2017-01-05 13:52:10 +03:00
2017-01-04 22:17:24 +03:00
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
if gas , overflow = math . SafeAdd ( gas , params . LogGas ) ; overflow {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , n * params . LogTopicGas ) ; overflow {
return 0 , errGasUintOverflow
}
var memorySizeGas uint64
if memorySizeGas , overflow = math . SafeMul ( requestedSize , params . LogDataGas ) ; overflow {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , memorySizeGas ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
}
2017-01-04 22:17:24 +03:00
func gasSha3 ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
var overflow bool
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
2017-01-05 13:52:10 +03:00
2017-01-04 22:17:24 +03:00
if gas , overflow = math . SafeAdd ( gas , params . Sha3Gas ) ; overflow {
return 0 , errGasUintOverflow
}
2017-01-05 13:52:10 +03:00
2017-01-04 22:17:24 +03:00
wordGas , overflow := bigUint64 ( stack . Back ( 1 ) )
if overflow {
return 0 , errGasUintOverflow
}
if wordGas , overflow = math . SafeMul ( toWordSize ( wordGas ) , params . Sha3WordGas ) ; overflow {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , wordGas ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasCodeCopy ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
var overflow bool
if gas , overflow = math . SafeAdd ( gas , GasFastestStep ) ; overflow {
return 0 , errGasUintOverflow
}
2017-02-02 17:25:42 +03:00
2017-01-04 22:17:24 +03:00
wordGas , overflow := bigUint64 ( stack . Back ( 2 ) )
if overflow {
return 0 , errGasUintOverflow
}
if wordGas , overflow = math . SafeMul ( toWordSize ( wordGas ) , params . CopyGas ) ; overflow {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , wordGas ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasExtCodeCopy ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
var overflow bool
if gas , overflow = math . SafeAdd ( gas , gt . ExtcodeCopy ) ; overflow {
return 0 , errGasUintOverflow
}
wordGas , overflow := bigUint64 ( stack . Back ( 3 ) )
if overflow {
return 0 , errGasUintOverflow
}
if wordGas , overflow = math . SafeMul ( toWordSize ( wordGas ) , params . CopyGas ) ; overflow {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , wordGas ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2018-07-24 18:06:40 +03:00
func gasExtCodeHash ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
return gt . ExtcodeHash , nil
}
2017-01-04 22:17:24 +03:00
func gasMLoad ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
var overflow bool
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , GasFastestStep ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasMStore8 ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
var overflow bool
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , GasFastestStep ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasMStore ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
var overflow bool
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , GasFastestStep ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasCreate ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
var overflow bool
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
if gas , overflow = math . SafeAdd ( gas , params . CreateGas ) ; overflow {
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2018-07-24 17:22:03 +03:00
func gasCreate2 ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
var overflow bool
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
if gas , overflow = math . SafeAdd ( gas , params . Create2Gas ) ; overflow {
return 0 , errGasUintOverflow
}
2018-10-05 10:32:35 +03:00
wordGas , overflow := bigUint64 ( stack . Back ( 2 ) )
if overflow {
return 0 , errGasUintOverflow
}
if wordGas , overflow = math . SafeMul ( toWordSize ( wordGas ) , params . Sha3WordGas ) ; overflow {
return 0 , errGasUintOverflow
}
if gas , overflow = math . SafeAdd ( gas , wordGas ) ; overflow {
return 0 , errGasUintOverflow
}
2018-07-24 17:22:03 +03:00
return gas , nil
}
2017-01-04 22:17:24 +03:00
func gasBalance ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
return gt . Balance , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasExtCodeSize ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
return gt . ExtcodeSize , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasSLoad ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
return gt . SLoad , nil
2017-02-02 17:25:42 +03:00
}
2017-01-04 22:17:24 +03:00
func gasExp ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
expByteLen := uint64 ( ( stack . data [ stack . len ( ) - 2 ] . BitLen ( ) + 7 ) / 8 )
2017-02-08 15:39:26 +03:00
2017-02-02 17:25:42 +03:00
var (
2017-01-04 22:17:24 +03:00
gas = expByteLen * gt . ExpByte // no overflow check required. Max is 256 * ExpByte gas
overflow bool
)
2019-01-24 14:14:02 +03:00
if gas , overflow = math . SafeAdd ( gas , params . ExpGas ) ; overflow {
2017-01-04 22:17:24 +03:00
return 0 , errGasUintOverflow
}
return gas , nil
}
func gasCall ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
var (
gas = gt . Calls
2017-02-28 17:09:11 +03:00
transfersValue = stack . Back ( 2 ) . Sign ( ) != 0
2017-01-04 22:17:24 +03:00
address = common . BigToAddress ( stack . Back ( 1 ) )
eip158 = evm . ChainConfig ( ) . IsEIP158 ( evm . BlockNumber )
2017-01-05 13:52:10 +03:00
)
if eip158 {
2017-09-14 10:07:31 +03:00
if transfersValue && evm . StateDB . Empty ( address ) {
2017-01-04 22:17:24 +03:00
gas += params . CallNewAccountGas
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
} else if ! evm . StateDB . Exist ( address ) {
gas += params . CallNewAccountGas
2017-01-05 13:52:10 +03:00
}
if transfersValue {
2017-01-04 22:17:24 +03:00
gas += params . CallValueTransferGas
}
memoryGas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
var overflow bool
if gas , overflow = math . SafeAdd ( gas , memoryGas ) ; overflow {
return 0 , errGasUintOverflow
2017-01-05 13:52:10 +03:00
}
2017-11-28 22:05:49 +03:00
evm . callGasTemp , err = callGas ( gt , contract . Gas , gas , stack . Back ( 0 ) )
2017-01-04 22:17:24 +03:00
if err != nil {
return 0 , err
}
2017-11-28 22:05:49 +03:00
if gas , overflow = math . SafeAdd ( gas , evm . callGasTemp ) ; overflow {
2017-01-04 22:17:24 +03:00
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasCallCode ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
gas := gt . Calls
2017-02-28 17:09:11 +03:00
if stack . Back ( 2 ) . Sign ( ) != 0 {
2017-01-04 22:17:24 +03:00
gas += params . CallValueTransferGas
}
memoryGas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
var overflow bool
if gas , overflow = math . SafeAdd ( gas , memoryGas ) ; overflow {
return 0 , errGasUintOverflow
2017-01-05 13:52:10 +03:00
}
2017-11-28 22:05:49 +03:00
evm . callGasTemp , err = callGas ( gt , contract . Gas , gas , stack . Back ( 0 ) )
2017-01-04 22:17:24 +03:00
if err != nil {
return 0 , err
}
2017-11-28 22:05:49 +03:00
if gas , overflow = math . SafeAdd ( gas , evm . callGasTemp ) ; overflow {
2017-01-04 22:17:24 +03:00
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasReturn ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
2017-08-16 17:09:29 +03:00
return memoryGasCost ( mem , memorySize )
}
func gasRevert ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
2017-01-05 13:52:10 +03:00
return memoryGasCost ( mem , memorySize )
}
2017-01-04 22:17:24 +03:00
func gasSuicide ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
var gas uint64
2017-01-05 13:52:10 +03:00
// EIP150 homestead gas reprice fork:
2017-01-04 22:17:24 +03:00
if evm . ChainConfig ( ) . IsEIP150 ( evm . BlockNumber ) {
gas = gt . Suicide
2017-01-05 13:52:10 +03:00
var (
address = common . BigToAddress ( stack . Back ( 0 ) )
2017-01-04 22:17:24 +03:00
eip158 = evm . ChainConfig ( ) . IsEIP158 ( evm . BlockNumber )
2017-01-05 13:52:10 +03:00
)
if eip158 {
// if empty and transfers value
2017-02-28 17:09:11 +03:00
if evm . StateDB . Empty ( address ) && evm . StateDB . GetBalance ( contract . Address ( ) ) . Sign ( ) != 0 {
2017-01-04 22:17:24 +03:00
gas += gt . CreateBySuicide
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
} else if ! evm . StateDB . Exist ( address ) {
gas += gt . CreateBySuicide
2017-01-05 13:52:10 +03:00
}
}
2017-01-04 22:17:24 +03:00
if ! evm . StateDB . HasSuicided ( contract . Address ( ) ) {
2017-11-13 14:47:27 +03:00
evm . StateDB . AddRefund ( params . SuicideRefundGas )
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
return gas , nil
2017-01-05 13:52:10 +03:00
}
2017-01-04 22:17:24 +03:00
func gasDelegateCall ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
var overflow bool
if gas , overflow = math . SafeAdd ( gas , gt . Calls ) ; overflow {
return 0 , errGasUintOverflow
2017-08-15 11:23:23 +03:00
}
2017-11-28 22:05:49 +03:00
evm . callGasTemp , err = callGas ( gt , contract . Gas , gas , stack . Back ( 0 ) )
2017-08-15 11:23:23 +03:00
if err != nil {
return 0 , err
}
2017-11-28 22:05:49 +03:00
if gas , overflow = math . SafeAdd ( gas , evm . callGasTemp ) ; overflow {
2017-08-15 11:23:23 +03:00
return 0 , errGasUintOverflow
}
return gas , nil
}
func gasStaticCall ( gt params . GasTable , evm * EVM , contract * Contract , stack * Stack , mem * Memory , memorySize uint64 ) ( uint64 , error ) {
gas , err := memoryGasCost ( mem , memorySize )
if err != nil {
return 0 , err
}
var overflow bool
if gas , overflow = math . SafeAdd ( gas , gt . Calls ) ; overflow {
return 0 , errGasUintOverflow
2017-01-04 22:17:24 +03:00
}
2017-01-05 13:52:10 +03:00
2017-11-28 22:05:49 +03:00
evm . callGasTemp , err = callGas ( gt , contract . Gas , gas , stack . Back ( 0 ) )
2017-01-04 22:17:24 +03:00
if err != nil {
return 0 , err
}
2017-11-28 22:05:49 +03:00
if gas , overflow = math . SafeAdd ( gas , evm . callGasTemp ) ; overflow {
2017-01-04 22:17:24 +03:00
return 0 , errGasUintOverflow
}
return gas , nil
2017-01-05 13:52:10 +03:00
}