mirror of
https://github.com/logos-storage/nim-ethers.git
synced 2026-07-31 12:03:16 +00:00
Remove auto-cancellation of failed tx, change revert reason level
- remove auto cancellation of failed tx (during estimate gas) - add asynclock to populate transaction, to ensure nonce sequence (signer level) - move checking of receipt status and obtaining revert reason from contract level to provider level
This commit is contained in:
parent
06dc6c4d65
commit
21de34ced9
@ -250,31 +250,13 @@ proc confirm*(tx: Future[?TransactionResponse],
|
|||||||
## `await token.connect(signer0)
|
## `await token.connect(signer0)
|
||||||
## .mint(accounts[1], 100.u256)
|
## .mint(accounts[1], 100.u256)
|
||||||
## .confirm(3)`
|
## .confirm(3)`
|
||||||
## Will raise ContractError with revert reason if TransactionReceipt.Status
|
|
||||||
## is Failed
|
|
||||||
without response =? (await tx):
|
without response =? (await tx):
|
||||||
raise newException(
|
raise newException(
|
||||||
EthersError,
|
EthersError,
|
||||||
"Transaction hash required. Possibly was a call instead of a send?"
|
"Transaction hash required. Possibly was a call instead of a send?"
|
||||||
)
|
)
|
||||||
|
|
||||||
let receipt = await response.confirm(confirmations, timeout)
|
return await response.confirm(confirmations, timeout)
|
||||||
|
|
||||||
# TODO: handle TransactionStatus.Invalid?
|
|
||||||
if receipt.status == TransactionStatus.Failure:
|
|
||||||
logScope:
|
|
||||||
transactionHash = receipt.transactionHash.to0xHex
|
|
||||||
|
|
||||||
trace "transaction failed, replaying transaction to get revert reason"
|
|
||||||
|
|
||||||
if revertReason =? await response.provider.getRevertReason(receipt):
|
|
||||||
trace "transaction revert reason obtained", revertReason
|
|
||||||
raiseContractError(revertReason)
|
|
||||||
else:
|
|
||||||
trace "transaction replay completed, no revert reason obtained"
|
|
||||||
raiseContractError("Transaction reverted with unknown reason")
|
|
||||||
|
|
||||||
return receipt
|
|
||||||
|
|
||||||
proc queryFilter[E: Event](contract: Contract,
|
proc queryFilter[E: Event](contract: Contract,
|
||||||
_: type E,
|
_: type E,
|
||||||
|
|||||||
@ -81,6 +81,9 @@ const EthersReceiptTimeoutBlks* {.intdefine.} = 50 # in blocks
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "ethers provider"
|
topics = "ethers provider"
|
||||||
|
|
||||||
|
template raiseProviderError(msg: string) =
|
||||||
|
raise newException(ProviderError, msg)
|
||||||
|
|
||||||
func toTransaction*(past: PastTransaction): Transaction =
|
func toTransaction*(past: PastTransaction): Transaction =
|
||||||
Transaction(
|
Transaction(
|
||||||
sender: some past.sender,
|
sender: some past.sender,
|
||||||
@ -194,11 +197,33 @@ method getRevertReason*(
|
|||||||
|
|
||||||
return await provider.getRevertReason(receipt.transactionHash, blockNumber - 1)
|
return await provider.getRevertReason(receipt.transactionHash, blockNumber - 1)
|
||||||
|
|
||||||
|
proc ensureSuccess(
|
||||||
|
provider: Provider,
|
||||||
|
receipt: TransactionReceipt
|
||||||
|
) {.async, upraises: [ProviderError].} =
|
||||||
|
## If the receipt.status is Failed, the tx is replayed to obtain a revert
|
||||||
|
## reason, after which a ProviderError with the revert reason is raised.
|
||||||
|
## If no revert reason was obtained
|
||||||
|
|
||||||
|
# TODO: handle TransactionStatus.Invalid?
|
||||||
|
if receipt.status == TransactionStatus.Failure:
|
||||||
|
logScope:
|
||||||
|
transactionHash = receipt.transactionHash.to0xHex
|
||||||
|
|
||||||
|
trace "transaction failed, replaying transaction to get revert reason"
|
||||||
|
|
||||||
|
if revertReason =? await provider.getRevertReason(receipt):
|
||||||
|
trace "transaction revert reason obtained", revertReason
|
||||||
|
raiseProviderError(revertReason)
|
||||||
|
else:
|
||||||
|
trace "transaction replay completed, no revert reason obtained"
|
||||||
|
raiseProviderError("Transaction reverted with unknown reason")
|
||||||
|
|
||||||
proc confirm*(tx: TransactionResponse,
|
proc confirm*(tx: TransactionResponse,
|
||||||
confirmations = EthersDefaultConfirmations,
|
confirmations = EthersDefaultConfirmations,
|
||||||
timeout = EthersReceiptTimeoutBlks):
|
timeout = EthersReceiptTimeoutBlks):
|
||||||
Future[TransactionReceipt]
|
Future[TransactionReceipt]
|
||||||
{.async, upraises: [EthersError].} =
|
{.async, upraises: [ProviderError, EthersError].} =
|
||||||
## Waits for a transaction to be mined and for the specified number of blocks
|
## Waits for a transaction to be mined and for the specified number of blocks
|
||||||
## to pass since it was mined (confirmations).
|
## to pass since it was mined (confirmations).
|
||||||
## A timeout, in blocks, can be specified that will raise an error if too many
|
## A timeout, in blocks, can be specified that will raise an error if too many
|
||||||
@ -237,6 +262,7 @@ proc confirm*(tx: TransactionResponse,
|
|||||||
|
|
||||||
if txBlockNumber + confirmations.u256 <= blockNumber + 1:
|
if txBlockNumber + confirmations.u256 <= blockNumber + 1:
|
||||||
await subscription.unsubscribe()
|
await subscription.unsubscribe()
|
||||||
|
await tx.provider.ensureSuccess(receipt)
|
||||||
return receipt
|
return receipt
|
||||||
|
|
||||||
proc confirm*(tx: Future[TransactionResponse],
|
proc confirm*(tx: Future[TransactionResponse],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user