github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/core/vm/gas_table.go (about) 1 package vm 2 3 import ( 4 "github.com/quickchainproject/quickchain/common" 5 "github.com/quickchainproject/quickchain/common/math" 6 "github.com/quickchainproject/quickchain/params" 7 ) 8 9 // memoryGasCosts calculates the quadratic gas for memory expansion. It does so 10 // only for the memory region that is expanded, not the total memory. 11 func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { 12 13 if newMemSize == 0 { 14 return 0, nil 15 } 16 // The maximum that will fit in a uint64 is max_word_count - 1 17 // anything above that will result in an overflow. 18 // Additionally, a newMemSize which results in a 19 // newMemSizeWords larger than 0x7ffffffff will cause the square operation 20 // to overflow. 21 // The constant 0xffffffffe0 is the highest number that can be used without 22 // overflowing the gas calculation 23 if newMemSize > 0xffffffffe0 { 24 return 0, errGasUintOverflow 25 } 26 27 newMemSizeWords := toWordSize(newMemSize) 28 newMemSize = newMemSizeWords * 32 29 30 if newMemSize > uint64(mem.Len()) { 31 square := newMemSizeWords * newMemSizeWords 32 linCoef := newMemSizeWords * params.MemoryGas 33 quadCoef := square / params.QuadCoeffDiv 34 newTotalFee := linCoef + quadCoef 35 36 fee := newTotalFee - mem.lastGasCost 37 mem.lastGasCost = newTotalFee 38 39 return fee, nil 40 } 41 return 0, nil 42 } 43 44 func constGasFunc(gas uint64) gasFunc { 45 return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 46 return gas, nil 47 } 48 } 49 50 func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 51 gas, err := memoryGasCost(mem, memorySize) 52 if err != nil { 53 return 0, err 54 } 55 56 var overflow bool 57 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 58 return 0, errGasUintOverflow 59 } 60 61 words, overflow := bigUint64(stack.Back(2)) 62 if overflow { 63 return 0, errGasUintOverflow 64 } 65 66 if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { 67 return 0, errGasUintOverflow 68 } 69 70 if gas, overflow = math.SafeAdd(gas, words); overflow { 71 return 0, errGasUintOverflow 72 } 73 return gas, nil 74 } 75 76 func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 77 gas, err := memoryGasCost(mem, memorySize) 78 if err != nil { 79 return 0, err 80 } 81 82 var overflow bool 83 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 84 return 0, errGasUintOverflow 85 } 86 87 words, overflow := bigUint64(stack.Back(2)) 88 if overflow { 89 return 0, errGasUintOverflow 90 } 91 92 if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { 93 return 0, errGasUintOverflow 94 } 95 96 if gas, overflow = math.SafeAdd(gas, words); overflow { 97 return 0, errGasUintOverflow 98 } 99 return gas, nil 100 } 101 102 func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 103 var ( 104 y, x = stack.Back(1), stack.Back(0) 105 val = evm.StateDB.GetState(contract.Address(), common.BigToHash(x)) 106 ) 107 // This checks for 3 scenario's and calculates gas accordingly 108 // 1. From a zero-value address to a non-zero value (NEW VALUE) 109 // 2. From a non-zero value address to a zero-value address (DELETE) 110 // 3. From a non-zero to a non-zero (CHANGE) 111 if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) { 112 // 0 => non 0 113 return params.SstoreSetGas, nil 114 } else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) { 115 evm.StateDB.AddRefund(params.SstoreRefundGas) 116 117 return params.SstoreClearGas, nil 118 } else { 119 // non 0 => non 0 (or 0 => 0) 120 return params.SstoreResetGas, nil 121 } 122 } 123 124 func makeGasLog(n uint64) gasFunc { 125 return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 126 requestedSize, overflow := bigUint64(stack.Back(1)) 127 if overflow { 128 return 0, errGasUintOverflow 129 } 130 131 gas, err := memoryGasCost(mem, memorySize) 132 if err != nil { 133 return 0, err 134 } 135 136 if gas, overflow = math.SafeAdd(gas, params.LogGas); overflow { 137 return 0, errGasUintOverflow 138 } 139 if gas, overflow = math.SafeAdd(gas, n*params.LogTopicGas); overflow { 140 return 0, errGasUintOverflow 141 } 142 143 var memorySizeGas uint64 144 if memorySizeGas, overflow = math.SafeMul(requestedSize, params.LogDataGas); overflow { 145 return 0, errGasUintOverflow 146 } 147 if gas, overflow = math.SafeAdd(gas, memorySizeGas); overflow { 148 return 0, errGasUintOverflow 149 } 150 return gas, nil 151 } 152 } 153 154 func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 155 var overflow bool 156 gas, err := memoryGasCost(mem, memorySize) 157 if err != nil { 158 return 0, err 159 } 160 161 if gas, overflow = math.SafeAdd(gas, params.Sha3Gas); overflow { 162 return 0, errGasUintOverflow 163 } 164 165 wordGas, overflow := bigUint64(stack.Back(1)) 166 if overflow { 167 return 0, errGasUintOverflow 168 } 169 if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Sha3WordGas); overflow { 170 return 0, errGasUintOverflow 171 } 172 if gas, overflow = math.SafeAdd(gas, wordGas); overflow { 173 return 0, errGasUintOverflow 174 } 175 return gas, nil 176 } 177 178 func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 179 gas, err := memoryGasCost(mem, memorySize) 180 if err != nil { 181 return 0, err 182 } 183 184 var overflow bool 185 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 186 return 0, errGasUintOverflow 187 } 188 189 wordGas, overflow := bigUint64(stack.Back(2)) 190 if overflow { 191 return 0, errGasUintOverflow 192 } 193 if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow { 194 return 0, errGasUintOverflow 195 } 196 if gas, overflow = math.SafeAdd(gas, wordGas); overflow { 197 return 0, errGasUintOverflow 198 } 199 return gas, nil 200 } 201 202 func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 203 gas, err := memoryGasCost(mem, memorySize) 204 if err != nil { 205 return 0, err 206 } 207 208 var overflow bool 209 if gas, overflow = math.SafeAdd(gas, gt.ExtcodeCopy); overflow { 210 return 0, errGasUintOverflow 211 } 212 213 wordGas, overflow := bigUint64(stack.Back(3)) 214 if overflow { 215 return 0, errGasUintOverflow 216 } 217 218 if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow { 219 return 0, errGasUintOverflow 220 } 221 222 if gas, overflow = math.SafeAdd(gas, wordGas); overflow { 223 return 0, errGasUintOverflow 224 } 225 return gas, nil 226 } 227 228 func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 229 var overflow bool 230 gas, err := memoryGasCost(mem, memorySize) 231 if err != nil { 232 return 0, errGasUintOverflow 233 } 234 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 235 return 0, errGasUintOverflow 236 } 237 return gas, nil 238 } 239 240 func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 241 var overflow bool 242 gas, err := memoryGasCost(mem, memorySize) 243 if err != nil { 244 return 0, errGasUintOverflow 245 } 246 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 247 return 0, errGasUintOverflow 248 } 249 return gas, nil 250 } 251 252 func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 253 var overflow bool 254 gas, err := memoryGasCost(mem, memorySize) 255 if err != nil { 256 return 0, errGasUintOverflow 257 } 258 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 259 return 0, errGasUintOverflow 260 } 261 return gas, nil 262 } 263 264 func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 265 var overflow bool 266 gas, err := memoryGasCost(mem, memorySize) 267 if err != nil { 268 return 0, err 269 } 270 if gas, overflow = math.SafeAdd(gas, params.CreateGas); overflow { 271 return 0, errGasUintOverflow 272 } 273 return gas, nil 274 } 275 276 func gasBalance(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 277 return gt.Balance, nil 278 } 279 280 func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 281 return gt.ExtcodeSize, nil 282 } 283 284 func gasSLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 285 return gt.SLoad, nil 286 } 287 288 func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 289 expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) 290 291 var ( 292 gas = expByteLen * gt.ExpByte // no overflow check required. Max is 256 * ExpByte gas 293 overflow bool 294 ) 295 if gas, overflow = math.SafeAdd(gas, GasSlowStep); overflow { 296 return 0, errGasUintOverflow 297 } 298 return gas, nil 299 } 300 301 func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 302 var ( 303 gas = gt.Calls 304 transfersValue = stack.Back(2).Sign() != 0 305 address = common.BigToAddress(stack.Back(1)) 306 eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber) 307 ) 308 if eip158 { 309 if transfersValue && evm.StateDB.Empty(address) { 310 gas += params.CallNewAccountGas 311 } 312 } else if !evm.StateDB.Exist(address) { 313 gas += params.CallNewAccountGas 314 } 315 if transfersValue { 316 gas += params.CallValueTransferGas 317 } 318 memoryGas, err := memoryGasCost(mem, memorySize) 319 if err != nil { 320 return 0, err 321 } 322 var overflow bool 323 if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { 324 return 0, errGasUintOverflow 325 } 326 327 evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) 328 if err != nil { 329 return 0, err 330 } 331 if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { 332 return 0, errGasUintOverflow 333 } 334 return gas, nil 335 } 336 337 func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 338 gas := gt.Calls 339 if stack.Back(2).Sign() != 0 { 340 gas += params.CallValueTransferGas 341 } 342 memoryGas, err := memoryGasCost(mem, memorySize) 343 if err != nil { 344 return 0, err 345 } 346 var overflow bool 347 if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { 348 return 0, errGasUintOverflow 349 } 350 351 evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) 352 if err != nil { 353 return 0, err 354 } 355 if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { 356 return 0, errGasUintOverflow 357 } 358 return gas, nil 359 } 360 361 func gasReturn(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 362 return memoryGasCost(mem, memorySize) 363 } 364 365 func gasRevert(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 366 return memoryGasCost(mem, memorySize) 367 } 368 369 func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 370 var gas uint64 371 // EIP150 homestead gas reprice fork: 372 if evm.ChainConfig().IsEIP150(evm.BlockNumber) { 373 gas = gt.Suicide 374 var ( 375 address = common.BigToAddress(stack.Back(0)) 376 eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber) 377 ) 378 379 if eip158 { 380 // if empty and transfers value 381 if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 { 382 gas += gt.CreateBySuicide 383 } 384 } else if !evm.StateDB.Exist(address) { 385 gas += gt.CreateBySuicide 386 } 387 } 388 389 if !evm.StateDB.HasSuicided(contract.Address()) { 390 evm.StateDB.AddRefund(params.SuicideRefundGas) 391 } 392 return gas, nil 393 } 394 395 func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 396 gas, err := memoryGasCost(mem, memorySize) 397 if err != nil { 398 return 0, err 399 } 400 var overflow bool 401 if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow { 402 return 0, errGasUintOverflow 403 } 404 405 evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) 406 if err != nil { 407 return 0, err 408 } 409 if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { 410 return 0, errGasUintOverflow 411 } 412 return gas, nil 413 } 414 415 func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 416 gas, err := memoryGasCost(mem, memorySize) 417 if err != nil { 418 return 0, err 419 } 420 var overflow bool 421 if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow { 422 return 0, errGasUintOverflow 423 } 424 425 evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) 426 if err != nil { 427 return 0, err 428 } 429 if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { 430 return 0, errGasUintOverflow 431 } 432 return gas, nil 433 } 434 435 func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 436 return GasFastestStep, nil 437 } 438 439 func gasSwap(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 440 return GasFastestStep, nil 441 } 442 443 func gasDup(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 444 return GasFastestStep, nil 445 }