Skip to content

Handle contract custom errors in redemptions - #782

Open
evgeny-stakewise wants to merge 1 commit into
v5-releasefrom
redemptions-custom-errors
Open

Handle contract custom errors in redemptions#782
evgeny-stakewise wants to merge 1 commit into
v5-releasefrom
redemptions-custom-errors

Conversation

@evgeny-stakewise

Copy link
Copy Markdown
Contributor

Adds custom error decoding to the redemption transaction paths, following the pattern already used in the harvest task.

Custom error handling

OsTokenRedeemerContract now mixes in ErrorMixin, so reverts can be decoded against its own ABI merged with the shared Errors.json library ABI.

Three call sites in src/redemptions/execution.py go through os_token_redeemer_contract directly rather than the multicall contract, and none of them decoded reverts:

Call site Path Before
tx_process_exit_queue tx_manager.transact no exception handling at all
tx_redeem_position tx_manager.transact broad catch, logged %r
simulate_redeem_position .call() broad catch, logged %r

Each now catches ContractCustomError first and logs decode_custom_error(str(e.data)) or e.data. Verified against the real ABI: 0x09bde339 decodes to InvalidProof(), 0x4ca88867 to AccessDenied().

tx_update_vaults_state is left alone — it submits through the multicall contract.

Exception handling cleanup

The except (Web3Exception, RuntimeError, ValueError) tuples were stale. RuntimeError dated back to when these sites wrapped a helper that raised RuntimeError on a failed receipt; that helper is long gone and tx_manager.transact signals failure by returning None. ValueError predates web3 v7, where every error subclasses Web3Exception. Both catches are now plain except Exception, so a single bad position cannot abort a whole redemption run.

Unconfirmed vs failed transactions

tx_manager.transact returns None on timeout, on status == 0, and on exhausted send retries — so "failed" was misleading. Reworded the three receipt checks in the file to the house pattern (Failed to confirm <thing> tx).

tx_update_vaults_state no longer raises RuntimeError; it returns the tx hash or None, and update_vaults_state stops the chunk loop and returns a bool. process_redeemer now skips the redemption pass when the state update did not fully succeed — previously the RuntimeError aborted the run, and simply dropping it would have let redemptions proceed against stale withdrawable assets and LTVs.

error_verbose

log_verbose logs only the exception instance, so the message describing what failed is lost. Added error_verbose(msg, *args) in src/common/utils.py, mirroring the logger.error signature and delegating to logger.exception when verbose is on. Wired into the two redemption sites that previously logged tracebacks unconditionally.

Note: error_verbose makes settings.verbose a runtime dependency of any code path that calls it, so unit tests reaching those paths need the fake_settings fixture.

Tests

  • custom error decoding on all three redemption paths
  • update_vaults_state return flag, including the stop-on-failure and stop-on-unconfirmed cases
  • process_redeemer skipping redemption on a failed state update
  • error_verbose preserving the message in both modes, with exc_info attached only when verbose

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant