DTeam 技术日志

Doer、Delivery、Dream

代码即金钱:Solidity 7 大费钱反模式

胡键 Posted at — Oct 2, 2018 阅读

天下没有免费的合约,这是以太坊开发者的常识。既然EVM上处处要真金白银,那么能替雇主节约钱自然就成了优秀开发者的指标之一。这篇论文的出现恰好为广大开发者提供了指引。

总的来讲,作为开发者,我们需要牢记下面几个事实:

费钱反模式

论文给出了7个浪费gas严重的反模式,作为开发者来讲,需引以为戒。这个7个模式被划分为两大类:

模式1:死代码

function p1 ( uint x ){
    if ( x > 5)
        if ( x*x < 20)
            XXX
}

显然,若x>5,x*x<20将永远无法成立。其危害在于增加了合约的字节码大小。

模式2:模糊谓词(opaque predicate)

function p2 ( uint x ){
    if ( x > 5)
        if ( x > 1)
            XXX
}

很明显,x>1是多余的,它的危害跟上面一样,增加了合约大小。

模式3:循环内昂贵的操作

uint sum = 0;
function p3 ( uint x ){
    for ( uint i = 0 ; i < x ; i++)
        sum += i;
}

此处的对于初学者就没有那么明显了。这里的sum是状态变量,存储于storage。由上可知,操作storage为昂贵操作,既然如此,换成下面的代码将节约不少gas:

uint sum = 0;
function p3 ( uint x ){
    unit localSum = sum;
    for ( uint i = 0 ; i < x ; i++)
        localSum += i;
    sum = localSum;
}

模式4:循环的输出是常数

function p4 () returns ( uint ){
    uint sum = 0;
    for ( uint i = 1 ; i <= 100 ; i++)
        sum += i;
    return sum;
}

在此,返回5050将避免昂贵的循环操作。

模式5:循环融合(loop fusion)

function p5 ( uint x ){
    uint m = 0;
    uint v = 0;
    for ( uint i = 0 ; i < x ; i++)
        m += i;
    for ( uint j = 0 ; j < x ; j++)
        v -= j;
}

显然,两个循环可以结合在一起,避免一次多余的循环。

模式6:循环内重复计算

uint x = 1;
uint y = 2;
function p6 ( uint k ){
    uint sum = 0;
    for ( uint i = 1 ; i <= k ; i++)
        sum = sum + x + y; 
}

这里的循环每次都重新计算了一次(x+y),更何况这两个还是状态变量,让整个gas的消耗更加雪上加霜。改进:

uint x = 1;
uint y = 2;
function p6 ( uint k ){
    unit tmp = x + y;
    uint sum = 0;
    for ( uint i = 1 ; i <= k ; i++)
        sum = sum + tmp; 
}

模式7:循环内单向输出比较(Comparison with unilateral outcome in a loop)

function p7 ( uint x , uint y ) returns ( uint ){
    for ( int i = 0 ; i < 100 ; i++)
        if ( x > 0 ) y+=x;
    return y;
}

这里的问题在于,循环内重复条件的比较,改成下面的代码将避免这种开销:

function p7 ( uint x , uint y ) returns ( uint ){
    if ( x <= 0 ) return y;
    for ( int i = 0 ; i < 100 ; i++)
        y+=x;
    return y;
}

总结

由于以太坊上跑代码花的是实实在在的Money,作为开发者,我们从来不曾如此的重要!归根结底一句话,开发的好日子来啦!

但是,这里有一个前提:写出既好又省钱的代码来。论文中给出的例子只是起点,帮助大家打开思路,至于其他就要靠各位自己总结和发现了。

参考

Under-Optimized Smart Contracts Devour Your Money


相关文章