[技术交流] 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---------------
        }
    }
}

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

查看所有标签

猜你喜欢:

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

CSS揭秘

CSS揭秘

[希] Lea Verou / CSS魔法 / 人民邮电出版社 / 2016-4 / 99.00元

本书是一本注重实践的教程,作者为我们揭示了 47 个鲜为人知的 CSS 技巧,主要内容包括背景与边框、形状、 视觉效果、字体排印、用户体验、结构与布局、过渡与动画等。本书将带领读者循序渐进地探寻更优雅的解决方案,攻克每天都会遇到的各种网页样式难题。 本书的读者对象为前端工程师、网页开发人员。一起来看看 《CSS揭秘》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具