mirror of
https://github.com/logos-storage/nim-ethers.git
synced 2026-01-25 17:03:17 +00:00
Only cancels transactions if nonce has been incremented since the last estimateGas failure
This commit is contained in:
parent
9ffc1763e4
commit
1862c9eea6
@ -8,6 +8,7 @@ import ./provider
|
||||
import ./signer
|
||||
import ./events
|
||||
import ./fields
|
||||
import ./exceptions
|
||||
|
||||
export basics
|
||||
export provider
|
||||
@ -116,6 +117,38 @@ proc call(contract: Contract,
|
||||
let response = await contract.provider.call(transaction, overrides)
|
||||
return decodeResponse(ReturnType, returnMultiple, response)
|
||||
|
||||
proc populateTransaction(
|
||||
contract: Contract,
|
||||
tx: Transaction
|
||||
): Future[Transaction] {.async.} =
|
||||
|
||||
if signer =? contract.signer:
|
||||
try:
|
||||
return await signer.populateTransaction(tx)
|
||||
except EstimateGasError as e:
|
||||
if nonce =? e.transaction.nonce:
|
||||
|
||||
if lastSeenNonce =? signer.lastSeenNonce and
|
||||
lastSeenNonce > nonce:
|
||||
discard await signer.cancelTransaction(e.transaction)
|
||||
let revertReason = if not e.parent.isNil: e.parent.msg
|
||||
else: "unknown"
|
||||
info "A cancellation transaction has been sent to prevent stuck " &
|
||||
"transactions",
|
||||
nonce = e.transaction.nonce,
|
||||
revertReason
|
||||
|
||||
# nonce wasn't incremented by another transaction, so force update the
|
||||
# lastSeenNonce
|
||||
else:
|
||||
signer.updateNonce(nonce - 1, force = true)
|
||||
trace "nonce decremented -- estimateGas failed but no further " &
|
||||
"nonces were generated. Prevents stuck txs.",
|
||||
failedNonce = nonce,
|
||||
newNonce = nonce - 1
|
||||
|
||||
raiseContractError e.msgStack
|
||||
|
||||
proc send(contract: Contract,
|
||||
function: string,
|
||||
parameters: tuple,
|
||||
@ -123,7 +156,7 @@ proc send(contract: Contract,
|
||||
Future[?TransactionResponse] {.async.} =
|
||||
if signer =? contract.signer:
|
||||
let transaction = createTransaction(contract, function, parameters, overrides)
|
||||
let populated = await signer.populateTransaction(transaction, cancelOnEstimateGasError = true)
|
||||
let populated = await contract.populateTransaction(transaction)
|
||||
let txResp = await signer.sendTransaction(populated)
|
||||
return txResp.some
|
||||
else:
|
||||
|
||||
7
ethers/exceptions.nim
Normal file
7
ethers/exceptions.nim
Normal file
@ -0,0 +1,7 @@
|
||||
import ./basics
|
||||
|
||||
func msgStack*(error: ref EthersError): string =
|
||||
var msg = error.msg
|
||||
if not error.parent.isNil:
|
||||
msg &= " -- Parent exception: " & error.parent.msg
|
||||
return msg
|
||||
@ -66,7 +66,9 @@ method estimateGas*(signer: Signer,
|
||||
method getChainId*(signer: Signer): Future[UInt256] {.base, gcsafe.} =
|
||||
signer.provider.getChainId()
|
||||
|
||||
method getNonce(signer: Signer): Future[UInt256] {.base, gcsafe, async.} =
|
||||
func lastSeenNonce*(signer: Signer): ?UInt256 = signer.lastSeenNonce
|
||||
|
||||
method getNonce*(signer: Signer): Future[UInt256] {.base, gcsafe, async.} =
|
||||
var nonce = await signer.getTransactionCount(BlockTag.pending)
|
||||
|
||||
if lastSeen =? signer.lastSeenNonce and lastSeen >= nonce:
|
||||
@ -84,7 +86,7 @@ method updateNonce*(
|
||||
signer.lastSeenNonce = some nonce
|
||||
return
|
||||
|
||||
if nonce > lastSeen:
|
||||
if force or nonce > lastSeen:
|
||||
signer.lastSeenNonce = some nonce
|
||||
|
||||
method decreaseNonce*(signer: Signer) {.base, gcsafe.} =
|
||||
@ -92,8 +94,7 @@ method decreaseNonce*(signer: Signer) {.base, gcsafe.} =
|
||||
signer.lastSeenNonce = some lastSeen - 1
|
||||
|
||||
method populateTransaction*(signer: Signer,
|
||||
transaction: Transaction,
|
||||
cancelOnEstimateGasError = false):
|
||||
transaction: Transaction):
|
||||
Future[Transaction] {.base, async.} =
|
||||
|
||||
if sender =? transaction.sender and sender != await signer.getAddress():
|
||||
|
||||
@ -16,6 +16,7 @@ type
|
||||
|
||||
method mint(token: TestToken, holder: Address, amount: UInt256): ?TransactionResponse {.base, contract.}
|
||||
method myBalance(token: TestToken): UInt256 {.base, contract, view.}
|
||||
method doRevert(token: TestToken, reason: string): ?TransactionResponse {.base, contract.}
|
||||
|
||||
for url in ["ws://localhost:8545", "http://localhost:8545"]:
|
||||
|
||||
|
||||
@ -21,4 +21,9 @@ contract TestToken is ERC20 {
|
||||
function myBalance() public view returns (uint256) {
|
||||
return balanceOf(msg.sender);
|
||||
}
|
||||
|
||||
function doRevert(string memory reason) public {
|
||||
// Revert every tx with given reason
|
||||
require(false, reason);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user