From 988345720dd96ad6670f02b98c23f294e1024d28 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 28 Jan 2026 20:01:25 +0100 Subject: [PATCH 1/2] fix(settlement): use requiredLockup in lockup sufficiency check Per audit recommendation, the lockup check now compares against requiredLockup instead of grossSettledAmount. This is more direct since requiredLockup is what we actually subtract from lockupCurrent. The calculation of actualSettledDuration and requiredLockup is moved before the check to make the comparison possible. Fixes #267 Co-Authored-By: Claude Opus 4.5 --- src/FilecoinPayV1.sol | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/FilecoinPayV1.sol b/src/FilecoinPayV1.sol index 0d1dc78..c92bbf7 100644 --- a/src/FilecoinPayV1.sol +++ b/src/FilecoinPayV1.sol @@ -1463,13 +1463,16 @@ contract FilecoinPayV1 is ReentrancyGuard { Errors.InsufficientFundsForSettlement(rail.token, rail.from, grossSettledAmount, payer.funds) ); + // Calculate required lockup based on actual settled duration + uint256 actualSettledDuration = settledUntilEpoch - epochStart; + uint256 requiredLockup = rate * actualSettledDuration; + // Verify payer has sufficient lockup for the settlement + // We check against requiredLockup (not grossSettledAmount) because that's what we subtract from lockupCurrent require( - payer.lockupCurrent >= grossSettledAmount, - Errors.InsufficientLockupForSettlement(rail.token, rail.from, payer.lockupCurrent, grossSettledAmount) + payer.lockupCurrent >= requiredLockup, + Errors.InsufficientLockupForSettlement(rail.token, rail.from, payer.lockupCurrent, requiredLockup) ); - uint256 actualSettledDuration = settledUntilEpoch - epochStart; - uint256 requiredLockup = rate * actualSettledDuration; // Transfer funds from payer (always pays full settled amount) payer.funds -= grossSettledAmount; From 9eecda44d3ac1e7a11a1815a6e6eaa5c0a98b5c4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 28 Jan 2026 20:17:42 +0100 Subject: [PATCH 2/2] Cleanup --- src/FilecoinPayV1.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/FilecoinPayV1.sol b/src/FilecoinPayV1.sol index c92bbf7..ab65f0d 100644 --- a/src/FilecoinPayV1.sol +++ b/src/FilecoinPayV1.sol @@ -1463,12 +1463,10 @@ contract FilecoinPayV1 is ReentrancyGuard { Errors.InsufficientFundsForSettlement(rail.token, rail.from, grossSettledAmount, payer.funds) ); - // Calculate required lockup based on actual settled duration uint256 actualSettledDuration = settledUntilEpoch - epochStart; uint256 requiredLockup = rate * actualSettledDuration; // Verify payer has sufficient lockup for the settlement - // We check against requiredLockup (not grossSettledAmount) because that's what we subtract from lockupCurrent require( payer.lockupCurrent >= requiredLockup, Errors.InsufficientLockupForSettlement(rail.token, rail.from, payer.lockupCurrent, requiredLockup)