mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-28 07:36:44 +00:00
core/vm: implemented create2
This commit is contained in:
parent
797172bfe8
commit
4eae3cc25c
6 changed files with 74 additions and 4 deletions
|
|
@ -236,7 +236,8 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
|
|||
vmerr error
|
||||
)
|
||||
if contractCreation {
|
||||
ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
|
||||
createAddressFn := vm.CreateAddressFn(st.evm.ChainConfig(), st.evm.BlockNumber, sender.Address(), st.state.GetNonce(sender.Address()), st.data)
|
||||
ret, _, st.gas, vmerr = evm.Create(sender, createAddressFn, st.data, st.gas, st.value)
|
||||
} else {
|
||||
// Increment the nonce for the next transaction
|
||||
st.state.SetNonce(sender.Address(), st.state.GetNonce(sender.Address())+1)
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
|||
}
|
||||
|
||||
// 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) {
|
||||
func (evm *EVM) Create(caller ContractRef, createAddress addressCreationFn, code []byte, gas uint64, value *big.Int) (ret []byte, _ common.Address, leftOverGas uint64, err error) {
|
||||
if evm.vmConfig.NoRecursion && evm.depth > 0 {
|
||||
return nil, common.Address{}, gas, nil
|
||||
}
|
||||
|
|
@ -309,7 +309,9 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
|
|||
evm.StateDB.SetNonce(caller.Address(), nonce+1)
|
||||
|
||||
snapshot := evm.StateDB.Snapshot()
|
||||
contractAddr = crypto.CreateAddress(caller.Address(), nonce)
|
||||
|
||||
contractAddr := createAddress()
|
||||
|
||||
evm.StateDB.CreateAccount(contractAddr)
|
||||
if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
|
||||
evm.StateDB.SetNonce(contractAddr, 1)
|
||||
|
|
@ -361,3 +363,5 @@ func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
|
|||
|
||||
// Interpreter returns the EVM interpreter
|
||||
func (evm *EVM) Interpreter() *Interpreter { return evm.interpreter }
|
||||
|
||||
type addressCreationFn func() common.Address
|
||||
|
|
|
|||
|
|
@ -541,6 +541,18 @@ func opGas(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func CreateAddressFn(chainConfig *params.ChainConfig, blockNumber *big.Int, senderAddress common.Address, nonce uint64, input []byte) func() common.Address {
|
||||
if chainConfig.IsMetropolis(blockNumber) {
|
||||
return func() common.Address {
|
||||
return common.BytesToAddress(crypto.Keccak256(senderAddress.Bytes(), crypto.Keccak256(input))[12:])
|
||||
}
|
||||
} else {
|
||||
return func() common.Address {
|
||||
return crypto.CreateAddress(senderAddress, nonce)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
var (
|
||||
value = stack.pop()
|
||||
|
|
@ -552,8 +564,46 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
|
|||
gas -= gas / 64
|
||||
}
|
||||
|
||||
createAddressFn := CreateAddressFn(evm.ChainConfig(), evm.BlockNumber, contract.Address(), evm.StateDB.GetNonce(contract.Address()), input)
|
||||
|
||||
contract.UseGas(gas)
|
||||
_, addr, returnGas, suberr := evm.Create(contract, input, gas, value)
|
||||
_, addr, returnGas, suberr := evm.Create(contract, createAddressFn, input, gas, value)
|
||||
// Push item on the stack based on the returned error. If the ruleset is
|
||||
// homestead we must check for CodeStoreOutOfGasError (homestead only
|
||||
// rule) and treat as an error, if the ruleset is frontier we must
|
||||
// ignore this error and pretend the operation was successful.
|
||||
if evm.ChainConfig().IsHomestead(evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas {
|
||||
stack.push(new(big.Int))
|
||||
} else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
|
||||
stack.push(new(big.Int))
|
||||
} else {
|
||||
stack.push(addr.Big())
|
||||
}
|
||||
contract.Gas += returnGas
|
||||
|
||||
evm.interpreter.intPool.put(value, offset, size)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCreate2(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
var (
|
||||
value = stack.pop()
|
||||
salt = stack.pop()
|
||||
offset, size = stack.pop(), stack.pop()
|
||||
input = memory.Get(offset.Int64(), size.Int64())
|
||||
gas = contract.Gas
|
||||
)
|
||||
if evm.ChainConfig().IsEIP150(evm.BlockNumber) {
|
||||
gas -= gas / 64
|
||||
}
|
||||
|
||||
createAddress := func() common.Address {
|
||||
return common.BytesToAddress(crypto.Keccak256(contract.Address().Bytes(), salt.Bytes(), crypto.Keccak256(input))[12:])
|
||||
}
|
||||
|
||||
contract.UseGas(gas)
|
||||
_, addr, returnGas, suberr := evm.Create(contract, createAddress, input, gas, value)
|
||||
// Push item on the stack based on the returned error. If the ruleset is
|
||||
// homestead we must check for CodeStoreOutOfGasError (homestead only
|
||||
// rule) and treat as an error, if the ruleset is frontier we must
|
||||
|
|
|
|||
|
|
@ -891,6 +891,15 @@ func NewFrontierInstructionSet() [256]operation {
|
|||
writes: true,
|
||||
clearsReturndata: true,
|
||||
},
|
||||
CREATE2: {
|
||||
execute: opCreate2,
|
||||
gasCost: gasCreate,
|
||||
validateStack: makeStackFunc(4, 1),
|
||||
memorySize: memoryCreate2,
|
||||
valid: true,
|
||||
writes: true,
|
||||
clearsReturndata: true,
|
||||
},
|
||||
CALL: {
|
||||
execute: opCall,
|
||||
gasCost: gasCall,
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ func memoryCreate(stack *Stack) *big.Int {
|
|||
return calcMemSize(stack.Back(1), stack.Back(2))
|
||||
}
|
||||
|
||||
func memoryCreate2(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(2), stack.Back(3))
|
||||
}
|
||||
|
||||
func memoryCall(stack *Stack) *big.Int {
|
||||
x := calcMemSize(stack.Back(5), stack.Back(6))
|
||||
y := calcMemSize(stack.Back(3), stack.Back(4))
|
||||
|
|
|
|||
|
|
@ -208,6 +208,8 @@ const (
|
|||
DELEGATECALL
|
||||
STATIC_CALL
|
||||
|
||||
CREATE2 OpCode = 0xfb
|
||||
|
||||
REVERT = 0xfd
|
||||
SELFDESTRUCT = 0xff
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue