24种增加gas的anti-pattern


2018年的「Towards Saving Money in Using Smart Contracts」paper中提出会使Ethereum上执行Smart contract所花费的gas变高的24种anti-pattern,此文章中分别说明此24种anti-pattern的形式与解决方法。

P1 — {swap(X), swap(X)} →delete, 1≤X≤16

  • swap(X)交换第一个和第(X+1)个stack中的元素
  • 两个连续的swap(X)等于对元素无作用,应该删除
  • deploy多花136 gas, execution多花6 gas

P2 — {M consecutive jumpdests} → {jumpdest}, M≥2

  • jumpdests是jump的目的地址
  • 一个jumpdests取代多个连续的jumpdests,因他们是相同操作
  • deploy多花68×(M−1)gas, execution多花(M−1)gas

P3 — {OP, pop} → {pop}, OP∈iszero,not,balance,calldataload,extcodesize,blockhash,mload,sload

  • OP会存取stack最上方的元素做运算,再push运算结果回stack
  • 如果再pop会把该元素移除,因此等于没有做过运算
  • deploy多花68 gas, execution多花(gas_cost of OP) gas

P4 — {OP, pop} → {pop, pop}, OP∈add,sub,mul,div,sdiv,mod,smod,exp,sigextnd,lt,gt,slt,sgt,eq,and,or,xor,byte,sha3

  • 类似P3,此类操作会pop stack最上方的2个元素做运算,再push运算结果回stack
  • P4相当于两个poppop
  • deploy多花0 gas, execution多花(gas_costgas_cost of OPOP) gas

P5 — {OP, pop} → {pop, pop, pop}, OP∈addmod,mulmod

  • 类似P3,此类操作会pop stack最上方的3个元素做运算,再push运算结果回stack
  • P5相当于三个pop
  • 此pattern取代后在deploy时会增加68 gas
  • 但在呼叫时OP会花8 gas,pop会花2 gas
  • 如果呼叫较多次还是叫efficient

P6 — {OP, pop} → delete, OP∈address,origin,caller,callvalue,calldatasize,codesize,gasprice,coinbase,timestamp,number,difficulty,gaslimit,pc,msize,gas

  • 类似P3,但此操作不会消耗stack中的元素,而是产生一个值之后push回stack
  • 因此此操作可以被删除
  • deploy多花136 gas, execution多花(gas_cost of OP) gas

P7 — {swap1, swap(X), OP, dup(X), OP} → {dup2, swap(X+1), OP, OP}, 2≤X≤15,OP∈add,mul,and,or,xor

  • dup(X)会复制stack中第X个元素并放至stack最上方
  • 设最上方三个元素为i0, i1, i2,X为2,OP为add
  • 因此其中一个swap可以被删除,因为OP(add)是可交换的(commutative)
  • deploy多花68 gas, execution多花3 gas

P8 — {OP, stop} → {stop}, OP can be any operation except jumpdest, jump, jumpi and all operations that change storage.

  • stop会终止smart contract的执行,且stack及memory会被清空
  • 假设OP是add,计算完add的结果后被stop,stack的元素被清空,等于没有操作过add
  • 另一方面如果OP跟control flow transfer或storage space相关,则无法删去

P9 — {swap(X), dup(X+1), swap1} → {dup1, swap(X+1)}, 1≤X≤15

  • 假设stack最上方两个元素为i0, i1,X为1
  • 执行此anti-pattern后stack元素个数加一,且最上方三个元素为i1, i0, i0
  • deploy多花68 gas, execution多花3 gas

P10 — {push(X), swap(Y), Y consecutive pops} → {Y consecutive pops, push(X)}, 1≤X≤32,1≤Y≤16

  • 假设stack最上方两个元素为i0,push1为i1,Y为1
  • 执行此anti-pattern后最上方的元素为i1
  • 因此其中anti-pattern可以被pops, push1取代。一个swap操作可以被移除
  • deploy多花68 gas, execution多花3 gas

P11 — {swap(X), X+1 consecutive pops} → {X+1 consecutive pops}, 1≤X≤16

  • 设X为1,因连续两个pop会消除stack上方两个元素,因此swap1无作用
  • deploy多花68 gas, execution多花3 gas

P12 — {swap(X), swap(Y), Y consecutive pops} → {X consecutive pops, swap(Y−X), (YX) consecutive pops}, 1≤X≤15,X<Y

  • 假设最上方三个元素为i0, i1, i2,X为1,Y为2
  • 经过此anti-pattern操过后,stack的元素减少2个,且最上方的元素为i1
  • deploy多花68 gas, execution多花3 gas

