Distribution's claim
function does not update storage variables
Description
In Distributor, the claim
function does not work correctly. The poolInfo
is not updated after the claim
, so the amountToDistribute
is not updated. Since the balance decreases while the amountToDistribute
remains the same, once the first claim occurs, other users will not be able to make a claim.
function claim(address _pool) external whenNotPaused() nonReentrant() {
require(_pool != address(0), UnsupportedPool());
// ...
PoolInfo memory poolInfo = poolInfos[_pool];
// check if pool has enough *allocated* shares to distribute
if (poolInfo.amountToDistribute < shares) {
revert NotEnoughSharesToDistribute();
}
// check if the distributor has enough shares tokens as the amount to distribute
if (IERC20(couponToken).balanceOf(address(this)) < poolInfo.amountToDistribute) {
revert NotEnoughSharesToDistribute();
}
poolInfo.amountToDistribute -= shares;
couponAmountsToDistribute[couponToken] -= shares;
// ...
}
Impact
If there are no other pools sharing the coupon token, a revert will occur from the second claimant onward due to the unupdated amountToDistribute
. If such pools exist, it will ultimately cause a balance mismatch, putting the protocol at risk.
The following proof-of-concept script demonstrates that the second claimant receives a revert by the unupdated amountToDistribute
:
function testAuditClaimFailedByPoolInfoNotUpdated() public {
Token sharesToken = Token(_pool.couponToken());
vm.startPrank(minter);
_pool.bondToken().mint(user1, 1*10**18);
_pool.bondToken().mint(user2, 1*10**18);
sharesToken.mint(address(_pool), 20004000000000000000000);
vm.stopPrank();
vm.startPrank(governance);
fakeSucceededAuction(address(_pool), 0);
vm.mockCall(
address(0),
abi.encodeWithSignature("state()"),
abi.encode(uint256(1))
);
vm.warp(block.timestamp + params.distributionPeriod);
_pool.distribute();
vm.stopPrank();
vm.startPrank(user1);
distributor.claim(address(_pool));
vm.stopPrank();
vm.startPrank(user2);
vm.expectRevert();
distributor.claim(address(_pool));
vm.stopPrank();
}
Recommendations
Use storage poolInfo
to update the storage variable.
Remediation
This issue has been acknowledged by Plaza Finance, and a fix was implemented in commit 70eb9503↗.