use customized deployer

This commit is contained in:
steven 2025-07-15 12:00:30 +08:00
parent afdbefebe4
commit e106357366
No known key found for this signature in database
3 changed files with 37 additions and 27 deletions

View file

@ -443,6 +443,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
if opts.NoSend { if opts.NoSend {
return signedTx, nil return signedTx, nil
} }
fmt.Println("nonce:", signedTx.Nonce())
if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx); err != nil { if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx); err != nil {
return nil, err return nil, err
} }

View file

@ -27,10 +27,8 @@
package bind package bind
import ( import (
"context"
"errors" "errors"
"fmt" "math/big"
"time"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
@ -227,28 +225,7 @@ func DeployContract(opts *TransactOpts, bytecode []byte, backend ContractBackend
if err != nil { if err != nil {
return common.Address{}, nil, err return common.Address{}, nil, err
} }
return crypto.CreateAddress(opts.From, tx.Nonce()), tx, nil
addr := crypto.CreateAddress(opts.From, tx.Nonce())
ctx, cancel := context.WithTimeout(opts.Context, 5*time.Second)
defer cancel()
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return common.Address{}, nil, fmt.Errorf("contract deployment timeout at %s", addr.Hex())
case <-ticker.C:
code, err := c.transactor.PendingCodeAt(ensureContext(ctx), addr)
if err != nil {
return common.Address{}, nil, err
}
if len(code) != 0 {
return addr, tx, nil
}
}
}
} }
// DefaultDeployer returns a DeployFn that signs and submits creation transactions // DefaultDeployer returns a DeployFn that signs and submits creation transactions
@ -265,3 +242,27 @@ func DefaultDeployer(opts *TransactOpts, backend ContractBackend) DeployFn {
return addr, tx, nil return addr, tx, nil
} }
} }
// DeployerWithNonceAssignment is basically identical to DefaultDeployer,
// but it additionally tracks the nonce to enable automatic assignment.
//
// This is especially useful when deploying multiple contracts
// from the same address — whether they are independent contracts
// or part of a dependency chain that must be deployed in order.
func DeployerWithNonceAssignment(opts *TransactOpts, backend ContractBackend) DeployFn {
var pendingNonce int64
if opts.Nonce != nil {
pendingNonce = opts.Nonce.Int64()
}
return func(input []byte, deployer []byte) (common.Address, *types.Transaction, error) {
if pendingNonce != 0 {
opts.Nonce = big.NewInt(pendingNonce)
}
addr, tx, err := DeployContract(opts, deployer, backend, input)
if err != nil {
return common.Address{}, nil, err
}
pendingNonce = int64(tx.Nonce() + 1)
return addr, tx, nil
}
}

View file

@ -65,6 +65,14 @@ func makeTestDeployer(backend simulated.Client) func(input, deployer []byte) (co
return bind.DefaultDeployer(bind.NewKeyedTransactor(testKey, chainId), backend) return bind.DefaultDeployer(bind.NewKeyedTransactor(testKey, chainId), 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)
}
// test that deploying a contract with library dependencies works, // test that deploying a contract with library dependencies works,
// verifying by calling method on the deployed contract. // verifying by calling method on the deployed contract.
func TestDeploymentLibraries(t *testing.T) { func TestDeploymentLibraries(t *testing.T) {
@ -80,7 +88,7 @@ func TestDeploymentLibraries(t *testing.T) {
Contracts: []*bind.MetaData{&nested_libraries.C1MetaData}, Contracts: []*bind.MetaData{&nested_libraries.C1MetaData},
Inputs: map[string][]byte{nested_libraries.C1MetaData.ID: constructorInput}, Inputs: map[string][]byte{nested_libraries.C1MetaData.ID: constructorInput},
} }
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(bindBackend.Client)) res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployerWithNonceAssignment(bindBackend.Client))
if err != nil { if err != nil {
t.Fatalf("err: %+v\n", err) t.Fatalf("err: %+v\n", err)
} }
@ -122,7 +130,7 @@ func TestDeploymentWithOverrides(t *testing.T) {
deploymentParams := &bind.DeploymentParams{ deploymentParams := &bind.DeploymentParams{
Contracts: nested_libraries.C1MetaData.Deps, Contracts: nested_libraries.C1MetaData.Deps,
} }
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(bindBackend)) res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployerWithNonceAssignment(bindBackend))
if err != nil { if err != nil {
t.Fatalf("err: %+v\n", err) t.Fatalf("err: %+v\n", err)
} }