github.com/theQRL/go-zond@v0.2.1/core/vm/gas_table.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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-ethereum 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-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vm 18 19 import ( 20 "github.com/theQRL/go-zond/common" 21 "github.com/theQRL/go-zond/common/math" 22 "github.com/theQRL/go-zond/params" 23 ) 24 25 // memoryGasCost calculates the quadratic gas for memory expansion. It does so 26 // only for the memory region that is expanded, not the total memory. 27 func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { 28 if newMemSize == 0 { 29 return 0, nil 30 } 31 // The maximum that will fit in a uint64 is max_word_count - 1. Anything above 32 // that will result in an overflow. Additionally, a newMemSize which results in 33 // a newMemSizeWords larger than 0xFFFFFFFF will cause the square operation to 34 // overflow. The constant 0x1FFFFFFFE0 is the highest number that can be used 35 // without overflowing the gas calculation. 36 if newMemSize > 0x1FFFFFFFE0 { 37 return 0, ErrGasUintOverflow 38 } 39 newMemSizeWords := toWordSize(newMemSize) 40 newMemSize = newMemSizeWords * 32 41 42 if newMemSize > uint64(mem.Len()) { 43 square := newMemSizeWords * newMemSizeWords 44 linCoef := newMemSizeWords * params.MemoryGas 45 quadCoef := square / params.QuadCoeffDiv 46 newTotalFee := linCoef + quadCoef 47 48 fee := newTotalFee - mem.lastGasCost 49 mem.lastGasCost = newTotalFee 50 51 return fee, nil 52 } 53 return 0, nil 54 } 55 56 // memoryCopierGas creates the gas functions for the following opcodes, and takes 57 // the stack position of the operand which determines the size of the data to copy 58 // as argument: 59 // CALLDATACOPY (stack position 2) 60 // CODECOPY (stack position 2) 61 // EXTCODECOPY (stack position 3) 62 // RETURNDATACOPY (stack position 2) 63 func memoryCopierGas(stackpos int) gasFunc { 64 return func(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 65 // Gas for expanding the memory 66 gas, err := memoryGasCost(mem, memorySize) 67 if err != nil { 68 return 0, err 69 } 70 // And gas for copying data, charged per word at param.CopyGas 71 words, overflow := stack.Back(stackpos).Uint64WithOverflow() 72 if overflow { 73 return 0, ErrGasUintOverflow 74 } 75 76 if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { 77 return 0, ErrGasUintOverflow 78 } 79 80 if gas, overflow = math.SafeAdd(gas, words); overflow { 81 return 0, ErrGasUintOverflow 82 } 83 return gas, nil 84 } 85 } 86 87 var ( 88 gasCallDataCopy = memoryCopierGas(2) 89 gasCodeCopy = memoryCopierGas(2) 90 gasExtCodeCopy = memoryCopierGas(3) 91 gasReturnDataCopy = memoryCopierGas(2) 92 ) 93 94 func makeGasLog(n uint64) gasFunc { 95 return func(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 96 requestedSize, overflow := stack.Back(1).Uint64WithOverflow() 97 if overflow { 98 return 0, ErrGasUintOverflow 99 } 100 101 gas, err := memoryGasCost(mem, memorySize) 102 if err != nil { 103 return 0, err 104 } 105 106 if gas, overflow = math.SafeAdd(gas, params.LogGas); overflow { 107 return 0, ErrGasUintOverflow 108 } 109 if gas, overflow = math.SafeAdd(gas, n*params.LogTopicGas); overflow { 110 return 0, ErrGasUintOverflow 111 } 112 113 var memorySizeGas uint64 114 if memorySizeGas, overflow = math.SafeMul(requestedSize, params.LogDataGas); overflow { 115 return 0, ErrGasUintOverflow 116 } 117 if gas, overflow = math.SafeAdd(gas, memorySizeGas); overflow { 118 return 0, ErrGasUintOverflow 119 } 120 return gas, nil 121 } 122 } 123 124 func gasKeccak256(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 125 gas, err := memoryGasCost(mem, memorySize) 126 if err != nil { 127 return 0, err 128 } 129 wordGas, overflow := stack.Back(1).Uint64WithOverflow() 130 if overflow { 131 return 0, ErrGasUintOverflow 132 } 133 if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Keccak256WordGas); overflow { 134 return 0, ErrGasUintOverflow 135 } 136 if gas, overflow = math.SafeAdd(gas, wordGas); overflow { 137 return 0, ErrGasUintOverflow 138 } 139 return gas, nil 140 } 141 142 // pureMemoryGascost is used by several operations, which aside from their 143 // static cost have a dynamic cost which is solely based on the memory 144 // expansion 145 func pureMemoryGascost(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 146 return memoryGasCost(mem, memorySize) 147 } 148 149 var ( 150 gasReturn = pureMemoryGascost 151 gasRevert = pureMemoryGascost 152 gasMLoad = pureMemoryGascost 153 gasMStore8 = pureMemoryGascost 154 gasMStore = pureMemoryGascost 155 ) 156 157 func gasCreateEip3860(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 158 gas, err := memoryGasCost(mem, memorySize) 159 if err != nil { 160 return 0, err 161 } 162 size, overflow := stack.Back(2).Uint64WithOverflow() 163 if overflow || size > params.MaxInitCodeSize { 164 return 0, ErrGasUintOverflow 165 } 166 // Since size <= params.MaxInitCodeSize, these multiplication cannot overflow 167 moreGas := params.InitCodeWordGas * ((size + 31) / 32) 168 if gas, overflow = math.SafeAdd(gas, moreGas); overflow { 169 return 0, ErrGasUintOverflow 170 } 171 return gas, nil 172 } 173 func gasCreate2Eip3860(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 174 gas, err := memoryGasCost(mem, memorySize) 175 if err != nil { 176 return 0, err 177 } 178 size, overflow := stack.Back(2).Uint64WithOverflow() 179 if overflow || size > params.MaxInitCodeSize { 180 return 0, ErrGasUintOverflow 181 } 182 // Since size <= params.MaxInitCodeSize, these multiplication cannot overflow 183 moreGas := (params.InitCodeWordGas + params.Keccak256WordGas) * ((size + 31) / 32) 184 if gas, overflow = math.SafeAdd(gas, moreGas); overflow { 185 return 0, ErrGasUintOverflow 186 } 187 return gas, nil 188 } 189 190 func gasExpEIP158(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 191 expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) 192 193 var ( 194 gas = expByteLen * params.ExpByteEIP158 // no overflow check required. Max is 256 * ExpByte gas 195 overflow bool 196 ) 197 if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow { 198 return 0, ErrGasUintOverflow 199 } 200 return gas, nil 201 } 202 203 func gasCall(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 204 var ( 205 gas uint64 206 transfersValue = !stack.Back(2).IsZero() 207 address = common.Address(stack.Back(1).Bytes20()) 208 ) 209 if transfersValue && zvm.StateDB.Empty(address) { 210 gas += params.CallNewAccountGas 211 } 212 if transfersValue { 213 gas += params.CallValueTransferGas 214 } 215 memoryGas, err := memoryGasCost(mem, memorySize) 216 if err != nil { 217 return 0, err 218 } 219 var overflow bool 220 if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { 221 return 0, ErrGasUintOverflow 222 } 223 224 zvm.callGasTemp, err = callGas(contract.Gas, gas, stack.Back(0)) 225 if err != nil { 226 return 0, err 227 } 228 if gas, overflow = math.SafeAdd(gas, zvm.callGasTemp); overflow { 229 return 0, ErrGasUintOverflow 230 } 231 return gas, nil 232 } 233 234 func gasDelegateCall(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 235 gas, err := memoryGasCost(mem, memorySize) 236 if err != nil { 237 return 0, err 238 } 239 zvm.callGasTemp, err = callGas(contract.Gas, gas, stack.Back(0)) 240 if err != nil { 241 return 0, err 242 } 243 var overflow bool 244 if gas, overflow = math.SafeAdd(gas, zvm.callGasTemp); overflow { 245 return 0, ErrGasUintOverflow 246 } 247 return gas, nil 248 } 249 250 func gasStaticCall(zvm *ZVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 251 gas, err := memoryGasCost(mem, memorySize) 252 if err != nil { 253 return 0, err 254 } 255 zvm.callGasTemp, err = callGas(contract.Gas, gas, stack.Back(0)) 256 if err != nil { 257 return 0, err 258 } 259 var overflow bool 260 if gas, overflow = math.SafeAdd(gas, zvm.callGasTemp); overflow { 261 return 0, ErrGasUintOverflow 262 } 263 return gas, nil 264 }