Skip to content

Commit 889ef0d

Browse files
author
Manoranjith
committed
🐛 [backend/eth/channel] Fix nonce generation for transactions
- Previously, ERC20 deposit transactions would not work when using ganache-cli node. Because ERC20 deposit involved two txs and both txs got the same nonce. - Now, track the nonce in contract backend for each account and use it to ensure no two transactions get the same nonce. Resolves #62. Signed-off-by: Manoranjith <ponraj.manoranjitha@in.bosch.com
1 parent c1cbad0 commit 889ef0d

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

backend/ethereum/channel/contractbackend.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ import (
1818
"context"
1919
stderrors "errors"
2020
"math/big"
21+
"sync"
2122

2223
"github.com/ethereum/go-ethereum"
2324
"github.com/ethereum/go-ethereum/accounts"
2425
"github.com/ethereum/go-ethereum/accounts/abi"
2526
"github.com/ethereum/go-ethereum/accounts/abi/bind"
27+
"github.com/ethereum/go-ethereum/common"
2628
"github.com/ethereum/go-ethereum/core/types"
2729
"github.com/pkg/errors"
2830

@@ -60,14 +62,18 @@ type Transactor interface {
6062
// This is needed to send on-chain transaction to interact with the smart contracts.
6163
type ContractBackend struct {
6264
ContractInterface
63-
tr Transactor
65+
tr Transactor
66+
nonceMtx *sync.Mutex
67+
expectedNextNonce map[common.Address]uint64
6468
}
6569

6670
// NewContractBackend creates a new ContractBackend with the given parameters.
6771
func NewContractBackend(cf ContractInterface, tr Transactor) ContractBackend {
6872
return ContractBackend{
6973
ContractInterface: cf,
7074
tr: tr,
75+
expectedNextNonce: make(map[common.Address]uint64),
76+
nonceMtx: &sync.Mutex{},
7177
}
7278
}
7379

@@ -122,6 +128,13 @@ func (c *ContractBackend) pastOffsetBlockNum(ctx context.Context) (uint64, error
122128
// set the value manually afterwards if it should be different from 0.
123129
func (c *ContractBackend) NewTransactor(ctx context.Context, gasLimit uint64,
124130
acc accounts.Account) (*bind.TransactOpts, error) {
131+
c.nonceMtx.Lock()
132+
defer c.nonceMtx.Unlock()
133+
expectedNextNonce, found := c.expectedNextNonce[acc.Address]
134+
if !found {
135+
c.expectedNextNonce[acc.Address] = 0
136+
}
137+
125138
auth, err := c.tr.NewTransactor(acc)
126139
if err != nil {
127140
return nil, errors.WithMessage(err, "creating transactor")
@@ -130,6 +143,17 @@ func (c *ContractBackend) NewTransactor(ctx context.Context, gasLimit uint64,
130143
auth.GasLimit = gasLimit
131144
auth.Context = ctx
132145

146+
nonce, err := c.PendingNonceAt(ctx, acc.Address)
147+
if err != nil {
148+
return nil, errors.Wrap(err, "fetching nonce")
149+
}
150+
if nonce < expectedNextNonce {
151+
nonce = expectedNextNonce
152+
}
153+
154+
auth.Nonce = big.NewInt(int64(nonce))
155+
c.expectedNextNonce[acc.Address] = nonce + 1
156+
133157
return auth, nil
134158
}
135159

0 commit comments

Comments
 (0)