Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 74 additions & 10 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/filtermaps"
Expand Down Expand Up @@ -71,6 +73,7 @@ type SimulatedBackend struct {

database ethdb.Database // In memory database to store our testing data
blockchain *core.BlockChain // Ethereum blockchain to handle the consensus
engine consensus.Engine // Consensus engine for block generation

mu sync.Mutex
pendingBlock *types.Block // Currently pending block that will be imported on request
Expand All @@ -87,17 +90,32 @@ type SimulatedBackend struct {
// and uses a simulated blockchain for testing purposes.
// A simulated backend always uses chainID 1337.
func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc types.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
return NewSimulatedBackendWithConfig(database, alloc, gasLimit, params.AllEthashProtocolChanges)
}

// NewSimulatedBackendWithConfig creates a new binding backend based on the given database
// and chain config. Use this when you need features from newer EVM versions (e.g., PUSH0 from Shanghai).
func NewSimulatedBackendWithConfig(database ethdb.Database, alloc types.GenesisAlloc, gasLimit uint64, config *params.ChainConfig) *SimulatedBackend {
genesis := core.Genesis{
Config: params.AllEthashProtocolChanges,
Config: config,
GasLimit: gasLimit,
Alloc: alloc,
}

blockchain, _ := core.NewBlockChain(database, &genesis, ethash.NewFaker(), core.DefaultConfig())
// Use beacon.NewFaker() for post-merge configs (Shanghai+), ethash.NewFaker() otherwise
var engine consensus.Engine
if config.ShanghaiBlock != nil {
engine = beacon.NewFaker()
} else {
engine = ethash.NewFaker()
}

blockchain, _ := core.NewBlockChain(database, &genesis, engine, core.DefaultConfig())

backend := &SimulatedBackend{
database: database,
blockchain: blockchain,
engine: engine,
config: genesis.Config,
}

Expand Down Expand Up @@ -155,7 +173,7 @@ func (b *SimulatedBackend) Rollback() {
}

func (b *SimulatedBackend) rollback(parent *types.Block) {
blocks, _ := core.GenerateChain(b.config, parent, ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
blocks, _ := core.GenerateChain(b.config, parent, b.engine, b.database, 1, func(int, *core.BlockGen) {})

b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), b.blockchain.StateCache())
Expand Down Expand Up @@ -687,6 +705,10 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
if call.Gas == 0 {
call.Gas = 10 * header.GasLimit
}
// Cap gas to protocol limit to avoid exceeding MaxTxGas
if call.Gas > params.MaxTxGas {
call.Gas = params.MaxTxGas
}
if call.Value == nil {
call.Value = new(big.Int)
}
Expand Down Expand Up @@ -739,7 +761,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
return fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce)
}
// Include tx in chain
blocks, receipts := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
blocks, receipts := core.GenerateChain(b.config, block, b.engine, b.database, 1, func(number int, block *core.BlockGen) {
for _, tx := range b.pendingBlock.Transactions() {
block.AddTxWithChain(b.blockchain, tx)
}
Expand Down Expand Up @@ -770,7 +792,7 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.Filter
if query.FromBlock != nil {
from = query.FromBlock.Int64()
}
to := int64(-1)
to := int64(rpc.LatestBlockNumber)
if query.ToBlock != nil {
to = query.ToBlock.Int64()
}
Expand Down Expand Up @@ -865,7 +887,7 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
return errors.New("could not find parent")
}

blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
blocks, _ := core.GenerateChain(b.config, block, b.engine, b.database, 1, func(number int, block *core.BlockGen) {
block.OffsetTime(int64(adjustment.Seconds()))
})
stateDB, err := b.blockchain.State()
Expand Down Expand Up @@ -967,19 +989,23 @@ func (fb *filterBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event
func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 }

func (fb *filterBackend) ChainConfig() *params.ChainConfig {
panic("not supported")
return fb.bc.Config()
}

func (fb *filterBackend) CurrentHeader() *types.Header {
panic("not supported")
return fb.bc.CurrentHeader()
}

func (fb *filterBackend) NewMatcherBackend() filtermaps.MatcherBackend {
panic("not supported")
return &simulatedMatcherBackend{bc: fb.bc}
}

func (fb *filterBackend) CurrentView() *filtermaps.ChainView {
panic("implement me")
head := fb.bc.CurrentBlock()
if head == nil {
return nil
}
return filtermaps.NewChainView(fb.bc, head.Number.Uint64(), head.Hash())
}

func (fb *filterBackend) HistoryPruningCutoff() uint64 {
Expand All @@ -992,3 +1018,41 @@ func nullSubscription() event.Subscription {
return nil
})
}

