From fa8590a5c83acf05c55a0d29a58f19a2eeb7aa76 Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Tue, 8 Jul 2025 14:29:50 +0900 Subject: [PATCH 1/3] fix contract deployment by waiting for tx acceptance between individual lib deployments --- accounts/abi/abigen/source.go.tpl | 5 ++++- accounts/abi/bind/v2/backend.go | 1 + accounts/abi/bind/v2/base.go | 6 +++--- accounts/abi/bind/v2/util.go | 25 +++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/accounts/abi/abigen/source.go.tpl b/accounts/abi/abigen/source.go.tpl index c84862d03b..56ff1e66f0 100644 --- a/accounts/abi/abigen/source.go.tpl +++ b/accounts/abi/abigen/source.go.tpl @@ -77,7 +77,10 @@ var ( return common.Address{}, nil, nil, errors.New("GetABI returned nil") } {{range $pattern, $name := .Libraries}} - {{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend) + {{decapitalise $name}}Addr, tx, _, _ := Deploy{{capitalise $name}}(auth, backend) + if err := bind.WaitAccepted(context.Background(), backend, tx.Hash()); err != nil { + return common.Address{}, nil, nil err + } {{$contract.Type}}Bin = strings.ReplaceAll({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:]) {{end}} address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}}) diff --git a/accounts/abi/bind/v2/backend.go b/accounts/abi/bind/v2/backend.go index 2f5f17b31e..6ddd6b8b2c 100644 --- a/accounts/abi/bind/v2/backend.go +++ b/accounts/abi/bind/v2/backend.go @@ -109,6 +109,7 @@ type ContractTransactor interface { type DeployBackend interface { TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) + TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) } // ContractFilterer defines the methods needed to access log events using one-off diff --git a/accounts/abi/bind/v2/base.go b/accounts/abi/bind/v2/base.go index 535c0ed4fd..0a34523575 100644 --- a/accounts/abi/bind/v2/base.go +++ b/accounts/abi/bind/v2/base.go @@ -313,7 +313,7 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add } } // create the transaction - nonce, err := c.getNonce(opts) + nonce, err := c.GetNonce(opts) if err != nil { return nil, err } @@ -358,7 +358,7 @@ func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Addr } } // create the transaction - nonce, err := c.getNonce(opts) + nonce, err := c.GetNonce(opts) if err != nil { return nil, err } @@ -395,7 +395,7 @@ func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Ad return c.transactor.EstimateGas(ensureContext(opts.Context), msg) } -func (c *BoundContract) getNonce(opts *TransactOpts) (uint64, error) { +func (c *BoundContract) GetNonce(opts *TransactOpts) (uint64, error) { if opts.Nonce == nil { return c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From) } else { diff --git a/accounts/abi/bind/v2/util.go b/accounts/abi/bind/v2/util.go index 438848a753..0a0e86441a 100644 --- a/accounts/abi/bind/v2/util.go +++ b/accounts/abi/bind/v2/util.go @@ -75,3 +75,28 @@ func WaitDeployed(ctx context.Context, b DeployBackend, hash common.Hash) (commo } return receipt.ContractAddress, err } + +func WaitAccepted(ctx context.Context, d DeployBackend, txHash common.Hash) error { + queryTicker := time.NewTicker(time.Second) + defer queryTicker.Stop() + logger := log.New("hash", txHash) + for { + _, _, err := d.TransactionByHash(ctx, txHash) + if err == nil { + return nil + } + + if errors.Is(err, ethereum.NotFound) { // TODO: check this is emitted + logger.Trace("Transaction not yet accepted") + } else { + logger.Trace("Transaction submission failed", "err", err) + } + + // Wait for the next round. + select { + case <-ctx.Done(): + return ctx.Err() + case <-queryTicker.C: + } + } +} From 0729d2a99e822084eea1b9120ee98d9411ad8f13 Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Tue, 8 Jul 2025 14:52:51 +0900 Subject: [PATCH 2/3] fix --- accounts/abi/abigen/source.go.tpl | 9 +++++++-- accounts/abi/bind/old.go | 6 ++++++ accounts/abi/bind/v2/backend.go | 4 +++- accounts/abi/bind/v2/util.go | 2 +- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/accounts/abi/abigen/source.go.tpl b/accounts/abi/abigen/source.go.tpl index 56ff1e66f0..816ea1cb40 100644 --- a/accounts/abi/abigen/source.go.tpl +++ b/accounts/abi/abigen/source.go.tpl @@ -4,8 +4,10 @@ package {{.Package}} import ( + "context" "math/big" "strings" + "time" "errors" ethereum "github.com/ethereum/go-ethereum" @@ -27,6 +29,8 @@ var ( _ = types.BloomLookup _ = event.NewSubscription _ = abi.ConvertType + _ = time.Tick + _ = context.Background ) {{$structs := .Structs}} @@ -78,8 +82,9 @@ var ( } {{range $pattern, $name := .Libraries}} {{decapitalise $name}}Addr, tx, _, _ := Deploy{{capitalise $name}}(auth, backend) - if err := bind.WaitAccepted(context.Background(), backend, tx.Hash()); err != nil { - return common.Address{}, nil, nil err + ctx, _ := context.WithTimeout(context.Background(), 5 * time.Second) + if err := bind.WaitAccepted(ctx, backend, tx); err != nil { + return common.Address{}, nil, nil, err } {{$contract.Type}}Bin = strings.ReplaceAll({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:]) {{end}} diff --git a/accounts/abi/bind/old.go b/accounts/abi/bind/old.go index b09f5f3c7a..86e18a8c2c 100644 --- a/accounts/abi/bind/old.go +++ b/accounts/abi/bind/old.go @@ -266,6 +266,12 @@ func (m *MetaData) GetAbi() (*abi.ABI, error) { // util.go +// WaitAccepted waits for a tx to be accepted into the pool. +// It stops waiting when the context is canceled. +func WaitAccepted(ctx context.Context, b ContractBackend, tx *types.Transaction) error { + return bind2.WaitAccepted(ctx, b, tx.Hash()) +} + // WaitMined waits for tx to be mined on the blockchain. // It stops waiting when the context is canceled. func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) { diff --git a/accounts/abi/bind/v2/backend.go b/accounts/abi/bind/v2/backend.go index 6ddd6b8b2c..d7ac49867c 100644 --- a/accounts/abi/bind/v2/backend.go +++ b/accounts/abi/bind/v2/backend.go @@ -103,13 +103,15 @@ type ContractTransactor interface { // PendingNonceAt retrieves the current pending nonce associated with an account. PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) + + // TransactionByHash retrieves the transaction associated with the hash, if it exists in the pool. + TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) } // DeployBackend wraps the operations needed by WaitMined and WaitDeployed. type DeployBackend interface { TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) - TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) } // ContractFilterer defines the methods needed to access log events using one-off diff --git a/accounts/abi/bind/v2/util.go b/accounts/abi/bind/v2/util.go index 0a0e86441a..0f56edbcf1 100644 --- a/accounts/abi/bind/v2/util.go +++ b/accounts/abi/bind/v2/util.go @@ -76,7 +76,7 @@ func WaitDeployed(ctx context.Context, b DeployBackend, hash common.Hash) (commo return receipt.ContractAddress, err } -func WaitAccepted(ctx context.Context, d DeployBackend, txHash common.Hash) error { +func WaitAccepted(ctx context.Context, d ContractBackend, txHash common.Hash) error { queryTicker := time.NewTicker(time.Second) defer queryTicker.Stop() logger := log.New("hash", txHash) From ee4c97193b69ec88d55536d4343973629bffe9bf Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Tue, 8 Jul 2025 15:38:45 +0900 Subject: [PATCH 3/3] fixed lint --- accounts/abi/abigen/source.go.tpl | 2 +- accounts/abi/bind/v2/base_test.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/accounts/abi/abigen/source.go.tpl b/accounts/abi/abigen/source.go.tpl index 816ea1cb40..09bc167188 100644 --- a/accounts/abi/abigen/source.go.tpl +++ b/accounts/abi/abigen/source.go.tpl @@ -4,7 +4,7 @@ package {{.Package}} import ( - "context" + "context" "math/big" "strings" "time" diff --git a/accounts/abi/bind/v2/base_test.go b/accounts/abi/bind/v2/base_test.go index 80d0f22f2c..7015d39694 100644 --- a/accounts/abi/bind/v2/base_test.go +++ b/accounts/abi/bind/v2/base_test.go @@ -75,6 +75,10 @@ func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transac return nil } +func (mt *mockTransactor) TransactionByHash(ctx context.Context, hash common.Hash) (*types.Transaction, bool, error) { + return nil, false, nil +} + type mockCaller struct { codeAtBlockNumber *big.Int callContractBlockNumber *big.Int