Eip1014
1、create
通过CREATE关键字创建合约
// Create creates a new contract using code as deployment code.
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE)}
合约的地址被定义为Keccak256(call.address,nonce)
// CreateAddress creates an ethereum address given the bytes and the noncefunc CreateAddress(b common.Address, nonce uint64) common.Address {data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})return common.BytesToAddress(Keccak256(data)[12:])}
2、create2
通过CREATE2关键字创建合约
// Create2 creates a new contract using code as deployment code.//// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {codeAndHash := &codeAndHash{code: code}contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes())return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)}
根据call.address,32字节256位的salt:µs[3] denotes the third item on the machine’s stack,inithash :the runtime bytecode(合约的运行时代码)
keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]
// CreateAddress2 creates an ethereum address given the address bytes, initial// contract code hash and a salt.func CreateAddress2(b common.Address, salt [32]byte, inithash []byte) common.Address {return common.BytesToAddress(Keccak256([]byte{0xff}, b.Bytes(), salt[:], inithash)[12:])}
3、EIP-1014提出新的合约地址创建公式
以太坊CREATE通过Address和递增的Nonce值(避免双花)创建合约地址,一个地址无法在不同的时间得到相同的合约地址。
在EIP-1014中,提出了另外一个指令create2,接受的参数是一个salt和initcode(建立合约的运行时 ByteCodes)。这个指令会透过keccak256哈希,混和参数和主合约的地址来算出子合约地址。
EIP-1014在起初是基于State Channel的需求,主要是因为某些状况下可能还没有要和合约做互动,但需要先知道合约地址。因此只要是需要先知道地址,但没有要立即使用的合约就十分适合通过这个指令来建立。
例如对于交易所来说,替所有要入金的人建立私钥有管理上的问题,若透过智能合约则相对有弹性,但却不是所有申请地址的人都真的会入金,此时就适合利用这个指令先行取得地址,当真的有入金时再布署合约。
4 账户碰撞
3607
私钥账户和合约账户之间存在碰撞性
Any transaction where tx.sender has a CODEHASH != EMPTYCODEHASH MUST be rejected as invalid, where EMPTYCODEHASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470. The invalid transaction MUST be rejected by the client and not be included in a block. A block containing such a transaction MUST be considered invalid.
1.存在私钥账户和CREATE2合约账户碰撞的背景:不同私钥生成不同的公钥,从而生成不同的私钥账户;通过CREATE2不同salt值下同一个合约代码能够生成不同的合约账户。
假设存在一个160bit的冲突账户,考虑最小计算花销和存储花销,前80bit由遍历不同私钥生成,后80位通过遍历不同salt值生成。一共花费 2 ** 80 + 2 ** 80 =281的哈希值计算时间和存储空间,在当前的硬件条件以及电力下,需花费1年时间以及100亿美元可以计算得出。
2.CREATE合约账户和私钥账户的碰撞花销为2160,计算时间和存储成本都不可接受
计算281的成本为:281=2.4*10**25,在当前的硬件条件以及电力下,需花费1年时间以及100亿美元可以计算得出。