Skip to content

fix(circle): reject zero-net payouts in trigger_payout - #186

Open
fridaypetra55-afk wants to merge 1 commit into
cocor-tech:masterfrom
fridaypetra55-afk:fix/117-circle-reject-zero-payout
Open

fix(circle): reject zero-net payouts in trigger_payout#186
fridaypetra55-afk wants to merge 1 commit into
cocor-tech:masterfrom
fridaypetra55-afk:fix/117-circle-reject-zero-payout

Conversation

@fridaypetra55-afk

Copy link
Copy Markdown
Contributor

Summary

  • trigger_payout computed net/fee via math::apply_fee(pool, fee_bps) but never checked whether net came out to zero. If fees consume the whole pool (small contribution_amount + high fee_bps), the function would still transfer 0 tokens, emit a PayoutExecuted event, advance current_round, and possibly mark the circle STATUS_COMPLETED — wasted gas and a misleading audit trail for something that didn't actually pay anyone out.
  • Added CircleError::ZeroPayoutAmount and a net <= 0 check right after apply_fee, before any transfers or state mutation occur.
  • Added test_trigger_payout_rejects_zero_net_amount, which sets fee_bps to 10000 (100%) so the whole pool is fee, and asserts trigger_payout now fails with ZeroPayoutAmount instead of silently no-op-succeeding.

Note on a pre-existing, unrelated build break

packages/circle/src/contract.rs currently fails to compile on master — confirmed on a clean checkout of upstream/master before any of my changes. 15 functions with Result<(), CircleError> return type end their body with the bare Ok() instead of Ok(()), which doesn't compile (Ok is a 1-argument tuple variant). I fixed all 15 occurrences in this PR since I have to touch this file anyway and couldn't otherwise build or test my change. This appears to have gone unnoticed because the CI workflow (.github/workflows/*.yml) triggers on branches: ["main"], but the repo's default branch is master — so cargo test --workspace has not actually been running in CI.

cargo build -p circle and cargo test -p circle both pass locally after this change (6/6 tests, including the new one).

Closes #117

If fees consume the entire contribution pool (e.g. a small
contribution_amount combined with a high fee_bps), trigger_payout
would previously transfer 0 tokens, still emit a PayoutExecuted
event, and advance current_round — wasting gas and leaving a
misleading audit trail. trigger_payout now rejects with the new
CircleError::ZeroPayoutAmount before any state changes or transfers
happen if net <= 0.

Also fixes a pre-existing, unrelated compile break in this same file:
15 call sites wrote the bare `Ok()` instead of `Ok(())` for a
Result<(), CircleError> return type, so packages/circle currently
fails to build on master at all (confirmed on a clean checkout of
upstream/master). This needed to be fixed for this file to compile
and for the new test to run.

Closes cocor-tech#117
@drips-wave

drips-wave Bot commented Jul 31, 2026

Copy link
Copy Markdown

@fridaypetra55-afk Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

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.

fix(contract): validate payout amount is not zero before executing

1 participant