github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/core/wavm/gas/rules.go (about)

     1  // Copyright 2019 The go-vnt Authors
     2  // This file is part of the go-vnt library.
     3  //
     4  // The go-vnt library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-vnt library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-vnt library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package gas
    18  
    19  import (
    20  	"errors"
    21  	"math/big"
    22  
    23  	"github.com/vntchain/go-vnt/common"
    24  	"github.com/vntchain/go-vnt/common/math"
    25  	"github.com/vntchain/go-vnt/core/state"
    26  	"github.com/vntchain/go-vnt/core/vm"
    27  	"github.com/vntchain/go-vnt/core/wavm/contract"
    28  	"github.com/vntchain/go-vnt/params"
    29  	ops "github.com/vntchain/vnt-wasm/wasm/operators"
    30  )
    31  
    32  const (
    33  	WasmCostsRegular       = 1
    34  	WasmCostsDiv           = 16
    35  	WasmCostsMul           = 4
    36  	WasmCostsMem           = 2
    37  	WasmCostsStaticU256    = 64
    38  	WasmCostsStaticHash    = 64
    39  	WasmCostsStaticAddress = 40
    40  	/// Memory stipend. Amount of free memory (in 64kb pages) each contract can use for stack.
    41  	WasmCostsInitialMem = 4096
    42  	/// Grow memory cost, per page (64kb)
    43  	WasmCostsGrowMem        = 8192
    44  	WasmCostsMemcpy         = 1
    45  	WasmCostsMaxStackHeight = 64 * 1024
    46  	WasmCostsOpcodesMul     = 3
    47  	WasmCostsOpcodesDiv     = 8
    48  )
    49  
    50  const ErrorGasLimit = "Invocation resulted in gas limit violated"
    51  const ErrorInitialMemLimit = "Initial memory limit"
    52  const ErrorDisableFloatingPoint = "Wasm contract error: disabled floating point"
    53  
    54  var errGasUintOverflow = errors.New("gas uint64 overflow")
    55  
    56  type GasValue struct {
    57  	Metering Metering
    58  	Value    uint64
    59  }
    60  
    61  type Gas struct {
    62  	Ops   map[byte]InstructionType
    63  	Rules map[InstructionType]GasValue
    64  }
    65  
    66  type GasCounter struct {
    67  	Contract *contract.WASMContract
    68  	GasTable params.GasTable
    69  }
    70  
    71  func NewGas(disableFloatingPoint bool) Gas {
    72  	rules := Gas{
    73  		Ops: map[byte]InstructionType{
    74  			ops.Unreachable:  InstructionTypeUnreachable,
    75  			ops.Nop:          InstructionTypeNop,
    76  			ops.Block:        InstructionTypeControlFlow,
    77  			ops.Loop:         InstructionTypeControlFlow,
    78  			ops.If:           InstructionTypeControlFlow,
    79  			ops.Else:         InstructionTypeControlFlow,
    80  			ops.End:          InstructionTypeControlFlow,
    81  			ops.Br:           InstructionTypeControlFlow,
    82  			ops.BrIf:         InstructionTypeControlFlow,
    83  			ops.BrTable:      InstructionTypeControlFlow,
    84  			ops.Return:       InstructionTypeControlFlow,
    85  			ops.Call:         InstructionTypeControlFlow,
    86  			ops.CallIndirect: InstructionTypeControlFlow,
    87  			ops.Drop:         InstructionTypeControlFlow,
    88  			ops.Select:       InstructionTypeControlFlow,
    89  
    90  			ops.GetLocal:  InstructionTypeLocal,
    91  			ops.SetLocal:  InstructionTypeLocal,
    92  			ops.TeeLocal:  InstructionTypeLocal,
    93  			ops.GetGlobal: InstructionTypeLocal,
    94  			ops.SetGlobal: InstructionTypeLocal,
    95  
    96  			ops.I32Load:    InstructionTypeLoad,
    97  			ops.I64Load:    InstructionTypeLoad,
    98  			ops.F32Load:    InstructionTypeLoad,
    99  			ops.F64Load:    InstructionTypeLoad,
   100  			ops.I32Load8s:  InstructionTypeLoad,
   101  			ops.I32Load8u:  InstructionTypeLoad,
   102  			ops.I32Load16s: InstructionTypeLoad,
   103  			ops.I32Load16u: InstructionTypeLoad,
   104  			ops.I64Load8s:  InstructionTypeLoad,
   105  			ops.I64Load8u:  InstructionTypeLoad,
   106  			ops.I64Load16s: InstructionTypeLoad,
   107  			ops.I64Load16u: InstructionTypeLoad,
   108  			ops.I64Load32s: InstructionTypeLoad,
   109  			ops.I64Load32u: InstructionTypeLoad,
   110  
   111  			ops.I32Store:   InstructionTypeStore,
   112  			ops.I64Store:   InstructionTypeStore,
   113  			ops.F32Store:   InstructionTypeStore,
   114  			ops.F64Store:   InstructionTypeStore,
   115  			ops.I32Store8:  InstructionTypeStore,
   116  			ops.I32Store16: InstructionTypeStore,
   117  			ops.I64Store8:  InstructionTypeStore,
   118  			ops.I64Store16: InstructionTypeStore,
   119  			ops.I64Store32: InstructionTypeStore,
   120  
   121  			ops.CurrentMemory: InstructionTypeCurrentMemory,
   122  			ops.GrowMemory:    InstructionTypeGrowMemory,
   123  
   124  			ops.I32Const: InstructionTypeConst,
   125  			ops.I64Const: InstructionTypeConst,
   126  
   127  			ops.F32Const: InstructionTypeFloatConst,
   128  			ops.F64Const: InstructionTypeFloatConst,
   129  
   130  			ops.I32Eqz: InstructionTypeIntegerComparsion,
   131  			ops.I32Eq:  InstructionTypeIntegerComparsion,
   132  			ops.I32Ne:  InstructionTypeIntegerComparsion,
   133  			ops.I32LtS: InstructionTypeIntegerComparsion,
   134  			ops.I32LtU: InstructionTypeIntegerComparsion,
   135  			ops.I32GtS: InstructionTypeIntegerComparsion,
   136  			ops.I32GtU: InstructionTypeIntegerComparsion,
   137  			ops.I32LeS: InstructionTypeIntegerComparsion,
   138  			ops.I32LeU: InstructionTypeIntegerComparsion,
   139  			ops.I32GeS: InstructionTypeIntegerComparsion,
   140  			ops.I32GeU: InstructionTypeIntegerComparsion,
   141  
   142  			ops.I64Eqz: InstructionTypeIntegerComparsion,
   143  			ops.I64Eq:  InstructionTypeIntegerComparsion,
   144  			ops.I64Ne:  InstructionTypeIntegerComparsion,
   145  			ops.I64LtS: InstructionTypeIntegerComparsion,
   146  			ops.I64LtU: InstructionTypeIntegerComparsion,
   147  			ops.I64GtS: InstructionTypeIntegerComparsion,
   148  			ops.I64GtU: InstructionTypeIntegerComparsion,
   149  			ops.I64LeS: InstructionTypeIntegerComparsion,
   150  			ops.I64LeU: InstructionTypeIntegerComparsion,
   151  			ops.I64GeS: InstructionTypeIntegerComparsion,
   152  			ops.I64GeU: InstructionTypeIntegerComparsion,
   153  
   154  			ops.F32Eq: InstructionTypeFloatComparsion,
   155  			ops.F32Ne: InstructionTypeFloatComparsion,
   156  			ops.F32Lt: InstructionTypeFloatComparsion,
   157  			ops.F32Gt: InstructionTypeFloatComparsion,
   158  			ops.F32Le: InstructionTypeFloatComparsion,
   159  			ops.F32Ge: InstructionTypeFloatComparsion,
   160  
   161  			ops.F64Eq: InstructionTypeFloatComparsion,
   162  			ops.F64Ne: InstructionTypeFloatComparsion,
   163  			ops.F64Lt: InstructionTypeFloatComparsion,
   164  			ops.F64Gt: InstructionTypeFloatComparsion,
   165  			ops.F64Le: InstructionTypeFloatComparsion,
   166  			ops.F64Ge: InstructionTypeFloatComparsion,
   167  
   168  			ops.I32Clz:    InstructionTypeBit,
   169  			ops.I32Ctz:    InstructionTypeBit,
   170  			ops.I32Popcnt: InstructionTypeBit,
   171  			ops.I32Add:    InstructionTypeAdd,
   172  			ops.I32Sub:    InstructionTypeAdd,
   173  			ops.I32Mul:    InstructionTypeMul,
   174  			ops.I32DivS:   InstructionTypeDiv,
   175  			ops.I32DivU:   InstructionTypeDiv,
   176  			ops.I32RemS:   InstructionTypeDiv,
   177  			ops.I32RemU:   InstructionTypeDiv,
   178  			ops.I32And:    InstructionTypeBit,
   179  			ops.I32Or:     InstructionTypeBit,
   180  			ops.I32Xor:    InstructionTypeBit,
   181  			ops.I32Shl:    InstructionTypeBit,
   182  			ops.I32ShrS:   InstructionTypeBit,
   183  			ops.I32ShrU:   InstructionTypeBit,
   184  			ops.I32Rotl:   InstructionTypeBit,
   185  			ops.I32Rotr:   InstructionTypeBit,
   186  
   187  			ops.I64Clz:    InstructionTypeBit,
   188  			ops.I64Ctz:    InstructionTypeBit,
   189  			ops.I64Popcnt: InstructionTypeBit,
   190  			ops.I64Add:    InstructionTypeAdd,
   191  			ops.I64Sub:    InstructionTypeAdd,
   192  			ops.I64Mul:    InstructionTypeMul,
   193  			ops.I64DivS:   InstructionTypeDiv,
   194  			ops.I64DivU:   InstructionTypeDiv,
   195  			ops.I64RemS:   InstructionTypeDiv,
   196  			ops.I64RemU:   InstructionTypeDiv,
   197  			ops.I64And:    InstructionTypeBit,
   198  			ops.I64Or:     InstructionTypeBit,
   199  			ops.I64Xor:    InstructionTypeBit,
   200  			ops.I64Shl:    InstructionTypeBit,
   201  			ops.I64ShrS:   InstructionTypeBit,
   202  			ops.I64ShrU:   InstructionTypeBit,
   203  			ops.I64Rotl:   InstructionTypeBit,
   204  			ops.I64Rotr:   InstructionTypeBit,
   205  
   206  			ops.F32Abs:      InstructionTypeFloat,
   207  			ops.F32Neg:      InstructionTypeFloat,
   208  			ops.F32Ceil:     InstructionTypeFloat,
   209  			ops.F32Floor:    InstructionTypeFloat,
   210  			ops.F32Trunc:    InstructionTypeFloat,
   211  			ops.F32Nearest:  InstructionTypeFloat,
   212  			ops.F32Sqrt:     InstructionTypeFloat,
   213  			ops.F32Add:      InstructionTypeFloat,
   214  			ops.F32Sub:      InstructionTypeFloat,
   215  			ops.F32Mul:      InstructionTypeFloat,
   216  			ops.F32Div:      InstructionTypeFloat,
   217  			ops.F32Min:      InstructionTypeFloat,
   218  			ops.F32Max:      InstructionTypeFloat,
   219  			ops.F32Copysign: InstructionTypeFloat,
   220  			ops.F64Abs:      InstructionTypeFloat,
   221  			ops.F64Neg:      InstructionTypeFloat,
   222  			ops.F64Ceil:     InstructionTypeFloat,
   223  			ops.F64Floor:    InstructionTypeFloat,
   224  			ops.F64Trunc:    InstructionTypeFloat,
   225  			ops.F64Nearest:  InstructionTypeFloat,
   226  			ops.F64Sqrt:     InstructionTypeFloat,
   227  			ops.F64Add:      InstructionTypeFloat,
   228  			ops.F64Sub:      InstructionTypeFloat,
   229  			ops.F64Mul:      InstructionTypeFloat,
   230  			ops.F64Div:      InstructionTypeFloat,
   231  			ops.F64Min:      InstructionTypeFloat,
   232  			ops.F64Max:      InstructionTypeFloat,
   233  			ops.F64Copysign: InstructionTypeFloat,
   234  
   235  			ops.I32WrapI64:    InstructionTypeConversion,
   236  			ops.I64ExtendSI32: InstructionTypeConversion,
   237  			ops.I64ExtendUI32: InstructionTypeConversion,
   238  
   239  			ops.I32TruncSF32:   InstructionTypeFloatConversion,
   240  			ops.I32TruncUF32:   InstructionTypeFloatConversion,
   241  			ops.I32TruncSF64:   InstructionTypeFloatConversion,
   242  			ops.I32TruncUF64:   InstructionTypeFloatConversion,
   243  			ops.I64TruncSF32:   InstructionTypeFloatConversion,
   244  			ops.I64TruncUF32:   InstructionTypeFloatConversion,
   245  			ops.I64TruncSF64:   InstructionTypeFloatConversion,
   246  			ops.I64TruncUF64:   InstructionTypeFloatConversion,
   247  			ops.F32ConvertSI32: InstructionTypeFloatConversion,
   248  			ops.F32ConvertUI32: InstructionTypeFloatConversion,
   249  			ops.F32ConvertSI64: InstructionTypeFloatConversion,
   250  			ops.F32ConvertUI64: InstructionTypeFloatConversion,
   251  			ops.F32DemoteF64:   InstructionTypeFloatConversion,
   252  			ops.F64ConvertSI32: InstructionTypeFloatConversion,
   253  			ops.F64ConvertUI32: InstructionTypeFloatConversion,
   254  			ops.F64ConvertSI64: InstructionTypeFloatConversion,
   255  			ops.F64ConvertUI64: InstructionTypeFloatConversion,
   256  			ops.F64PromoteF32:  InstructionTypeFloatConversion,
   257  
   258  			ops.I32ReinterpretF32: InstructionTypeReinterpretation,
   259  			ops.I64ReinterpretF64: InstructionTypeReinterpretation,
   260  			ops.F32ReinterpretI32: InstructionTypeReinterpretation,
   261  			ops.F64ReinterpretI64: InstructionTypeReinterpretation,
   262  		},
   263  		Rules: map[InstructionType]GasValue{
   264  			InstructionTypeLoad:  GasValue{Metering: MeteringFixed, Value: WasmCostsMem},
   265  			InstructionTypeStore: GasValue{Metering: MeteringFixed, Value: WasmCostsMem},
   266  			InstructionTypeDiv:   GasValue{Metering: MeteringFixed, Value: WasmCostsDiv},
   267  			InstructionTypeMul:   GasValue{Metering: MeteringFixed, Value: WasmCostsMul},
   268  		},
   269  	}
   270  	if disableFloatingPoint {
   271  		rules.Rules[InstructionTypeFloat] = GasValue{
   272  			Metering: MeteringForbidden, Value: 0,
   273  		}
   274  		rules.Rules[InstructionTypeFloatComparsion] = GasValue{
   275  			Metering: MeteringForbidden, Value: 0,
   276  		}
   277  		rules.Rules[InstructionTypeFloatConst] = GasValue{
   278  			Metering: MeteringForbidden, Value: 0,
   279  		}
   280  		rules.Rules[InstructionTypeFloatConversion] = GasValue{
   281  			Metering: MeteringForbidden, Value: 0,
   282  		}
   283  	}
   284  	return rules
   285  }
   286  
   287  func (gas Gas) GasCost(op byte) uint64 {
   288  	metering := gas.Rules[gas.Ops[op]]
   289  	switch metering.Metering {
   290  	case MeteringForbidden:
   291  		panic(ErrorDisableFloatingPoint)
   292  	case MeteringFixed:
   293  		return metering.Value
   294  	default:
   295  		return WasmCostsRegular
   296  	}
   297  }
   298  
   299  func constGasFunc(gas uint64) uint64 {
   300  	return gas
   301  }
   302  
   303  func NewGasCounter(contract *contract.WASMContract, gasTable params.GasTable) GasCounter {
   304  	return GasCounter{
   305  		Contract: contract,
   306  		GasTable: gasTable,
   307  	}
   308  
   309  }
   310  
   311  func (gas GasCounter) Charge(amount uint64) {
   312  	if !gas.ChargeGas(amount) {
   313  		panic(ErrorGasLimit)
   314  	}
   315  }
   316  
   317  func (gas GasCounter) ChargeGas(amount uint64) bool {
   318  	return gas.Contract.UseGas(amount)
   319  }
   320  
   321  func (gas GasCounter) AdjustedCharge(amount uint64) {
   322  	// gas.Charge(amount * WasmCostsOpcodesMul / WasmCostsOpcodesDiv)
   323  	gas.Charge(amount)
   324  }
   325  
   326  func (gas GasCounter) GasQuickStep() {
   327  	gas.Charge(constGasFunc(vm.GasQuickStep))
   328  }
   329  
   330  func (gas GasCounter) GasFastestStep() {
   331  	gas.Charge(constGasFunc(vm.GasFastestStep))
   332  }
   333  
   334  func (gas GasCounter) GasGetBlockNumber() {
   335  	gas.Charge(constGasFunc(vm.GasQuickStep))
   336  }
   337  
   338  func (gas GasCounter) GasGetBalanceFromAddress() {
   339  	gas.Charge(constGasFunc(vm.GasQuickStep))
   340  }
   341  
   342  func (gas GasCounter) GasMemoryCost(size uint64) {
   343  	gas.Charge(constGasFunc(vm.GasQuickStep * size))
   344  }
   345  
   346  func (gas GasCounter) GasGetGas() {
   347  	gas.Charge(constGasFunc(vm.GasQuickStep))
   348  }
   349  
   350  func (gas GasCounter) GasGetBlockHash() {
   351  	gas.Charge(constGasFunc(vm.GasExtStep))
   352  }
   353  
   354  func (gas GasCounter) GasGetBlockProduser() {
   355  	gas.Charge(constGasFunc(vm.GasQuickStep))
   356  }
   357  
   358  func (gas GasCounter) GasGetTimestamp() {
   359  	gas.Charge(constGasFunc(vm.GasQuickStep))
   360  }
   361  
   362  func (gas GasCounter) GasGetOrigin() {
   363  	gas.Charge(constGasFunc(vm.GasQuickStep))
   364  }
   365  
   366  func (gas GasCounter) GasGetSender() {
   367  	gas.Charge(constGasFunc(vm.GasQuickStep))
   368  }
   369  
   370  func (gas GasCounter) GasGetGasLimit() {
   371  	gas.Charge(constGasFunc(vm.GasQuickStep))
   372  }
   373  
   374  // func (vm *VM) GasGenerateKey() error {
   375  // 	return vm.adjustedCharge(constGasFunc(20))
   376  // }
   377  
   378  // func (vm *VM) GasGetStorageCount() error {
   379  // 	return nil
   380  // }
   381  
   382  func (gas GasCounter) GasGetValue() {
   383  	gas.Charge(constGasFunc(vm.GasQuickStep))
   384  }
   385  
   386  //todo 验证sha3 gas消耗,和evm保持一致
   387  func (gas GasCounter) GasSHA3(size uint64) {
   388  	gas.Charge(params.Sha3Gas)
   389  	gas.Charge(params.Sha3WordGas * size)
   390  }
   391  
   392  func (gas GasCounter) GasGetContractAddress() {
   393  	gas.Charge(constGasFunc(vm.GasQuickStep))
   394  }
   395  
   396  func (gas GasCounter) GasAssert() {
   397  	gas.Charge(constGasFunc(vm.GasQuickStep))
   398  }
   399  
   400  func (gas GasCounter) GasRevert() {
   401  	gas.Charge(constGasFunc(vm.GasQuickStep))
   402  }
   403  
   404  func (gas GasCounter) GasSendFromContract() {
   405  	gas.Charge(constGasFunc(params.CallStipend))
   406  }
   407  
   408  // func (gas GasCounter) GasGetContractValue() {
   409  // 	gas.Charge(constGasFunc(params.CallValueTransferGas))
   410  // }
   411  
   412  func (gas GasCounter) GasFromI64() {
   413  	gas.Charge(constGasFunc(vm.GasQuickStep))
   414  }
   415  
   416  func (gas GasCounter) GasFromU64() {
   417  	gas.Charge(constGasFunc(vm.GasQuickStep))
   418  }
   419  
   420  func (gas GasCounter) GasToI64() {
   421  	gas.Charge(constGasFunc(vm.GasQuickStep))
   422  }
   423  
   424  func (gas GasCounter) GasToU64() {
   425  	gas.Charge(constGasFunc(vm.GasQuickStep))
   426  }
   427  
   428  func (gas GasCounter) GasConcat(size uint64) {
   429  	gas.Charge(constGasFunc(WasmCostsMem * size))
   430  }
   431  
   432  func (gas GasCounter) GasEqual() {
   433  	gas.Charge(constGasFunc(vm.GasQuickStep))
   434  }
   435  
   436  func (gas GasCounter) GasLog(size uint64, topics uint64) {
   437  	requestedSize, overflow := vm.BigUint64(new(big.Int).SetUint64(size))
   438  	if overflow {
   439  		panic(errGasUintOverflow)
   440  	}
   441  	costgas := uint64(0)
   442  	if costgas, overflow = math.SafeAdd(costgas, params.LogGas); overflow {
   443  		panic(errGasUintOverflow)
   444  	}
   445  	if costgas, overflow = math.SafeAdd(costgas, topics*params.LogTopicGas); overflow {
   446  		panic(errGasUintOverflow)
   447  	}
   448  	var memorySizeGas uint64
   449  	if memorySizeGas, overflow = math.SafeMul(requestedSize, params.LogDataGas); overflow {
   450  		panic(errGasUintOverflow)
   451  	}
   452  	if costgas, overflow = math.SafeAdd(costgas, memorySizeGas); overflow {
   453  		panic(errGasUintOverflow)
   454  	}
   455  	gas.Charge(costgas)
   456  }
   457  
   458  func (gas GasCounter) GasCall(address common.Address, value, gasLimit, blockNumber *big.Int, chainConfig *params.ChainConfig, statedb *state.StateDB) uint64 {
   459  	var (
   460  		callgas        = gas.GasTable.Calls
   461  		transfersValue = value.Sign() != 0
   462  	)
   463  	if transfersValue && statedb.Empty(address) {
   464  		callgas += params.CallNewAccountGas
   465  	}
   466  	if transfersValue {
   467  		callgas += params.CallValueTransferGas
   468  	}
   469  	tempgas, err := gas.callGas(gas.GasTable, gas.Contract.Gas, callgas, gasLimit)
   470  	if err != nil {
   471  		panic(err.Error())
   472  	}
   473  
   474  	var overflow bool
   475  	if callgas, overflow = math.SafeAdd(callgas, tempgas); overflow {
   476  		panic(errGasUintOverflow)
   477  	}
   478  	gas.Charge(callgas)
   479  	return tempgas
   480  }
   481  
   482  func (gas GasCounter) callGas(gasTable params.GasTable, availableGas, base uint64, callCost *big.Int) (uint64, error) {
   483  	if gasTable.CreateBySuicide > 0 {
   484  		availableGas = availableGas - base
   485  		gas := availableGas - availableGas/64
   486  		// If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150
   487  		// is smaller than the requested amount. Therefor we return the new gas instead
   488  		// of returning an error.
   489  		if callCost.BitLen() > 64 || gas < callCost.Uint64() {
   490  			return gas, nil
   491  		}
   492  	}
   493  	if callCost.BitLen() > 64 {
   494  		return 0, errGasUintOverflow
   495  	}
   496  	return callCost.Uint64(), nil
   497  }
   498  
   499  func (gas GasCounter) GasStore(stateDb *state.StateDB, contractAddr common.Address, loc common.Hash, value common.Hash) {
   500  	var (
   501  		y, x = value, loc
   502  		val  = stateDb.GetState(contractAddr, x)
   503  	)
   504  	// This checks for 3 scenario's and calculates gas accordingly
   505  	// 1. From a zero-value address to a non-zero value         (NEW VALUE)
   506  	// 2. From a non-zero value address to a zero-value address (DELETE)
   507  	// 3. From a non-zero to a non-zero                         (CHANGE)
   508  	if (val == common.Hash{} && y != common.Hash{}) {
   509  		// 0 => non 0
   510  		gas.Charge(constGasFunc(params.SstoreSetGas))
   511  		// return params.SstoreSetGas, nil
   512  	} else if (val != common.Hash{} && y == common.Hash{}) {
   513  		stateDb.AddRefund(params.SstoreRefundGas)
   514  		gas.Charge(constGasFunc(params.SstoreClearGas))
   515  		// return params.SstoreClearGas, nil
   516  	} else {
   517  		// non 0 => non 0 (or 0 => 0)
   518  		gas.Charge(constGasFunc(params.SstoreResetGas))
   519  		// return params.SstoreResetGas, nil
   520  	}
   521  }
   522  
   523  func (gas GasCounter) GasLoad() {
   524  	gas.Charge(constGasFunc(gas.GasTable.SLoad))
   525  }
   526  
   527  func (gas GasCounter) GasEcrecover() {
   528  	gas.Charge(constGasFunc(params.EcrecoverGas))
   529  }
   530  
   531  func (gas GasCounter) GasPow(exponent *big.Int) {
   532  	expByteLen := uint64((exponent.BitLen() + 7) / 8)
   533  	var (
   534  		costgas  = expByteLen * gas.GasTable.ExpByte // no overflow check required. Max is 256 * ExpByte gas
   535  		overflow bool
   536  	)
   537  	if costgas, overflow = math.SafeAdd(costgas, vm.GasQuickStep); overflow {
   538  		panic(errGasUintOverflow)
   539  	}
   540  	gas.Charge(constGasFunc(costgas))
   541  }
   542  
   543  func (gas GasCounter) GasCostZero() {
   544  	gas.Charge(constGasFunc(0))
   545  }
   546  
   547  func (gas GasCounter) GasReturnAddress() {
   548  	gas.AdjustedCharge(constGasFunc(WasmCostsStaticAddress))
   549  }
   550  
   551  func (gas GasCounter) GasReturnU256() {
   552  	gas.AdjustedCharge(constGasFunc(WasmCostsStaticU256))
   553  }
   554  
   555  func (gas GasCounter) GasReturnHash() {
   556  	gas.AdjustedCharge(constGasFunc(WasmCostsStaticHash))
   557  }
   558  
   559  func (gas GasCounter) GasReturnPointer(size uint64) {
   560  	gas.AdjustedCharge(constGasFunc(size))
   561  }
   562  
   563  func (gas GasCounter) GasInitialMemory(initial uint64) {
   564  	amount := initial * WasmCostsInitialMem
   565  	if !gas.ChargeGas(amount) {
   566  		panic(ErrorInitialMemLimit)
   567  	}
   568  }