Skip to content

Commit

Permalink
Fix contract creation aw (#68)
Browse files Browse the repository at this point in the history
* fix contract creation AccessWitness

* remove tracing

* remove tracing

* remove block2.rlp

* move repeated error message into its own error type
  • Loading branch information
jwasinger committed Feb 1, 2022
1 parent 2c896ba commit f89d0bc
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 7 deletions.
5 changes: 5 additions & 0 deletions core/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ var (
// have enough funds for transfer(topmost call only).
ErrInsufficientFundsForTransfer = errors.New("insufficient funds for transfer")

// ErrInsufficientBalanceWitness is returned if the transaction sender has enough
// funds to cover the transfer, but not enough to pay for witness access/modification
// costs for the transaction
ErrInsufficientBalanceWitness = errors.New("insufficient funds to cover witness access costs for transaction")

// ErrInsufficientFunds is returned if the total cost of executing a transaction
// is higher than the balance of the user's account.
ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value")
Expand Down
17 changes: 12 additions & 5 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,23 +317,24 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gas, gas)
}
if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber) {
var targetBalance, targetNonce, targetCodeSize, targetCodeKeccak, originBalance, originNonce []byte
var targetBalance, targetNonce, targetCodeSize, targetCodeKeccak, originBalance, originNonceBytes []byte

targetAddr := msg.To()
originAddr := msg.From()

statelessGasOrigin := st.evm.Accesses.TouchTxOriginAndComputeGas(originAddr.Bytes(), msg.Value().Sign() != 0)
if !tryConsumeGas(&st.gas, statelessGasOrigin) {
return nil, fmt.Errorf("insufficient gas to cover witness access costs")
return nil, ErrInsufficientBalanceWitness
}
originBalance = st.evm.StateDB.GetBalanceLittleEndian(originAddr)
originNonce = st.evm.StateDB.GetNonceLittleEndian(originAddr)
st.evm.Accesses.SetTxOriginTouchedLeaves(originAddr.Bytes(), originBalance, originNonce)
originNonce := st.evm.StateDB.GetNonce(originAddr)
originNonceBytes = st.evm.StateDB.GetNonceLittleEndian(originAddr)
st.evm.Accesses.SetTxOriginTouchedLeaves(originAddr.Bytes(), originBalance, originNonceBytes)

if msg.To() != nil {
statelessGasDest := st.evm.Accesses.TouchTxExistingAndComputeGas(targetAddr.Bytes(), msg.Value().Sign() != 0)
if !tryConsumeGas(&st.gas, statelessGasDest) {
return nil, fmt.Errorf("insufficient gas to cover witness access costs")
return nil, ErrInsufficientBalanceWitness
}
targetBalance = st.evm.StateDB.GetBalanceLittleEndian(*targetAddr)
targetNonce = st.evm.StateDB.GetNonceLittleEndian(*targetAddr)
Expand All @@ -343,7 +344,13 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
var codeSizeBytes [32]byte
binary.LittleEndian.PutUint64(codeSizeBytes[:8], codeSize)
st.evm.Accesses.SetTxExistingTouchedLeaves(targetAddr.Bytes(), targetBalance, targetNonce, targetCodeSize, targetCodeKeccak)
} else {
contractAddr := crypto.CreateAddress(originAddr, originNonce)
if !tryConsumeGas(&st.gas, st.evm.Accesses.TouchAndChargeContractCreateInit(contractAddr.Bytes(), msg.Value().Sign() != 0)) {
return nil, ErrInsufficientBalanceWitness
}
}

if st.gas < gas {
return nil, fmt.Errorf("Insufficient funds to cover witness access costs for transaction: have %d, want %d", st.gas, gas)
}
Expand Down
7 changes: 5 additions & 2 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,18 +474,21 @@ func (c *codeAndHash) Hash() common.Hash {
// create creates a new contract using code as deployment code.
func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) {
var zeroVerkleLeaf [32]byte
var balance []byte

if evm.chainConfig.IsCancun(evm.Context.BlockNumber) {
// note: assumption is that the nonce, code size, code hash
// will be 0x0000...00 at the target account before it is created
// otherwise would imply contract creation collision which is
// impossible if self-destruct is removed
balance := evm.StateDB.GetBalanceLittleEndian(address)
if evm.StateDB.GetBalance(address).Sign() != 0 {
balance = evm.StateDB.GetBalanceLittleEndian(address)
}

if value.Sign() != 0 {
evm.Accesses.SetLeafValuesContractCreateInit(address.Bytes()[:], zeroVerkleLeaf[:], nil)
} else {
evm.Accesses.SetLeafValuesContractCreateInit(address.Bytes()[:], zeroVerkleLeaf[:], balance[:])
evm.Accesses.SetLeafValuesContractCreateInit(address.Bytes()[:], zeroVerkleLeaf[:], balance)
}
}

Expand Down

0 comments on commit f89d0bc

Please sign in to comment.