From 58a97856b4f2d2af76b3e746713040d1f8531e16 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 +++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/codex/contracts/market.nim b/codex/contracts/market.nim index deba47d6..4e0c63a2 100644 --- a/codex/contracts/market.nim +++ b/codex/contracts/market.nim @@ -110,7 +110,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 be0d06fc..198deed2 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 91faad2a..fb9da4d6 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 867a3ef5..38d93a96 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,