gas_table.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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. package vm
  17. import (
  18. gmath "math"
  19. "math/big"
  20. "github.com/ethereum/go-ethereum/common"
  21. "github.com/ethereum/go-ethereum/common/math"
  22. "github.com/ethereum/go-ethereum/params"
  23. )
  24. // memoryGasCosts calculates the quadratic gas for memory expansion. It does so
  25. // only for the memory region that is expanded, not the total memory.
  26. func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
  27. // The maximum that will fit in a uint64 is max_word_count - 1
  28. // anything above that will result in an overflow.
  29. if newMemSize > gmath.MaxUint64-32 {
  30. return 0, errGasUintOverflow
  31. }
  32. if newMemSize == 0 {
  33. return 0, nil
  34. }
  35. newMemSizeWords := toWordSize(newMemSize)
  36. newMemSize = newMemSizeWords * 32
  37. if newMemSize > uint64(mem.Len()) {
  38. square := newMemSizeWords * newMemSizeWords
  39. linCoef := newMemSizeWords * params.MemoryGas
  40. quadCoef := square / params.QuadCoeffDiv
  41. newTotalFee := linCoef + quadCoef
  42. fee := newTotalFee - mem.lastGasCost
  43. mem.lastGasCost = newTotalFee
  44. return fee, nil
  45. }
  46. return 0, nil
  47. }
  48. func constGasFunc(gas uint64) gasFunc {
  49. return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  50. return gas, nil
  51. }
  52. }
  53. func gasCalldataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  54. gas, err := memoryGasCost(mem, memorySize)
  55. if err != nil {
  56. return 0, err
  57. }
  58. var overflow bool
  59. if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
  60. return 0, errGasUintOverflow
  61. }
  62. words, overflow := bigUint64(stack.Back(2))
  63. if overflow {
  64. return 0, errGasUintOverflow
  65. }
  66. if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
  67. return 0, errGasUintOverflow
  68. }
  69. if gas, overflow = math.SafeAdd(gas, words); overflow {
  70. return 0, errGasUintOverflow
  71. }
  72. return gas, nil
  73. }
  74. func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  75. var (
  76. y, x = stack.Back(1), stack.Back(0)
  77. val = evm.StateDB.GetState(contract.Address(), common.BigToHash(x))
  78. )
  79. // This checks for 3 scenario's and calculates gas accordingly
  80. // 1. From a zero-value address to a non-zero value (NEW VALUE)
  81. // 2. From a non-zero value address to a zero-value address (DELETE)
  82. // 3. From a non-zero to a non-zero (CHANGE)
  83. if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) {
  84. // 0 => non 0
  85. return params.SstoreSetGas, nil
  86. } else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
  87. evm.StateDB.AddRefund(new(big.Int).SetUint64(params.SstoreRefundGas))
  88. return params.SstoreClearGas, nil
  89. } else {
  90. // non 0 => non 0 (or 0 => 0)
  91. return params.SstoreResetGas, nil
  92. }
  93. }
  94. func makeGasLog(n uint64) gasFunc {
  95. return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  96. requestedSize, overflow := bigUint64(stack.Back(1))
  97. if overflow {
  98. return 0, errGasUintOverflow
  99. }
  100. gas, err := memoryGasCost(mem, memorySize)
  101. if err != nil {
  102. return 0, err
  103. }
  104. if gas, overflow = math.SafeAdd(gas, params.LogGas); overflow {
  105. return 0, errGasUintOverflow
  106. }
  107. if gas, overflow = math.SafeAdd(gas, n*params.LogTopicGas); overflow {
  108. return 0, errGasUintOverflow
  109. }
  110. var memorySizeGas uint64
  111. if memorySizeGas, overflow = math.SafeMul(requestedSize, params.LogDataGas); overflow {
  112. return 0, errGasUintOverflow
  113. }
  114. if gas, overflow = math.SafeAdd(gas, memorySizeGas); overflow {
  115. return 0, errGasUintOverflow
  116. }
  117. return gas, nil
  118. }
  119. }
  120. func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  121. var overflow bool
  122. gas, err := memoryGasCost(mem, memorySize)
  123. if err != nil {
  124. return 0, err
  125. }
  126. if gas, overflow = math.SafeAdd(gas, params.Sha3Gas); overflow {
  127. return 0, errGasUintOverflow
  128. }
  129. wordGas, overflow := bigUint64(stack.Back(1))
  130. if overflow {
  131. return 0, errGasUintOverflow
  132. }
  133. if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Sha3WordGas); 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. func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  142. gas, err := memoryGasCost(mem, memorySize)
  143. if err != nil {
  144. return 0, err
  145. }
  146. var overflow bool
  147. if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
  148. return 0, errGasUintOverflow
  149. }
  150. wordGas, overflow := bigUint64(stack.Back(2))
  151. if overflow {
  152. return 0, errGasUintOverflow
  153. }
  154. if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow {
  155. return 0, errGasUintOverflow
  156. }
  157. if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
  158. return 0, errGasUintOverflow
  159. }
  160. return gas, nil
  161. }
  162. func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  163. gas, err := memoryGasCost(mem, memorySize)
  164. if err != nil {
  165. return 0, err
  166. }
  167. var overflow bool
  168. if gas, overflow = math.SafeAdd(gas, gt.ExtcodeCopy); overflow {
  169. return 0, errGasUintOverflow
  170. }
  171. wordGas, overflow := bigUint64(stack.Back(3))
  172. if overflow {
  173. return 0, errGasUintOverflow
  174. }
  175. if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow {
  176. return 0, errGasUintOverflow
  177. }
  178. if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
  179. return 0, errGasUintOverflow
  180. }
  181. return gas, nil
  182. }
  183. func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  184. var overflow bool
  185. gas, err := memoryGasCost(mem, memorySize)
  186. if err != nil {
  187. return 0, errGasUintOverflow
  188. }
  189. if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
  190. return 0, errGasUintOverflow
  191. }
  192. return gas, nil
  193. }
  194. func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  195. var overflow bool
  196. gas, err := memoryGasCost(mem, memorySize)
  197. if err != nil {
  198. return 0, errGasUintOverflow
  199. }
  200. if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
  201. return 0, errGasUintOverflow
  202. }
  203. return gas, nil
  204. }
  205. func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  206. var overflow bool
  207. gas, err := memoryGasCost(mem, memorySize)
  208. if err != nil {
  209. return 0, errGasUintOverflow
  210. }
  211. if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
  212. return 0, errGasUintOverflow
  213. }
  214. return gas, nil
  215. }
  216. func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  217. var overflow bool
  218. gas, err := memoryGasCost(mem, memorySize)
  219. if err != nil {
  220. return 0, err
  221. }
  222. if gas, overflow = math.SafeAdd(gas, params.CreateGas); overflow {
  223. return 0, errGasUintOverflow
  224. }
  225. return gas, nil
  226. }
  227. func gasBalance(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  228. return gt.Balance, nil
  229. }
  230. func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  231. return gt.ExtcodeSize, nil
  232. }
  233. func gasSLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  234. return gt.SLoad, nil
  235. }
  236. func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  237. expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8)
  238. var (
  239. gas = expByteLen * gt.ExpByte // no overflow check required. Max is 256 * ExpByte gas
  240. overflow bool
  241. )
  242. if gas, overflow = math.SafeAdd(gas, GasSlowStep); overflow {
  243. return 0, errGasUintOverflow
  244. }
  245. return gas, nil
  246. }
  247. func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  248. var (
  249. gas = gt.Calls
  250. transfersValue = stack.Back(2).Sign() != 0
  251. address = common.BigToAddress(stack.Back(1))
  252. eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber)
  253. )
  254. if eip158 {
  255. if evm.StateDB.Empty(address) && transfersValue {
  256. gas += params.CallNewAccountGas
  257. }
  258. } else if !evm.StateDB.Exist(address) {
  259. gas += params.CallNewAccountGas
  260. }
  261. if transfersValue {
  262. gas += params.CallValueTransferGas
  263. }
  264. memoryGas, err := memoryGasCost(mem, memorySize)
  265. if err != nil {
  266. return 0, err
  267. }
  268. var overflow bool
  269. if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
  270. return 0, errGasUintOverflow
  271. }
  272. cg, err := callGas(gt, contract.Gas, gas, stack.Back(0))
  273. if err != nil {
  274. return 0, err
  275. }
  276. // Replace the stack item with the new gas calculation. This means that
  277. // either the original item is left on the stack or the item is replaced by:
  278. // (availableGas - gas) * 63 / 64
  279. // We replace the stack item so that it's available when the opCall instruction is
  280. // called. This information is otherwise lost due to the dependency on *current*
  281. // available gas.
  282. stack.data[stack.len()-1] = new(big.Int).SetUint64(cg)
  283. if gas, overflow = math.SafeAdd(gas, cg); overflow {
  284. return 0, errGasUintOverflow
  285. }
  286. return gas, nil
  287. }
  288. func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  289. gas := gt.Calls
  290. if stack.Back(2).Sign() != 0 {
  291. gas += params.CallValueTransferGas
  292. }
  293. memoryGas, err := memoryGasCost(mem, memorySize)
  294. if err != nil {
  295. return 0, err
  296. }
  297. var overflow bool
  298. if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
  299. return 0, errGasUintOverflow
  300. }
  301. cg, err := callGas(gt, contract.Gas, gas, stack.Back(0))
  302. if err != nil {
  303. return 0, err
  304. }
  305. // Replace the stack item with the new gas calculation. This means that
  306. // either the original item is left on the stack or the item is replaced by:
  307. // (availableGas - gas) * 63 / 64
  308. // We replace the stack item so that it's available when the opCall instruction is
  309. // called. This information is otherwise lost due to the dependency on *current*
  310. // available gas.
  311. stack.data[stack.len()-1] = new(big.Int).SetUint64(cg)
  312. if gas, overflow = math.SafeAdd(gas, cg); overflow {
  313. return 0, errGasUintOverflow
  314. }
  315. return gas, nil
  316. }
  317. func gasReturn(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  318. return memoryGasCost(mem, memorySize)
  319. }
  320. func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  321. var gas uint64
  322. // EIP150 homestead gas reprice fork:
  323. if evm.ChainConfig().IsEIP150(evm.BlockNumber) {
  324. gas = gt.Suicide
  325. var (
  326. address = common.BigToAddress(stack.Back(0))
  327. eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber)
  328. )
  329. if eip158 {
  330. // if empty and transfers value
  331. if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
  332. gas += gt.CreateBySuicide
  333. }
  334. } else if !evm.StateDB.Exist(address) {
  335. gas += gt.CreateBySuicide
  336. }
  337. }
  338. if !evm.StateDB.HasSuicided(contract.Address()) {
  339. evm.StateDB.AddRefund(new(big.Int).SetUint64(params.SuicideRefundGas))
  340. }
  341. return gas, nil
  342. }
  343. func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  344. gas, err := memoryGasCost(mem, memorySize)
  345. if err != nil {
  346. return 0, err
  347. }
  348. var overflow bool
  349. if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow {
  350. return 0, errGasUintOverflow
  351. }
  352. cg, err := callGas(gt, contract.Gas, gas, stack.Back(0))
  353. if err != nil {
  354. return 0, err
  355. }
  356. // Replace the stack item with the new gas calculation. This means that
  357. // either the original item is left on the stack or the item is replaced by:
  358. // (availableGas - gas) * 63 / 64
  359. // We replace the stack item so that it's available when the opCall instruction is
  360. // called.
  361. stack.data[stack.len()-1] = new(big.Int).SetUint64(cg)
  362. if gas, overflow = math.SafeAdd(gas, cg); overflow {
  363. return 0, errGasUintOverflow
  364. }
  365. return gas, nil
  366. }
  367. func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  368. return GasFastestStep, nil
  369. }
  370. func gasSwap(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  371. return GasFastestStep, nil
  372. }
  373. func gasDup(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
  374. return GasFastestStep, nil
  375. }