Skip to content

Vesting: no aggregate getters, so index: None silently touches only the newest schedule #360

Description

@zachyo

File: contracts/vesting/src/lib.rs lines 536 to 547 (_resolve_schedule_index), lines 399 to 408

Issue: _resolve_schedule_index defaults None to count - 1, the newest schedule. That default is applied consistently across release, revoke, get_schedule, vested_amount, and released_amount, which is good, but it makes every single-value API quietly wrong for a multi-schedule recipient:

None => {
    assert!(count > 0, "no schedule found");
    count - 1
}

A recipient with three tranches who calls release(me, None) claims from the newest one only and has no signal that two others hold claimable tokens. vested_amount(me, None) reports the newest schedule's figure, so any integration or dashboard that trusts it under-reports the recipient's position. The frontend works around this by fetching get_schedule_count and looping (PersonalDashboard.tsx:219-224, ClaimVesting.tsx:61), which is N+1 RPC calls and puts correctness in the caller's hands.

Fix: Add aggregate getters that do the summing on chain: total_vested(recipient), total_released(recipient), total_releasable(recipient), and a get_all_schedules(recipient) -> Vec<VestingSchedule> so the UI needs one call rather than count + 1. Add release_all(recipient) that iterates every non-revoked schedule and transfers the combined releasable amount in a single transaction, which is the operation recipients actually want. Then point the frontend at these and delete the loops.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions