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
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。