Skip to content

CYS3-06: Policies Can Be Backed By Unswappable Collateral - #106

Merged
evercoinx merged 3 commits into
mainfrom
serge/CYS306
May 9, 2026
Merged

evercoinx merged 3 commits into
mainfrom
serge/CYS306

Conversation

@evercoinx

@evercoinx evercoinx commented May 7, 2026 •

Copy link
Copy Markdown
Contributor

Note

High Risk
High risk because it changes core policy-binding invariants and introduces time-based route/target locks in Swapper, which can block admin reconfiguration and affect claim settlement if mis-wired or misconfigured.

Overview
Fixes CYS3-06 by adding bind-time validation that every non-payout collateral token has a working Swapper quote route to the policy payoutToken, and by locking those routes until policy maturity so they can’t be disabled or pointed at a new target while policies are active.

PolicyManager.bindPolicy now calls ClaimManager.validateAndLockCollateralRoutes before counting collateral toward the USD backing check; Swapper adds claimManager wiring plus route/target lock tracking and enforces the locks in setSwapRoute and setSwapTargetWhitelist. Wiring/scripts, docs, and unit/fork tests are updated to require Swapper.setClaimManager(claimManager) and to cover the new revert/lock behaviors.

Reviewed by Cursor Bugbot for commit 521a538. Bugbot is set up for automated code reviews on this repo. Configure here.

@evercoinx evercoinx self-assigned this May 7, 2026
@dB2510 dB2510 changed the title fix: implement CYS3-06 fix CYS3-06: Policies Can Be Backed By Unswappable Collateral May 8, 2026
@evercoinx
evercoinx requested a review from dB2510 May 9, 2026 04:11
Comment thread src/Swapper.sol
Comment on lines +52 to +54
address public override claimManager;
mapping(bytes32 routeKey => uint256 lockedUntil) private _routeLockedUntil;
mapping(address target => uint256 lockedUntil) private _targetLockedUntil;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

these change will not collide with the existing storage variables, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, we will just extend the storage, not replace it.

Comment thread src/PolicyManager.sol
* `payoutToken` (via `ClaimManager.validateAndLockCollateralRoutes`), locks those routes
* until `maturityTime`, and returns the aggregate USD value of all staked collateral.
*/
function _validateRoutesAndComputeStake(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why you moved total stake calculation inside this function?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The stake computation was moved inside precisely to enforce the invariant from the audit: collateral should only count toward backing if it can actually be used for settlement. If the stake loop lived separately in bindPolicy(), we would have a logical gap where totalStakeUSD gets computed unconditionally for all tokens, but route validation could revert later.

@evercoinx
evercoinx merged commit c724726 into main May 9, 2026
5 checks passed
@evercoinx
evercoinx deleted the serge/CYS306 branch May 9, 2026 14:11
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.

2 participants