OpenZeppelin audit remediations: payment/pledge hardening, lifecycle enforcement, accounting fixes, and error-code cleanup#75
Conversation
…ee disbursement before or after cancellation, ensuring accrued fees are not trapped. (OZ-7) (#18)
…hatsRaised (OZ-9) (#19) - Enhanced comments to specify the time delay for withdrawals after the campaign deadline, detailing the conditions under which withdrawals are allowed.
* Refactor fee handling in KeepWhatsRaised contract - Introduced flat and cumulative flat fee values, replacing the previous fee mapping. - Added checks for unique fee keys and validation for percentage fee limits. - Updated getFeeValue function to accommodate new fee structure. - Emitted new errors for duplicate fee keys and percentage fee violations. * Add unit tests for treasury configuration in KeepWhatsRaised contract - Implemented tests to ensure proper error handling for duplicate flat and percentage fee keys. - Added checks for maximum percentage fee limits and aggregate percentage constraints. - Enhanced test coverage for the configureTreasury function to validate fee configurations. * Refactor fee calculation in KeepWhatsRaised contract
…16) (#23) - Introduced a check to ensure the current time is within the launch and deadline range, enhancing the campaign scheduling logic.
…contract (OZ-26) (#25) - Introduced a new error, FiatEnabledTransactionAlreadyRecorded, to handle cases where a fiat transaction ID has already been recorded. - Updated the _updateFiatTransaction function to revert with the new error if a duplicate transaction ID is detected.
* Use named parameters for public getter functions * Add named return params to aggregate getter functions in CampaignInfo
- Introduced a constant PERCENT_DIVIDER to enforce a maximum of 100% for fee percentages. - Added error handling to revert transactions when fee percentages exceed the allowed limits. - Updated functions to check both individual and combined fee percentages for protocol and platform fees, ensuring compliance with the new validation rules.
…sed contract (OZ-33) (#27) - Introduced a new error, KeepWhatsRaisedFundAlreadyClaimed, to handle attempts to claim funds after they have already been claimed. - Updated the claim functions to revert with this error if the funds have been claimed, enhancing the contract's robustness and clarity in fund management.
…ntract (OZ-40) (#28) * Add error handling for platform data key ownership in CampaignInfo contract - Introduced a new error, CampaignInfoPlatformDataKeyNotOwnedByPlatform, to handle cases where a platform data key is not owned by the platform being updated. - Updated the relevant function to revert with this error if the ownership check fails. * Refactor test_UpdateSelectedPlatform to simplify platform data handling - Reduced the number of platform data keys and values from two to one in the test case for updating the selected platform. - Removed assertions related to the second platform data key to streamline the test and focus on the primary key-value pair.
* Restrict pledge NFT burn function to only treasuries * Add tests for treasury restricted NFT burn
- Simplified the protocol fee application logic by removing redundant variables and directly calculating the net amount based on whether the protocol fee is applied
…9) (#33) * Refactor campaign management functions in CampaignInfo contract - Renamed internal functions to public for better clarity and accessibility: _pauseCampaign to pauseCampaign, _unpauseCampaign to unpauseCampaign, _cancelCampaign to cancelCampaign, and _setPlatformInfo to setPlatformInfo. - Updated corresponding calls in TreasuryFactory to reflect the new function names. * Refactor campaign management function calls in unit tests - Updated unit tests in CampaignInfo and PaymentTreasury contracts to reflect the renaming of internal functions to public: _pauseCampaign to pauseCampaign, _unpauseCampaign to unpauseCampaign, _cancelCampaign to cancelCampaign, and _setPlatformInfo to setPlatformInfo. - Ensured all relevant test cases are aligned with the new function names for consistency and clarity.
- Introduced a new error for handling duplicate item IDs in batch operations. - Implemented logic to reject duplicate item IDs within the batch to prevent duplicate event emissions.
…t (OZ-13) (#47) - Implemented a new internal function `_colombianCreatorTax` to compute the Colombian creator tax based on net and gross amounts, ensuring compliance with local regulations. - Updated withdrawal logic to clarify tax application for partial and final withdrawals, enhancing documentation for better understanding of fee structures.
…Z-21) (#50) * Add 'canBeAddOn' field to Reward struct and update validation checks in AllOrNothing and KeepWhatsRaised contracts - Introduced a new boolean field 'canBeAddOn' in the Reward struct within IReward interface. - Updated input validation in AllOrNothing and KeepWhatsRaised contracts to check for 'canBeAddOn' alongside 'rewardValue' to ensure proper reward handling. * Update KeepWhatsRaised unit tests to incorporate 'canBeAddOn' parameter in reward creation and add new test for pledge validation with add-on restrictions - Modified existing tests to use the updated _createTestReward function, now including the 'canBeAddOn' parameter. - Added a new test case to validate that pledging for a reward with an invalid add-on configuration correctly reverts the transaction.
#52) * Add campaign info validation to TreasuryFactory - Introduced a new function `setCampaignInfoFactory` to set the address of the CampaignInfoFactory, ensuring it is not a zero address. - Added error handling for invalid campaign info in the deployment process. - Updated the TreasuryFactoryStorage to include a reference to the campaignInfoFactory. - Enhanced the ICampaignInfoFactory interface with a method to validate campaign info addresses. * Update tests to integrate CampaignInfoFactory into TreasuryFactory - Connected the CampaignInfoFactory to the TreasuryFactory by adding a call to `setCampaignInfoFactory` in the test setup. - This ensures that the TreasuryFactory can validate the CampaignInfoFactory address during testing. * Integrate CampaignInfoFactory into TreasuryFactory across deployment scripts - Added calls to `setCampaignInfoFactory` in multiple deployment scripts to ensure the CampaignInfoFactory is properly wired into the TreasuryFactory for validation during deployment. - Updated the UpgradeTreasuryFactory script to include a check for the CampaignInfoFactory address, enhancing deployment reliability. * Refactor deployment scripts to enhance CampaignInfoFactory integration - Updated multiple deployment scripts to ensure the CampaignInfoFactory is wired into the TreasuryFactory during deployment. - Modified the condition for wiring to account for both newly deployed and reused contracts, improving deployment reliability.
* Add s_feesDisbursed check in BaseTreasury for disburseFees * refactor(AllOrNothing): drop duplicate disburseFees check Rely on BaseTreasury.disburseFees s_feesDisbursed check and remove AllOrNothingFeeAlreadyDisbursed.
* Add configuration checks to KeepWhatsRaised contract - Introduced a new state variable `s_configured` to track if the treasury has been configured. - Added a new error `KeepWhatsRaisedAlreadyConfigured` to prevent reconfiguration attempts. - Updated the `configureTreasury` function to revert if called after the treasury has been configured, enhancing contract safety. * Add treasury reset functionality and update tests - Introduced a new internal function `_resetTreasury` to deploy a fresh campaign and treasury, facilitating initial configuration in tests. - Updated existing tests to utilize `_resetTreasury` for setting up fresh treasuries, ensuring accurate state validation and error handling. - Enhanced clarity in test comments to reflect the purpose of treasury resets during configuration.
…3) (#71) * Improve error clarity by including revert reasons in treasuries * fix(errors): use string instead of bytes32 for error reason params Switch AllOrNothingInvalidInput, AllOrNothingNotClaimable, KeepWhatsRaisedInvalidInput, and KeepWhatsRaisedNotClaimable to use string reason for clearer off-chain decoding. Add natspec for reason params and use more specific reason strings (e.g. REWARD_LENGTH_MISMATCH, FEE_LENGTH_MISMATCH). Update tests to use abi.encodeWithSelector. * improve(errors): use distinct reason strings for liquidity failures - KeepWhatsRaised: split claimRefund checks so liquidity failures revert with INSUFFICIENT_LIQUIDITY instead of ZERO_AMOUNT. - BasePaymentTreasury: add string reason to PaymentTreasuryInvalidInput and PaymentTreasuryPaymentNotClaimable; use distinct reasons for each case; split combined claimRefund checks (ZERO_AMOUNT, INSUFFICIENT_LIQUIDITY, INSUFFICIENT_GOAL_LIQUIDITY, INSUFFICIENT_NON_GOAL_LIQUIDITY, INSUFFICIENT_CONTRACT_BALANCE, NOT_NFT_PAYMENT).
…tract (OZ-8) (#49) * Refactor withdrawal and disbursement functions in KeepWhatsRaised contract - Updated function modifiers to ensure compliance with campaign status before executing actions. * Update tests in KeepWhatsRaised unit tests to utilize _resetTreasury for improved state management - Added calls to _resetTreasury in multiple test cases to ensure a clean state before executing treasury configuration tests. - Enhanced clarity in tests by ensuring that each test starts with a fresh treasury setup, improving reliability and accuracy of error handling.
…izes in BasePaymentTreasury contract (OZ-35) (#51) - Introduced constants for maximum line items, external fees, and batch size to ensure input validation. - Added error handling for exceeding array lengths to improve robustness of payment processing functions.
Remove whenNotCancelled modifier from claimRefund in PaymentTreasury and TimeConstrainedPaymentTreasury. Previously, treasury cancellation blocked user refunds while admin sweep functions remained callable, creating a fund locking vulnerability.
* Add pre campaign launch time constraint to removeReward
* Refactor error handling in BasePaymentTreasury contract - Updated revert statements to use `paymentId` instead of `internalPaymentId` for better clarity and consistency in error messages related to payment existence, confirmation, and claimability. * Refactor payment claim validation in BasePaymentTreasury to improve error handling. * Update tests in KeepWhatsRaised_UnitTest to utilize _resetTreasury for improved state management and error validation in treasury configuration scenarios. --------- Co-authored-by: rayedsikder <rayedsikder33@gmail.com>
…ontract (OZ-51) (#35) * Add item existence checks and removal functionality in ItemRegistry contract - Introduced a mapping to track item existence for each owner. - Added error handling for adding duplicate items and removing non-existent items. - Implemented an event for item removal. - Updated addItem and removeItem functions to incorporate new checks and emit appropriate events. * Refactor item existence checks in ItemRegistry contract - Moved the item existence check for duplicates to occur after the initial loop, ensuring proper validation before adding items. - Maintained error handling for duplicate item IDs and existing items to enhance contract reliability.
…cts (OZ-52) (#36) * Refactor pledge processing in AllOrNothing and KeepWhatsRaised contracts - Updated the _pledge function to ensure pledgeAmount and shippingFee are always in the token's native decimals, removing the need for denormalization by the caller. - Enhanced documentation for the _pledge function to clarify parameter requirements and processing logic. - Adjusted related calculations and state updates to reflect the new handling of pledge amounts and fees. * Add token acceptance checks in AllOrNothing and KeepWhatsRaised contracts - Implemented checks to ensure that the pledge token is accepted before processing pledges. - Added specific revert messages for each contract to improve error handling and clarity in case of unsupported tokens. * Block treasury deployment after deadline or when campaign cancelled Made-with: Cursor --------- Co-authored-by: adnanhq <adnan.haque1210@gmail.com>
* Refactor error handling in treasury contracts - Introduced specific error messages for various invalid input scenarios in CampaignInfoFactory, AllOrNothing, KeepWhatsRaised, and BasePaymentTreasury contracts. - Enhanced clarity and granularity of error handling by replacing generic reverts with more descriptive custom errors, improving debugging and user feedback. * Update error handling in KeepWhatsRaised unit tests - Replaced generic revert messages with specific custom errors for invalid input scenarios in the KeepWhatsRaised contract tests, enhancing clarity and improving debugging capabilities. - Updated tests to reflect changes in error handling for launch time, first reward tier, and claim fund window conditions.
…received amount minus shipping fee - This change ensures accurate NFT minting based on the net pledge amount.
… (OZ-01) (#74) * Add off-chain approval and args integrity validation for payment flows using Permit2 * Fix empty permit fallback in KWR, add Uniswap deps and update tests * Add permit2 submodule gitlink to fix CI builds * Use Mock Permit2 in tests to avoid solc mismatch * refactor: extract shared refund logic to helper function Reduces contract size across PaymentTreasury variants by removing duplicated refund logic. * Update _validatePaymentForAction function in BasePaymentTreasury contract to accept paymentId for improved clarity in revert messages. - This change enhances error handling by ensuring that the external payment ID is used in all relevant error scenarios, providing better feedback to users. --------- Co-authored-by: adnanhq <adnan.haque1210@gmail.com> Co-authored-by: Mahabub Alahi <mahabub@ccprotocol.xyz>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cfa314e407
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c894c9437
ℹ️ 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".
…he board (#79) * refactor core admin access around protocol admin * Remove redundant _msgSender() instances in core contracts
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6bd5dc9e3a
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b153c8c602
ℹ️ 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".
Summary
This PR merges the OpenZeppelin audit remediation set into
mainand consolidates the issue-by-issue fixes that were previously landed as separate PRs.Overall, this PR hardens signature-based payment and pledge flows, closes refund / cancellation / fee-disbursement edge cases, tightens campaign and treasury lifecycle enforcement, improves fee and refund accounting, strengthens input validation across core protocol contracts, and standardizes error handling to improve off-chain decoding while reducing bytecode size.
What changed
1. Signature, transfer, and fund-safety hardening
This PR closes the critical issues around token movement and signature use:
processCryptoPayment,pledgeForAReward, andpledgeWithoutAReward. The signed witness now commits to the exact payload being executed (for example: payment IDs, item IDs, buyer/backer, amounts, reward hashes, line item hashes, tips/shipping fees), so callers cannot front-run or tamper with signed arguments.nonReentrantprotection toBaseTreasury.disburseFees()and moves the fee-disbursed state transition into the protected path.PaymentTreasuryandTimeConstrainedPaymentTreasury, preventing cancellations from trapping refundable user funds.TREASURY_ROLE) instead of allowing arbitrary burn paths._msgSender()overrides so a malformed forwarder payload cannot resolve toaddress(0).2. Treasury lifecycle, campaign lifecycle, and admin-path enforcement
This PR tightens when protocol actions are allowed and who can perform them:
OZ-07 allows
KeepWhatsRaised.disburseFees()to run even after cancellation so already-accrued fees cannot get trapped.OZ-08 adds missing campaign-state checks to
KeepWhatsRaisedwithdrawal / fee-disbursement paths so those functions respect campaign pause/cancel status consistently.OZ-11 enforces campaign lifecycle rules for treasury onboarding and campaign config updates:
OZ-15 validates
withdrawalDelay >= refundDelayinKeepWhatsRaised, ensuring admin fund-claim windows cannot open before the refund window ends.OZ-16 adds the missing campaign time-window restriction to
setFeeAndPledge.OZ-20 restricts reward removal to pre-launch only.
OZ-27 makes
KeepWhatsRaised.configureTreasury()a one-time action and prevents accidental reconfiguration after initial setup.OZ-42 wires
TreasuryFactorytoCampaignInfoFactoryand validates thatinfoAddresspassed intodeploy()is a valid factory-createdCampaignInfo.A related follow-up changes treasury initialization to stop storing a static trusted forwarder and instead resolve the current platform adapter dynamically from
CampaignInfo/GlobalParams, so adapter rotations take effect immediately for deployed treasuries.3. Accounting, fee, and refund correctness
A large part of this PR is focused on removing ambiguity from treasury accounting:
KeepWhatsRaisedby separating flat fees from percentage fees, validating unique fee keys, and enforcing both per-fee and aggregate percentage bounds.s_feesDisbursedguard so fees cannot be disbursed twice.canBeAddOntoRewardand enforces add-on eligibility instead of implicitly treating every reward as add-on capable.BasePaymentTreasury.GlobalParams, including both per-value caps and combined protocol+platform fee bounds.KeepWhatsRaised.BasePaymentTreasuryrefund validation and error reporting by using the external payment ID in errors and by separating liquidity failures into clearer conditions.BasePaymentTreasury.AllOrNothing._pledge.AllOrNothingandKeepWhatsRaisedso amounts are consistently handled in token-native decimals at the right boundary.AllOrNothingmints the NFT using the actual received pledge amount minus shipping fee, not the pre-transfer nominal pledge amount.4. Validation, uniqueness, and data-integrity checks
This PR adds a broad set of missing validation checks across protocol state:
removePlatformData.imageURIJSON before accepting updates / initialization.CampaignInfoFactoryimplementation is updated.ItemRegistrybatch adds.ItemRegistry.PausableCancellableinstead of relying on duplicate interface definitions.uncheckedloop increments.__BaseContract_init.AllOrNothingFeeAlreadyDisburseddocstring.5. Documentation, storage, and maintainability cleanup
Several changes improve readability and maintainability while keeping behavior aligned with the audited design:
ccprotocol.*names tooaknetwork.*._disableInitializers()in base treasuries._safeMint/IERC721Receiverrequirements for pledge recipients.pauseCampaign,unpauseCampaign,cancelCampaign,setPlatformInfo).KeepWhatsRaised.withdraw.TreasuryErrors) and does the same for core contracts viaProtocolErrors, reducing bytecode while preserving machine-readable failure reasons.KeepWhatsRaisedtransfer path after the Permit2 migration made them unnecessary.6. Admin model and deployment-path cleanup
The tail of the patch also includes protocol-wide cleanup that supports the remediation set:
Ownableusage where protocol-admin authority is the real top-level control planeCampaignInfoFactory.initializeand related script/test wiringNotable interface / behavior changes
Reviewers and integrators should pay attention to these externally visible changes:
processCryptoPayment(...)now takesPermitDataAllOrNothing.pledgeForAReward(...)andpledgeWithoutAReward(...)now takePermitDataKeepWhatsRaised.pledgeForAReward(...)andpledgeWithoutAReward(...)now takePermitDatainitialize(...)no longer accepts a cached trusted-forwarder argument; platform adapter resolution is dynamicCampaignInfoFactory.initialize(...)changed as part of the protocol-admin authority cleanupTesting
This PR updates and extends unit / integration / upgrade coverage across:
CampaignInfoCampaignInfoFactoryGlobalParamsTreasuryFactoryAllOrNothingKeepWhatsRaisedPaymentTreasuryTimeConstrainedPaymentTreasuryPledgeNFTItemRegistryIt also adds
MockPermit2test coverage for the new Permit2-based flows and updates deployment / upgrade tests and scripts accordingly.