Skip to content

Commit f030347

Browse files
Increment nonce count when populating transaction (#54)
Increment nonce count when populating transaction Co-authored-by: markspanbroek <[email protected]>
1 parent 8fff631 commit f030347

File tree

5 files changed

+51
-5
lines changed

5 files changed

+51
-5
lines changed

ethers/providers/jsonrpc.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ method signMessage*(signer: JsonRpcSigner,
240240
method sendTransaction*(signer: JsonRpcSigner,
241241
transaction: Transaction): Future[TransactionResponse] {.async.} =
242242
convertError:
243+
signer.updateNonce(transaction.nonce)
243244
let
244245
client = await signer.provider.client
245246
hash = await client.eth_sendTransaction(transaction)

ethers/signer.nim

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import ./provider
33

44
export basics
55

6-
type Signer* = ref object of RootObj
6+
type
7+
Signer* = ref object of RootObj
8+
lastSeenNonce: ?UInt256
9+
710
type SignerError* = object of EthersError
811

912
template raiseSignerError(message: string) =
@@ -41,6 +44,26 @@ method estimateGas*(signer: Signer,
4144
method getChainId*(signer: Signer): Future[UInt256] {.base, gcsafe.} =
4245
signer.provider.getChainId()
4346

47+
method getNonce(signer: Signer): Future[UInt256] {.base, gcsafe, async.} =
48+
var nonce = await signer.getTransactionCount(BlockTag.pending)
49+
50+
if lastSeen =? signer.lastSeenNonce and lastSeen >= nonce:
51+
nonce = (lastSeen + 1.u256)
52+
signer.lastSeenNonce = some nonce
53+
54+
return nonce
55+
56+
method updateNonce*(signer: Signer, nonce: ?UInt256) {.base, gcsafe.} =
57+
without nonce =? nonce:
58+
return
59+
60+
without lastSeen =? signer.lastSeenNonce:
61+
signer.lastSeenNonce = some nonce
62+
return
63+
64+
if nonce > lastSeen:
65+
signer.lastSeenNonce = some nonce
66+
4467
method populateTransaction*(signer: Signer,
4568
transaction: Transaction):
4669
Future[Transaction] {.base, async.} =
@@ -55,7 +78,7 @@ method populateTransaction*(signer: Signer,
5578
if transaction.sender.isNone:
5679
populated.sender = some(await signer.getAddress())
5780
if transaction.nonce.isNone:
58-
populated.nonce = some(await signer.getTransactionCount(BlockTag.pending))
81+
populated.nonce = some(await signer.getNonce())
5982
if transaction.chainId.isNone:
6083
populated.chainId = some(await signer.getChainId())
6184
if transaction.gasPrice.isNone and (transaction.maxFee.isNone or transaction.maxPriorityFee.isNone):

ethers/transaction.nim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ func `$`*(transaction: Transaction): string =
2121
result &= "value: " & $transaction.value & ", "
2222
result &= "data: 0x" & $transaction.data.toHex
2323
if nonce =? transaction.nonce:
24-
result &= ", nonce: 0x" & $nonce.toHex
24+
result &= ", nonce: " & $nonce
2525
if chainId =? transaction.chainId:
2626
result &= ", chainId: " & $chainId
2727
if gasPrice =? transaction.gasPrice:
28-
result &= ", gasPrice: 0x" & $gasPrice.toHex
28+
result &= ", gasPrice: " & $gasPrice
2929
if gasLimit =? transaction.gasLimit:
30-
result &= ", gasLimit: 0x" & $gasLimit.toHex
30+
result &= ", gasLimit: " & $gasLimit
3131
result &= ")"

ethers/wallet.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,5 @@ proc signTransaction*(wallet: Wallet,
7070

7171
method sendTransaction*(wallet: Wallet, transaction: Transaction): Future[TransactionResponse] {.async.} =
7272
let signed = await signTransaction(wallet, transaction)
73+
wallet.updateNonce(transaction.nonce)
7374
return await provider(wallet).sendTransaction(signed)

testmodule/providers/jsonrpc/testJsonRpcSigner.nim

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,24 @@ suite "JsonRpcSigner":
8282
transaction.chainId = 0xdeadbeef.u256.some
8383
expect SignerError:
8484
discard await signer.populateTransaction(transaction)
85+
86+
test "concurrent populate calls increment nonce":
87+
let signer = provider.getSigner()
88+
let count = await signer.getTransactionCount(BlockTag.pending)
89+
var transaction1 = Transaction.example
90+
var transaction2 = Transaction.example
91+
var transaction3 = Transaction.example
92+
93+
let populated = await allFinished(
94+
signer.populateTransaction(transaction1),
95+
signer.populateTransaction(transaction2),
96+
signer.populateTransaction(transaction3)
97+
)
98+
99+
transaction1 = await populated[0]
100+
transaction2 = await populated[1]
101+
transaction3 = await populated[2]
102+
103+
check !transaction1.nonce == count
104+
check !transaction2.nonce == count + 1.u256
105+
check !transaction3.nonce == count + 2.u256

0 commit comments

Comments
 (0)