// simulatedMatcherBackend implements filtermaps.MatcherBackend for simulated backend.
// It returns empty indexed ranges to force unindexed search, which works correctly
// for simulated backends without needing full FilterMaps indexing.
type simulatedMatcherBackend struct {
bc *core.BlockChain
}

func (s *simulatedMatcherBackend) GetParams() *filtermaps.Params {
return nil
}

func (s *simulatedMatcherBackend) GetBlockLvPointer(ctx context.Context, blockNumber uint64) (uint64, error) {
return 0, nil
}

func (s *simulatedMatcherBackend) GetFilterMapRows(ctx context.Context, mapIndices []uint32, rowIndex uint32, baseLayerOnly bool) ([]filtermaps.FilterRow, error) {
return nil, nil
}

func (s *simulatedMatcherBackend) GetLogByLvIndex(ctx context.Context, lvIndex uint64) (*types.Log, error) {
return nil, nil
}

func (s *simulatedMatcherBackend) SyncLogIndex(ctx context.Context) (filtermaps.SyncRange, error) {
head := s.bc.CurrentBlock()
if head == nil {
return filtermaps.SyncRange{}, nil
}
// Return empty IndexedBlocks to force unindexed search
return filtermaps.SyncRange{
IndexedView: nil,
ValidBlocks: common.Range[uint64]{},
IndexedBlocks: common.Range[uint64]{},
}, nil
}

func (s *simulatedMatcherBackend) Close() {}
75 changes: 23 additions & 52 deletions accounts/abi/bind/v2/lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,69 +28,52 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2/internal/contracts/nested_libraries"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2/internal/contracts/solc_errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient/simulated"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
)

var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
var testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
var testChainID = big.NewInt(1337)

