From 2523ab15ef8e7ec77331d00582f6f3f9a5646135 Mon Sep 17 00:00:00 2001 From: Eric <5089238+emizzle@users.noreply.github.com> Date: Tue, 12 Sep 2023 12:35:03 +1000 Subject: [PATCH] Add cancel on error during filling state When calling fillSlot, any transaction errors that occur (possibly during estimate gas) will cause that tx to be replaced with a cancellation transaction (a 0-valued tx to ourselves). --- codex/contracts/market.nim | 9 ++++++++- codex/market.nim | 11 +++++++++++ codex/sales/states/filling.nim | 5 +++-- tests/codex/helpers/mockmarket.nim | 3 +++ vendor/nim-ethers | 2 +- 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/codex/contracts/market.nim b/codex/contracts/market.nim index 3ad707105..3a8b6d016 100644 --- a/codex/contracts/market.nim +++ b/codex/contracts/market.nim @@ -120,7 +120,14 @@ method getActiveSlot*(market: OnChainMarket, return none Slot raise e -method fillSlot(market: OnChainMarket, +proc cancelTransaction(market: OnChainMarket, nonce: UInt256) {.async.} = + let address = await market.getSigner() + let cancelTx = Transaction(to: address, value: 0.u256, nonce: some nonce) + let populated = await market.signer.populateTransaction(cancelTx) + trace "cancelling transaction to prevent stuck transactions", nonce + discard market.signer.sendTransaction(populated) + +method fillSlot*(market: OnChainMarket, requestId: RequestId, slotIndex: UInt256, proof: seq[byte], diff --git a/codex/market.nim b/codex/market.nim index be0d06fc0..198deed21 100644 --- a/codex/market.nim +++ b/codex/market.nim @@ -76,6 +76,17 @@ method getActiveSlot*( raiseAssert("not implemented") +method cancelTransaction(market: Market, nonce: UInt256) {.base, async.} = + raiseAssert("not implemented") + +template cancelOnError*(market: Market, body) = + try: + body + except JsonRpcProviderError as e: + if e.nonce.isSome: + # send a 0-valued transaction with the errored nonce to prevent stuck txs + await market.cancelTransaction(!e.nonce) + method fillSlot*(market: Market, requestId: RequestId, slotIndex: UInt256, diff --git a/codex/sales/states/filling.nim b/codex/sales/states/filling.nim index 91faad2a2..fb9da4d61 100644 --- a/codex/sales/states/filling.nim +++ b/codex/sales/states/filling.nim @@ -36,5 +36,6 @@ method run(state: SaleFilling, machine: Machine): Future[?State] {.async.} = raiseAssert("no slot index assigned") debug "Filling slot", requestId = $data.requestId, slotIndex - await market.fillSlot(data.requestId, slotIndex, state.proof, collateral) - debug "Waiting for slot filled event...", requestId = $data.requestId, slotIndex + market.cancelOnError: + await market.fillSlot(data.requestId, slotIndex, state.proof, collateral) + debug "Waiting for slot filled event...", requestId = $data.requestId, slotIndex diff --git a/tests/codex/helpers/mockmarket.nim b/tests/codex/helpers/mockmarket.nim index 867a3ef58..38d93a969 100644 --- a/tests/codex/helpers/mockmarket.nim +++ b/tests/codex/helpers/mockmarket.nim @@ -205,6 +205,9 @@ proc emitRequestFailed*(market: MockMarket, requestId: RequestId) = subscription.requestId.isNone: subscription.callback(requestId) +proc cancelTransaction(market: Market, nonce: UInt256) {.async.} = + discard + proc fillSlot*(market: MockMarket, requestId: RequestId, slotIndex: UInt256, diff --git a/vendor/nim-ethers b/vendor/nim-ethers index 6c191d60f..15245e189 160000 --- a/vendor/nim-ethers +++ b/vendor/nim-ethers @@ -1 +1 @@ -Subproject commit 6c191d60f1475d481b225a417103a501aab10460 +Subproject commit 15245e189b63bb2b8f7209675d246e5fde2cbc0d