Skip to content

Commit

Permalink
Add cancel on error during filling state
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
emizzle committed Sep 12, 2023
1 parent e7dd4d5 commit 2523ab1
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 4 deletions.
9 changes: 8 additions & 1 deletion codex/contracts/market.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down
11 changes: 11 additions & 0 deletions codex/market.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 3 additions & 2 deletions codex/sales/states/filling.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions tests/codex/helpers/mockmarket.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion vendor/nim-ethers

0 comments on commit 2523ab1

Please sign in to comment.