func testSetup() (*backends.SimulatedBackend, error) {
backend := simulated.NewBackend(
func testSetup() *backends.SimulatedBackend {
return backends.NewSimulatedBackendWithConfig(
rawdb.NewMemoryDatabase(),
types.GenesisAlloc{
testAddr: {Balance: big.NewInt(1000000000000000000)},
},
func(nodeConf *node.Config, ethConf *ethconfig.Config) {
ethConf.Genesis.Difficulty = big.NewInt(0)
},
60000000,
params.MergedTestChainConfig,
)

// we should just be able to use the backend directly, instead of using
// this deprecated interface. However, the simulated backend no longer
// implements backends.SimulatedBackend...
bindBackend := backends.SimulatedBackend{
Backend: backend,
Client: backend.Client(),
}
return &bindBackend, nil
}

func makeTestDeployer(backend simulated.Client) func(input, deployer []byte) (common.Address, *types.Transaction, error) {
chainId, _ := backend.ChainID(context.Background())
return bind.DefaultDeployer(bind.NewKeyedTransactor(testKey, chainId), backend)
func makeTestDeployer(backend *backends.SimulatedBackend) func(input, deployer []byte) (common.Address, *types.Transaction, error) {
return bind.DefaultDeployer(bind.NewKeyedTransactor(testKey, testChainID), backend)
}

// makeTestDeployerWithNonceAssignment is similar to makeTestDeployer,
// but it returns a deployer that automatically tracks nonce,
// enabling the deployment of multiple contracts from the same account.
func makeTestDeployerWithNonceAssignment(backend simulated.Client) func(input, deployer []byte) (common.Address, *types.Transaction, error) {
chainId, _ := backend.ChainID(context.Background())
return bind.DeployerWithNonceAssignment(bind.NewKeyedTransactor(testKey, chainId), backend)
func makeTestDeployerWithNonceAssignment(backend *backends.SimulatedBackend) func(input, deployer []byte) (common.Address, *types.Transaction, error) {
return bind.DeployerWithNonceAssignment(bind.NewKeyedTransactor(testKey, testChainID), backend)
}

// test that deploying a contract with library dependencies works,
// verifying by calling method on the deployed contract.
func TestDeploymentLibraries(t *testing.T) {
// TODO - bor: refactor and enable (task: POS-3046)
t.Skip("bor: Skipping all tests for now. To be fixed later")
bindBackend, err := testSetup()
if err != nil {
t.Fatalf("err setting up test: %v", err)
}
defer bindBackend.Backend.Close()
bindBackend := testSetup()
defer bindBackend.Close()

c := nested_libraries.NewC1()
constructorInput := c.PackConstructor(big.NewInt(42), big.NewInt(1))
deploymentParams := &bind.DeploymentParams{
Contracts: []*bind.MetaData{&nested_libraries.C1MetaData},
Inputs: map[string][]byte{nested_libraries.C1MetaData.ID: constructorInput},
}
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployerWithNonceAssignment(bindBackend.Client))
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployerWithNonceAssignment(bindBackend))
if err != nil {
t.Fatalf("err: %+v\n", err)
}
Expand Down Expand Up @@ -122,13 +105,8 @@ func TestDeploymentLibraries(t *testing.T) {
// Same as TestDeployment. However, stagger the deployments with overrides:
// first deploy the library deps and then the contract.
func TestDeploymentWithOverrides(t *testing.T) {
// TODO - bor: refactor and enable (task: POS-3046)
t.Skip("bor: Skipping all tests for now. To be fixed later")
bindBackend, err := testSetup()
if err != nil {
t.Fatalf("err setting up test: %v", err)
}
defer bindBackend.Backend.Close()
bindBackend := testSetup()
defer bindBackend.Close()

// deploy all the library dependencies of our target contract, but not the target contract itself.
deploymentParams := &bind.DeploymentParams{
Expand Down Expand Up @@ -191,7 +169,7 @@ func TestDeploymentWithOverrides(t *testing.T) {

// returns transaction auth to send a basic transaction from testAddr
func defaultTxAuth() *bind.TransactOpts {
signer := types.LatestSigner(params.AllDevChainProtocolChanges)
signer := types.LatestSigner(params.MergedTestChainConfig)
opts := &bind.TransactOpts{
From: testAddr,
Nonce: nil,
Expand All @@ -212,13 +190,9 @@ func defaultTxAuth() *bind.TransactOpts {
}

func TestEvents(t *testing.T) {
// TODO - bor: refactor and enable (task: POS-3046)
t.Skip("bor: Skipping all tests for now. To be fixed later")
// test watch/filter logs method on a contract that emits various kinds of events (struct-containing, etc.)
backend, err := testSetup()
if err != nil {
t.Fatalf("error setting up testing env: %v", err)
}
backend := testSetup()
defer backend.Close()
deploymentParams := &bind.DeploymentParams{
Contracts: []*bind.MetaData{&events.CMetaData},
}
Expand Down Expand Up @@ -321,13 +295,10 @@ done:
}

func TestErrors(t *testing.T) {
// TODO - bor: refactor and enable (task: POS-3046)
t.Skip("bor: Skipping all tests for now. To be fixed later")
// test watch/filter logs method on a contract that emits various kinds of events (struct-containing, etc.)
backend, err := testSetup()
if err != nil {
t.Fatalf("error setting up testing env: %v", err)
}
backend := testSetup()
defer backend.Close()

deploymentParams := &bind.DeploymentParams{
Contracts: []*bind.MetaData{&solc_errors.CMetaData},
}
Expand All @@ -344,7 +315,7 @@ func TestErrors(t *testing.T) {
c := solc_errors.NewC()
instance := c.Instance(backend, res.Addresses[solc_errors.CMetaData.ID])
packedInput := c.PackFoo()
opts := &bind.CallOpts{From: res.Addresses[solc_errors.CMetaData.ID]}
opts := &bind.CallOpts{From: testAddr}
_, err = bind.Call[struct{}](instance, opts, packedInput, nil)
if err == nil {
t.Fatalf("expected call to fail")
Expand Down
25 changes: 20 additions & 5 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -671,8 +671,9 @@ var (

// MergedTestChainConfig contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers for testing purposes.
// Includes all Bor hard forks enabled at block 0.
MergedTestChainConfig = &ChainConfig{
ChainID: big.NewInt(1),
ChainID: big.NewInt(1337),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: false,
Expand Down Expand Up @@ -703,10 +704,24 @@ var (
Osaka: DefaultOsakaBlobConfig,
},
Bor: &BorConfig{
Sprint: map[string]uint64{
"0": 4},
BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"},
Period: map[string]uint64{"0": 2},
Sprint: map[string]uint64{"0": 4},
Period: map[string]uint64{"0": 2},
ProducerDelay: map[string]uint64{"0": 1},
BackupMultiplier: map[string]uint64{"0": 2},
ValidatorContract: "0x0000000000000000000000000000000000001000",
StateReceiverContract: "0x0000000000000000000000000000000000001001",
BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"},
BlockAlloc: map[string]interface{}{},
// Bor hard forks
JaipurBlock: big.NewInt(0),
DelhiBlock: big.NewInt(0),
IndoreBlock: big.NewInt(0),
AhmedabadBlock: big.NewInt(0),
BhilaiBlock: big.NewInt(0),
RioBlock: big.NewInt(0),
MadhugiriBlock: big.NewInt(0),
MadhugiriProBlock: big.NewInt(0),
DandeliBlock: big.NewInt(0),
},
}

Expand Down
Loading