P13 — {X consecutive push(N)s, Y consecutive pops} → {(XY) consecutive push(N)s, if X>Y; (YX) consecutive pops, otherwise}, 1≤N≤32

  • pop接在push后的操作可以移除,因为两者互相抵消
  • 当push(N)多于如pop时,Y个pop及Y个push(N)可以被移除,deploy浪费136Y(68Yx2),execution浪费5Y(3Y+2Y)
  • 否则,X个push(N)及X个pop可以被移除,deploy浪费136X(68Xx2),execution浪费5X(3X+2X)

P14 — {X consecutive dup(N)s, Y consecutive pops} → {(XY) consecutive dup(N)s, ifX>Y; (YX) consecutive pops, otherwise}, 1≤N≤16

  • 与P13类似,dup(N)的作用与pop会互相抵消
  • 当X>Y时,deploy浪费136Y(68Yx2),execution浪费5Y(3Y+2Y)
  • 反之X≤Y时,deploy浪费136X(68Xx2),execution浪费5X(3X+2X)

P15 — {dup(X), swap(X)} → {dup(X)}, 1≤X≤16

  • 若X为1,dup1第一个stack上的item,再swap并没有效果
  • deploy多花68 gas, execution多花3 gas

P16 — {swap1,swap2,…,swap(X),swap(X−1),…,swap1, X-1 consecutive pops} → {X-1 consecutive pops, swap1}, 2≤X≤16

  • 假设最上方三个元素为i0, i1, i2,X为2
  • 经过此anti-pattern操过后,stack的元素减少1个,且最上方的两个元素为i2, i1
  • 若先pop在swap之前,则需要较少次的swap
  • deploy多花68 gas, execution多花3 gas

P17 — {$swap$1, OP} → {OP}, OP∈add,mul,and,or,xor

  • 因为OP是可交换的(commutative),所以swap无效
  • deploy多花68 gas, execution多花3 gas

P18 — {OP, iszero, iszero} → {OP}, OP∈lt,gt,slt,sgt,eq

  • 例如: gt的结果是0或1,取决于stack的第一个元素是否大于第二个元素
  • 两个连续的iszero不会改变OP的结果
  • deploy多花136 gas, execution多花6 gas

P19 — {N consecutive push(X),M consecutive swap(Y)} → {N consecutive push(X)}, Y<N,1≤X≤32,1≤Y≤16

  • push(X)是唯一有运算元(operand)的运算
  • push(X), push(X), swap(1)可以最佳化为push(X), push(X)
  • deploy多花68M gas, execution多花3M gas

P20 — {push(X), swap(Y), push(M), swap1} → {push(M), push(X), swap(Y+1)}, 1≤X≤32,1≤Y≤15,1≤M≤32

  • 因P19的原因,所以一个swap可以被移除
  • deploy多花68 gas, execution多花3 gas

P21 — {consecutive Xpush(N), dup(Y), swap(Z)} → {combination of Xpush(N) and dup(M)}, Y<=X,Z<=X,M<=X,1≤N≤32,1≤Y≤16,1≤Z≤16,1≤M≤16

  • 因P19的原因,所以一个swap可以被移除
  • deploy多花68 gas, execution多花3 gas

P22 — {swap(N), M consecutive OPs,(N+M) consecutive and same OP′} → {M consecutive OPs,(N+M) consecutive and same OP'}, OP∈push(X),dup(Y), OP′∈add,mul,and,or,xor,1≤X≤32,1≤N≤16,1≤Y≤16

  • 因OP′是可交换的(commutative),且push(X)和dup(Y)增加stack数1,swap(N)可以被移除
  • deploy多花68 gas, execution多花3 gas

P23 — {dup1, swap(X), dup2, swap1} → {dup1, dup2, swap(X+1)}, 1≤X≤15

  • 假设stack最上方两个元素为i0, i1,X为2
  • 执行此anti-pattern后stack数增加2,最上方4个元素为i1,i0,i0,i0
  • deploy多花68 gas, execution多花3 gas

P24 — {dup(X), swap(X−1), swap1, dup(X), swap1} → {dup(X), dup1, swap(X), swap2}, 3≤X≤16

  • 假设stack最上方两个元素为i0, i1, i2,X为3
  • 执行此anti-pattern后stack数增加2,最上方4个元素为i0,i2,i1,i2,i2
  • deploy多花68 gas, execution多花3 gas

本文链接地址:https://www.wwsww.cn/jishu/10360.html
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。