Skip to content

A failed vault release strands a resolved task's funds permanently, with no retry path #314

Description

@N-thnI

Description

Add a recovery path for tasks that resolved successfully but whose vault release failed.

Problem Statement

src/contracts/voting.rs:22 swallows vault failures by design:

match result {
    Ok(_)  => events::emit_vault_release_success(env, task_id),
    Err(_e) => events::emit_vault_release_failed(env, task_id),
}

This is the deliberate fix for #134 / #184 ("Vault release_funds call is not fault-isolated — a broken vault can permanently block task resolution"), and as a DoS fix it is correct: resolution must not be hostage to a broken vault.

But it traded a denial of service for silent fund-stranding, and the recovery half was never built.

When the release fails, the task is still marked is_done, resolved_at is set, and the task is persisted by storage::set_active_task. The release block is guarded by !t.is_done, so it can never run again for that task.

Searching every .rs file in the crate, release_funds appears only in voting.rs, events.rs and gas.rs. There is no admin retry entrypoint, no pending-release record, and no re-trigger path anywhere in the contract.

So a vault that is paused, underfunded, misconfigured, mid-upgrade, or simply out of gas for one subcall loses that task's payout permanently. The only trace is a vault_release_failed event, which nothing consumes on-chain.

Given the protocol exists to make contributor payouts verifiable, a resolved task whose funds silently never move is a direct failure of its core promise.

Proposed Changes

  • Record failed releases in storage (e.g. DataKey::PendingRelease(task_id)) when try_release_vault_funds fails, rather than only emitting an event
  • Add an entrypoint to retry release for a task with a recorded pending release, callable by the admin or permissionlessly (the vault call is idempotent per task and re-attempting is safe)
  • Clear the pending-release record on a successful retry and emit a success event
  • Expose a read method listing task IDs with outstanding pending releases, so operators can detect stranded funds without replaying events

Technical Implementation Scaffolding

  • Target Repository: vero-core-contracts
  • Target Path: src/contracts/voting.rs, src/contracts/vault_ops.rs, src/types.rs
  • Branch Naming: feat/issue--vault-release-retry
  • Authority Context: Security-sensitive — permanent loss of contributor payouts

Acceptance Criteria

Definition of Done

  • Reviewed by lead maintainer
  • Pull request merged via verified status check

This issue is self-contained. Everything it needs already exists on main; it does not wait on any other issue. Deliver the change and its tests in one PR.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions