[技术交流] solidity 汇编实现合约地址的计算器

栏目: 编程语言 · 发布时间: 6年前

内容简介:之前由于某种原因想要通过在合约里面计算它创建的下一个合约的地址,用solidity实现起来要消耗6000+ gas,所以就花了点时间用汇编重写了下,效率非常高,有需要的可以拿去gist:

之前由于某种原因想要通过在合约里面计算它创建的下一个合约的地址,用solidity实现起来要消耗6000+ gas,所以就花了点时间用汇编重写了下,效率非常高,有需要的可以拿去

gist: https://gist.github.com/yanche/00f5e7deef4d361eadf3058b2e99a816

pragma solidity ^0.4.24;

library ContractAddrCalculator {
    // author: yanche @ https://github.com/yanche/eth_contract_addr_calc

    // NOTE this program works as long as nonce is less than 33 bytes
    // which is 2**(8*33), almost impossible for a contract to create
    // so many contracts, also uint256 is only 32bytes
    // GAS COST
    // nonce = 1 => 256
    //         0x80 => 389
    //         0x0102 => 429
    // above is example of assembly execution cost, plus 280 other execution cost per tx
    // complaint: 1. the compiler's control flow analysis sucks
    //            2. no opcode for left/right shift, has to use a combination of exp and mul, causes a lot more gas usage
    function calc(address baseAddr, uint256 nonce) public view returns(address addr) {
        assembly {
            // ---------------START: genAddr---------------
            // TODO: load from parameters
            // A N
            baseAddr  /* dup3 */
            nonce     /* dup3 */

                // ---------------START: rlpEncodeNonce---------------
                // N
                dup1
                dup1 /* to fix the compiler bug on stack height calc around "jump" opcode, have to manually maintain the stack height */
                label_not0
                // N N N label_not0
                jumpi
                pop
                pop
                0x80
                1
                // 0x80 1
                label_rlpEnd
                // 0x80 1 label_rlpEnd
                jump
                label_not0:
                // N N
                dup1
                0x7f
                lt
                // N N N>0x7f
                label_rlpGt0x7f
                jumpi
                // N N
                pop
                1
                label_rlpEnd
                // N 1 label_rlpEnd
                jump
                label_rlpGt0x7f:
                // N N
                pop

                    // ---------------START: countStackTopInBytes---------------
                    // push the integer represents the byte count of stack-top number on to stak
                    // example with STACK
                    // 0x00 => 0x00 0x01
                    // 0xf0 => 0xf0 0x01
                    // 0x0102 => 0x0102 0x02
                    // X
                    0
                    // X 0
                    dup2
                    // X 0 X
                    label_loop:
                    swap1
                    // X X 0
                    1
                    add
                    // X X 1
                    swap1
                    // X 1 X
                    256
                    // X 1 X 256
                    swap1
                    // X 1 256 X
                    div
                    // X 1 X>>8
                    dup1
                    // X 1 X>>8 X>>8
                    label_loop
                    // X 1 X>>8 X>>8 label_loop
                    jumpi
                    // X 1 X>>8
                    pop
                    // X 1
                    // ---------------END: countStackTopInBytes---------------

                // N N_len
                swap1
                // N_len N
                dup2
                // N_len N N_len
                dup1
                0x80
                add
                // N_len N N_len rlpNHead
                swap1
                // N_len N rlpNHead N_len
                256
                exp
                // N_len N rlpNHead 256^N_len
                mul
                or
                // N_len rlpN
                swap1
                // rlpN N_len
                1
                add
                // rlpN rlpN_byte_length(N_len + 1)
                label_rlpEnd:
                // rlpN rlpN_byte_length
                // ---------------END: rlpEncodeNonce---------------

            // A rlpN rlpN_len
            dup1
            // A rlpN rlpN_len rlpN_len
            22
            add
            // A rlpN rlpN_len rlp_total_len
            swap3
            // rlp_total_len rlpN rlpN_len A
            dup2
            // rlp_total_len rlpN rlpN_len A rlpN_len
            0xd5 /* 0xd5 = 0xc0 + 21(the byte length of address rlp encoding) */
            // rlp_total_len rlpN rlpN_len A rlpN_len 0xd5
            add
            // rlp_total_len rlpN rlpN_len A rlp_head
            0x0100
            mul
            // rlp_total_len rlpN rlpN_len A rlp_head<<8
            0x94 /* 0x94 = 0x80 + 20 */
            or
            // rlp_total_len rlpN rlpN_len A rlp_head.0x94
            0x010000000000000000000000000000000000000000
            mul
            // rlp_total_len rlpN rlpN_len A rlp_head.0x94<<20bytes
            or
            // rlp_total_len rlpN rlpN_len rlp_head.rlpA
            swap1
            // rlp_total_len rlpN rlp_head.rlpA rlpN_len
            256
            exp
            // rlp_total_len rlpN rlp_head.rlpA 256^rlpN_len
            mul
            or
            // rlp_total_len rlp_head.rlpA.rlpN
            dup2
            0x80
            add
            // rlp_total_len rlp_head.rlpA.rlpN rlp_total_len+0x80
            mstore
            // rlp_total_len
            // memory 0xa0: rlp_head.rlpA.rlpN
            0xa0
            sha3
            // sha3_rlp
            0xffffffffffffffffffffffffffffffffffffffff
            and
            // sha3_rlp(last 20bytes)
            =:addr  /* equivalent to swap1 pop */
            // ---------------END: genAddr---------------
        }
    }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

平台转型

平台转型

陈威如、王诗一、余卓轩(统筹) / 中信出版社 / 2016-1-10 / 58

《平台战略》续篇,陈威如等关于企业平台转型最新力作! 平台带来的商业革命已改写了现在及未来的企业生存规则,而这股浪潮已经从互联网行业漫延到了其他多种行业之中!如果说,过去10 年是平台商业模式在互联网行业的爆发期,那未来10 年,将是平台商业模式在传统行业转型应用上的黄金时代。 平台思维不再是互联网行业的专用词,它可以用来解构价值链,可以被运用到组织架构的设计中,更能够帮助企业升级竞争......一起来看看 《平台转型》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具