内容简介:之前由于某种原因想要通过在合约里面计算它创建的下一个合约的地址,用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---------------
}
}
}
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Writing Apache Modules with Perl and C
Lincoln Stein、Doug MacEachern / O'Reilly Media, Inc. / 1999-03 / USD 39.95
Apache is the most popular Web server on the Internet because it is free, reliable, and extensible. The availability of the source code and the modular design of Apache makes it possible to extend Web......一起来看看 《Writing Apache Modules with Perl and C》 这本书的介绍吧!