美文网首页Dapp开发0岁的产品经理HiBlock区块链社区
代码即金钱:Solidity 7 大费钱反模式

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

作者: 胡键 | 来源:发表于2018-10-02 14:08 被阅读210次

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

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

    • 合约编译后的字节码大小会影响gas。
    • 变量的位置和gas消耗的关系:stack < memory < storage。
    • 区块链相关的操作超级昂贵,如创建合约。
    • 每行代码的执行都要钱,能精简就精简。

    费钱反模式

    论文给出了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

    相关文章

      网友评论

        本文标题:代码即金钱:Solidity 7 大费钱反模式

        本文链接:https://www.haomeiwen.com/subject/krnooftx.html