Feat/pre ipo claim - #119
Conversation
Pull Request ReviewThis Solidity UUPS upgrade adds BOT-managed, time-delayed Merkle settlement roots and permissionless claims for refunds and share-token allocations. It also introduces settlement state, role administration, configurable review periods, and extensive Foundry tests for the new workflow. Sensitive ContentNo sensitive content detected. Security Issues🟠 [HIGH] Declared refund total is not enforced during claims
Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits. |
50b1dc9 to
a6270a2
Compare
Pull Request ReviewThis Solidity/UUPS upgrade adds a two-step, role-controlled settlement Merkle root lifecycle and permissionless claims for deposit refunds and share-token delivery. It appends settlement accounting storage, initializes a six-hour review period, and adds Foundry tests covering settlement, claims, roles, and initialization. Sensitive ContentNo sensitive content detected. Security Issues🟠 [HIGH] Claims are not bounded by the committed total refund
🟠 [HIGH] Finalized settlements can be replaced and refund commitments reused
Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits. |
a6270a2 to
d6fd6bd
Compare
Pull Request ReviewThis Solidity/UUPS upgrade adds a two-step, time-delayed Merkle settlement lifecycle and permissionless one-time claims for refunds and share-token allocations. It appends settlement storage, introduces Sensitive ContentNo sensitive content detected. Security IssuesNo serious security issues detected. Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits. |
- M02: setPublicRound reverts once a settlement root is pending/finalized - I02: remove redundant root inequality check in setSettlementRoot - I03: pause now gates setSettlementRoot / finalizeSettlement / claim - I04: document emergencyWithdraw accounting caveat (NatSpec) - I09: cache duplicate deposit storage read in depositWhitelist - I10/I14: complete claim param docs, header, tranche + permissionless-claim docs - I13: add previewClaim read-only helper L03 handled operationally; M01/L01/I01/I05-I08/I11/I12 acknowledged; L02 pending xKLSH address. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Audi fix: Pre-IPO
Pull Request ReviewThis Solidity UUPS upgrade adds a two-step, time-delayed Merkle settlement lifecycle and permissionless, single-use claims for refunds and share-token delivery. It appends settlement storage, introduces Sensitive ContentNo sensitive content detected. Security IssuesNo serious security issues detected. Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits. |
Summary
Adds settlement + claim to
PreIPODistributor, on top of the subscription contract. After the whitelist and public rounds close, the manager/bot publish a single settlement merkle root (both rounds combined) through a two-step, time-delayed lifecycle; users then make one permanent claim that pays their USDT refund and either delivers the share token (unlocked tranche) or records the amount for off-chain delivery (locked tranche). The allocation math (weighted pro-rata + cap + waterfall) stays off-chain — the contract only verifies and pays out results committed in the root.What's added
LendingRewardsDistributorV2):setSettlementRoot(saleId, root, totalRefund)— BOT, step 1; writes the pending root and starts the review window. Guards: root non-zero/new, no pending already in flight, andtotalRefund <= totalDeposits + pubTotalDeposits.finalizeSettlement(saleId)— BOT, step 2; promotes pending → active only afterwaitingPeriod(min 6h).revokeSettlementRoot(saleId)/setWaitingPeriod(seconds)— MANAGER.claim(saleId, account, refundAmount, shareToken, tokenAmount, proof)— permissionless, once per account, permanent. Verifies the leaf, pays the refund, then routes by the on-chainuserTranche: unlocked → transferstokenAmountofshareToken; locked → refund only, amount emitted for off-chain delivery.initializeV2()(reinitializer(2)) — setswaitingPeriod = 6h; called at upgrade time so no post-upgrade config is needed.Settlementstruct (root/pendingRoot/pendingTotalRefund/totalRefund/lastSetTime/refunded),settlements,claimed,waitingPeriod.Design decisions
shareTokenis in the leaf —leaf = keccak256(abi.encode(chainid, saleId, account, refundAmount, shareToken, tokenAmount))— so no separatesetShareTokenstep; the address is locked by the finalized root. Delivery mode is still routed by the on-chainuserTranche(set at deposit).shareToken != 0— a zero share token is only valid for the locked tranche; otherwiseclaimreverts with a clear error instead of a cryptic transfer failure.totalRefundis the committed total (constant after finalize);refundedaccumulates per claim, sooutstanding = totalRefund - refundedis readable on-chain.withdrawProceeds— proceeds are withdrawn via the existingemergencyWithdraw(MANAGER), which already covers this; the settlement guard keeps a published root from over-committing refunds.Upgrade
UUPS; storage strictly appended over the subscription contract. Apply with
upgradeToAndCall(newImpl, abi.encodeCall(PreIPODistributor.initializeV2, ()))sowaitingPeriodis initialized atomically with the upgrade.Testing
forge test --match-contract PreIPODistributorTest