mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 15:47:21 +00:00
core, core/vm: implement EIP-7708
This commit is contained in:
parent
d2dbbe48c4
commit
50b7009201
6 changed files with 55 additions and 7 deletions
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -141,7 +142,10 @@ func CanTransfer(db vm.StateDB, addr common.Address, amount *uint256.Int) bool {
|
|||
}
|
||||
|
||||
// Transfer subtracts amount from sender and adds amount to recipient using the given Db
|
||||
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *uint256.Int) {
|
||||
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *uint256.Int, blockNumber *big.Int, rules *params.Rules) {
|
||||
db.SubBalance(sender, amount, tracing.BalanceChangeTransfer)
|
||||
db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer)
|
||||
if rules.IsAmsterdam && !amount.IsZero() {
|
||||
db.AddLog(types.EthTransferLog(blockNumber, sender, recipient, amount))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,11 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
//go:generate go run ../../rlp/rlpgen -type Log -out gen_log_rlp.go
|
||||
|
|
@ -62,3 +65,30 @@ type logMarshaling struct {
|
|||
BlockTimestamp hexutil.Uint64
|
||||
Index hexutil.Uint
|
||||
}
|
||||
|
||||
var (
|
||||
// system contract address
|
||||
EthTransferLogAddress = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
|
||||
// keccak256('Transfer(address,address,uint256)')
|
||||
EthTransferLogTopic0 = common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")
|
||||
)
|
||||
|
||||
// EthTransferLog creates and ETH transfer log according to EIP-7708.
|
||||
// Specification: https://eips.ethereum.org/EIPS/eip-7708
|
||||
func EthTransferLog(blockNumber *big.Int, from, to common.Address, amount *uint256.Int) *Log {
|
||||
topics := make([]common.Hash, 3)
|
||||
topics[0] = EthTransferLogTopic0
|
||||
copy(topics[1][common.HashLength-common.AddressLength:], from[:])
|
||||
copy(topics[2][common.HashLength-common.AddressLength:], to[:])
|
||||
amount32 := amount.Bytes32()
|
||||
data := make([]byte, 32)
|
||||
copy(data, amount32[:])
|
||||
return &Log{
|
||||
Address: EthTransferLogAddress,
|
||||
Topics: topics,
|
||||
Data: data,
|
||||
// This is a non-consensus field, but assigned here because
|
||||
// core/state doesn't know the current block number.
|
||||
BlockNumber: blockNumber.Uint64(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ type (
|
|||
// CanTransferFunc is the signature of a transfer guard function
|
||||
CanTransferFunc func(StateDB, common.Address, *uint256.Int) bool
|
||||
// TransferFunc is the signature of a transfer function
|
||||
TransferFunc func(StateDB, common.Address, common.Address, *uint256.Int)
|
||||
TransferFunc func(StateDB, common.Address, common.Address, *uint256.Int, *big.Int, *params.Rules)
|
||||
// GetHashFunc returns the n'th block hash in the blockchain
|
||||
// and is used by the BLOCKHASH EVM op code.
|
||||
GetHashFunc func(uint64) common.Hash
|
||||
|
|
@ -283,7 +283,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
}
|
||||
evm.StateDB.CreateAccount(addr)
|
||||
}
|
||||
evm.Context.Transfer(evm.StateDB, caller, addr, value)
|
||||
evm.Context.Transfer(evm.StateDB, caller, addr, value, evm.Context.BlockNumber, &evm.chainRules)
|
||||
|
||||
if isPrecompile {
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
||||
|
|
@ -560,7 +560,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
}
|
||||
gas = gas - consumed
|
||||
}
|
||||
evm.Context.Transfer(evm.StateDB, caller, address, value)
|
||||
evm.Context.Transfer(evm.StateDB, caller, address, value, evm.Context.BlockNumber, &evm.chainRules)
|
||||
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
// The contract is a scoped environment for this execution context only.
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ func TestEIP2200(t *testing.T) {
|
|||
|
||||
vmctx := BlockContext{
|
||||
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
|
||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
|
||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int, *big.Int, *params.Rules) {},
|
||||
}
|
||||
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ func TestCreateGas(t *testing.T) {
|
|||
statedb.Finalise(true)
|
||||
vmctx := BlockContext{
|
||||
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
|
||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
|
||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int, *big.Int, *params.Rules) {},
|
||||
BlockNumber: big.NewInt(0),
|
||||
}
|
||||
config := Config{}
|
||||
|
|
|
|||
|
|
@ -895,6 +895,13 @@ func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
}
|
||||
// Clear any leftover funds for the account being destructed.
|
||||
evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct)
|
||||
if evm.chainRules.IsAmsterdam && !balance.IsZero() {
|
||||
if this != beneficiary {
|
||||
evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, beneficiary, balance))
|
||||
} else {
|
||||
evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, common.Address{}, balance))
|
||||
}
|
||||
}
|
||||
evm.StateDB.SelfDestruct(this)
|
||||
|
||||
if tracer := evm.Config.Tracer; tracer != nil {
|
||||
|
|
@ -933,6 +940,13 @@ func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, erro
|
|||
evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct)
|
||||
evm.StateDB.AddBalance(beneficiary, balance, tracing.BalanceIncreaseSelfdestruct)
|
||||
}
|
||||
if evm.chainRules.IsAmsterdam && !balance.IsZero() {
|
||||
if this != beneficiary {
|
||||
evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, beneficiary, balance))
|
||||
} else if newContract {
|
||||
evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, common.Address{}, balance))
|
||||
}
|
||||
}
|
||||
|
||||
if tracer := evm.Config.Tracer; tracer != nil {
|
||||
if tracer.OnEnter != nil {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ var loopInterruptTests = []string{
|
|||
func TestLoopInterrupt(t *testing.T) {
|
||||
address := common.BytesToAddress([]byte("contract"))
|
||||
vmctx := BlockContext{
|
||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
|
||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int, *big.Int, *params.Rules) {},
|
||||
}
|
||||
|
||||
for i, tt := range loopInterruptTests {
|
||||
|
|
|
|||
Loading…
Reference in a new issue