Skip to content

Introduce pledge reversability in KWR#90

Open
adnanhq wants to merge 18 commits intomainfrom
feat/kwr-void-pledge
Open

Introduce pledge reversability in KWR#90
adnanhq wants to merge 18 commits intomainfrom
feat/kwr-void-pledge

Conversation

@adnanhq
Copy link
Copy Markdown
Contributor

@adnanhq adnanhq commented Apr 16, 2026

Summary

KeepWhatsRaised adds void pledge (ops/admin unwind without burning the NFT), optional forward tips on pledge, separate void accounting vs refunds, and on cancellation, route all disbursed fee balances in disburseFees to the platform admin. Unit tests cover the new behavior end-to-end.


Void pledge

  • voidPledge(tokenId)PLATFORM_HASH platform admin only. For chargebacks / lost disputes: unwinds that pledge’s current on-chain position; receipt NFT is not burned (unlike claimRefund, which burns and pays the backer).
  • “Active pledge” = s_tokenIdToPledgeToken[tokenId] != 0. Fails with KeepWhatsRaisedVoidPledgeNotFound if already cleared or never valid (covers tip-only the same way as principal pledges).
  • Ledgers: _clearPledgeLedger (shared with claimRefund) decrements current raised and clears per-pledge state. Voided principal is tracked in s_tokenVoidedAmounts and exposed via getVoidedAmount(). getLifetimeRaisedAmount() stays a monotonic “ever raised”; getRefundedAmount() is lifetime − current raised − voided so voids are not double-counted as refunds.
  • To platform admin (one transfer per token): up to (a) net still in s_availablePerToken, (b) imputed protocol + platform fee components of this pledge, only from the shared fee buckets if this pledge is newer than the last disburseFees boundary: tokenId > s_lastFeeDisbursedPledgeTokenId[pledgeToken] (otherwise no fee-bucket draw — avoids clawing from pooled, post-disburseFees state). (c) Unclaimed pooled tip, only while !s_tipClaimed, from s_tipPerToken, capped by the pledge’s tip. Everything is clamped so the call never underflows, including late voids (after withdraw, disburseFees, claimTip paths, or claimFund).
  • Disbursement boundary — on each successful disburseFees, s_lastFeeDisbursedPledgeTokenId[token] is set to s_lastMintedPledgeTokenId; that is the “fee snapshot” the void path uses.
  • Tips: s_tipClaimedPerToken records what the platform already received (forwarding + claimTip); it is not decremented. Forwarded or already-claimed money is not pulled back; only what’s still represented as reclaimable in the right pools is in play.

Optional tip forwarding (forwardTipsImmediately)

  • New config flag. When on: on pledge, tips go immediately toward the platform (Permit2: ERC20 to admin; admin / setFeeAndPledge when the “source is already the platform” — do not take the full pledge+tip twice from that side). Pooled accrual to s_tipPerToken[pledgeToken] is the off path. claimTip reverts with KeepWhatsRaisedTipsAlreadyForwarded. TipForwarded and **s_tipClaimedPerToken += tip` on the forward path.
  • getTipClaimedPerToken(address) — total tips the platform is counted as having received for that token. When tips were pooled and then claimTip runs, transferred amounts are also added to s_tipClaimedPerToken.

disburseFees when cancelled

  • Not cancelled: unchanged — protocol and platform shares go to protocol and platform admins. Cancelled (same notion as the rest of this contract for refund / claimFund — i.e. treasury and/or campaign in cancellation): all accumulated protocol and platform fee balances in that disbursal for each token are sent to the platform admin; FeesDisbursed reflects “all in the platform line” for the protocol share in that case. Callable so fees are not stuck; each call still updates the fee boundary that voidPledge uses (see above).

Tests

Unit coverage for access, full/partial/zero platform recovery, disburseFees ordering vs void, post-withdraw and post-claimFund, cancelled camp, both tip modes, refund vs void, and multi-pledge / multi-token cases; config defaults where the new flag is set.

Suvadra-Barua and others added 10 commits April 2, 2026 21:24
Cover the three key behaviors when Config.forwardTipsImmediately is true:
- claimTip() reverts with KeepWhatsRaisedTipsAlreadyForwarded
- Permit2 pledge forwards tip to platform admin at pledge time
- Admin setFeeAndPledge splits pledge vs tip accounting correctly

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
test(foundry): add forwardTipsImmediately unit tests
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 92ae3d44ce

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/treasuries/KeepWhatsRaised.sol
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: afbffc5183

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/treasuries/KeepWhatsRaised.sol Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0d7a480c63

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/treasuries/KeepWhatsRaised.sol Outdated
@adnanhq adnanhq changed the title Introduce VoidablePledge module for pledge reversal in KWR Introduce pledge reversability in KWR Apr 17, 2026
adnanhq and others added 4 commits April 17, 2026 23:41
…es, drop getTotalTipClaimed to stay under bytecode limit
…ed treasuries (#84)

* feat(KeepWhatsRaised): redirect all fees to platform admin on cancelled treasuries

* test(KeepWhatsRaised): redirect all fees to platform admin on cancelled treasuries
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fb4fc73653

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/treasuries/KeepWhatsRaised.sol Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5682b11821

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread foundry.toml
via_ir = true
optimizer = true
optimizer_runs = 200
optimizer_runs = 1
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore optimizer runs for production profile

Changing optimizer_runs from 200 to 1 in the default Foundry profile materially shifts optimization toward deployment cost and away from runtime execution, which can significantly increase gas usage for all user-facing contract calls and produce different bytecode than prior audited/deployed expectations. Unless this is intentionally scoped to a separate local/test profile, this default change is a performance regression for production builds.

Useful? React with 👍 / 👎.

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.

3 participants