From d97d3716ca5b1f2dca8551d7749cef102b8393cb Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Tue, 8 Jul 2025 20:05:25 +0900 Subject: [PATCH 1/3] accounts/abi/bind/v2: modify the default deployer to block until the transaction is accepted/rejected from the pool. --- accounts/abi/bind/v2/backend.go | 3 +++ accounts/abi/bind/v2/lib.go | 36 ++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/accounts/abi/bind/v2/backend.go b/accounts/abi/bind/v2/backend.go index 2f5f17b31eb..2ae75c1622d 100644 --- a/accounts/abi/bind/v2/backend.go +++ b/accounts/abi/bind/v2/backend.go @@ -103,6 +103,9 @@ 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 corresponding to the given hash. + TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, isPending bool, err error) } // DeployBackend wraps the operations needed by WaitMined and WaitDeployed. diff --git a/accounts/abi/bind/v2/lib.go b/accounts/abi/bind/v2/lib.go index 38311613413..f682dbdac37 100644 --- a/accounts/abi/bind/v2/lib.go +++ b/accounts/abi/bind/v2/lib.go @@ -27,14 +27,16 @@ package bind import ( + "context" "errors" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" + "time" ) // ContractEvent is a type constraint for ABI event types. @@ -227,6 +229,34 @@ func DeployContract(opts *TransactOpts, bytecode []byte, backend ContractBackend return crypto.CreateAddress(opts.From, tx.Nonce()), tx, nil } +// waitAccepted polls the backend until the transaction is accepted or the +// context is cancelled. If the transaction was not accepted into the pool, +// an error is returned. +func waitAccepted(ctx context.Context, d ContractBackend, 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: + } + } +} + // DefaultDeployer returns a DeployFn that signs and submits creation transactions // using the given signer. // @@ -238,6 +268,10 @@ func DefaultDeployer(opts *TransactOpts, backend ContractBackend) DeployFn { if err != nil { return common.Address{}, nil, err } + ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) + if err := waitAccepted(ctx, backend, tx.Hash()); err != nil { + return common.Address{}, nil, err + } return addr, tx, nil } } From eab13853a5bbd9260a8337530699321e11af61cf Mon Sep 17 00:00:00 2001 From: jwasinger Date: Tue, 8 Jul 2025 20:17:29 +0900 Subject: [PATCH 2/3] Update accounts/abi/bind/v2/lib.go --- accounts/abi/bind/v2/lib.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/abi/bind/v2/lib.go b/accounts/abi/bind/v2/lib.go index f682dbdac37..8b2a44d2c85 100644 --- a/accounts/abi/bind/v2/lib.go +++ b/accounts/abi/bind/v2/lib.go @@ -242,7 +242,7 @@ func waitAccepted(ctx context.Context, d ContractBackend, txHash common.Hash) er return nil } - if errors.Is(err, ethereum.NotFound) { // TODO: check this is emitted + if errors.Is(err, ethereum.NotFound) { logger.Trace("Transaction not yet accepted") } else { logger.Trace("Transaction submission failed", "err", err) From 45bc37294714997b7777448af5255bde79f19202 Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Tue, 8 Jul 2025 20:25:07 +0900 Subject: [PATCH 3/3] various fixes --- accounts/abi/bind/v2/base_test.go | 4 ++++ accounts/abi/bind/v2/lib.go | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/accounts/abi/bind/v2/base_test.go b/accounts/abi/bind/v2/base_test.go index 80d0f22f2c7..c7a27a96c3e 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, txHash common.Hash) (tx *types.Transaction, isPending bool, err error) { + return nil, false, nil +} + type mockCaller struct { codeAtBlockNumber *big.Int callContractBlockNumber *big.Int diff --git a/accounts/abi/bind/v2/lib.go b/accounts/abi/bind/v2/lib.go index 8b2a44d2c85..b644c0b5645 100644 --- a/accounts/abi/bind/v2/lib.go +++ b/accounts/abi/bind/v2/lib.go @@ -29,6 +29,8 @@ package bind import ( "context" "errors" + "time" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -36,7 +38,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" - "time" ) // ContractEvent is a type constraint for ABI event types. @@ -268,7 +269,8 @@ func DefaultDeployer(opts *TransactOpts, backend ContractBackend) DeployFn { if err != nil { return common.Address{}, nil, err } - ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() if err := waitAccepted(ctx, backend, tx.Hash()); err != nil { return common.Address{}, nil, err }