Platform: Code4rena
Start Date: 21/07/2023
Pot Size: $90,500 USDC
Total HM: 8
Participants: 60
Period: 7 days
Judge: 0xean
Total Solo HM: 2
Id: 264
League: ETH
Rank: 5/60
Findings: 1
Award: $2,663.87
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0x3b
Also found by: T1MOH, osmanozdemir1
2663.8738 USDC - $2,663.87
Admin is allowed to update merkleRoot
. But some users won't be able to claim correct amount because of inconsistent check in claiming function.
Current implementation reverts if user claimed some amount before.
function claimAndDelegate(address delegate, uint128 totalGrant, bytes32[] calldata merkleProof) external { ... _validateWithdraw(totalGrant, merkleProof); ... } function _validateWithdraw(uint256 totalGrant, bytes32[] memory merkleProof) internal { // validate proof and leaf hash bytes32 leafHash = keccak256(abi.encodePacked(msg.sender, totalGrant)); if (!MerkleProof.verify(merkleProof, rewardsRoot, leafHash)) revert AA_NonParticipant(); // ensure the user has not already claimed the airdrop if (claimed[msg.sender] != 0) revert AA_AlreadyClaimed(); claimed[msg.sender] = totalGrant; }
However this can be the case when admin by some reason (for example by mistake setted incorrect amounts before) wants to increase amount for user and submits new merkleRoot
.
merkleRoot
with user amount = 1000if (claimed[msg.sender] != 0) revert AA_AlreadyClaimed();
Manual Review
function claimAndDelegate(address delegate, uint128 totalGrant, bytes32[] calldata merkleProof) external { ... // validate the withdraw - _validateWithdraw(totalGrant, merkleProof); + totalGrant = _validateWithdraw(totalGrant, merkleProof); ... }
- function _validateWithdraw(uint256 totalGrant, bytes32[] memory merkleProof) internal { + function _validateWithdraw(uint256 totalGrant, bytes32[] memory merkleProof) internal returns(uint128 grantedAmount) { // validate proof and leaf hash bytes32 leafHash = keccak256(abi.encodePacked(msg.sender, totalGrant)); if (!MerkleProof.verify(merkleProof, rewardsRoot, leafHash)) revert AA_NonParticipant(); // ensure the user has not already claimed the airdrop - if (claimed[msg.sender] != 0) revert AA_AlreadyClaimed(); + if (claimed[msg.sender] >= totalGrant) revert AA_AlreadyClaimed(); + grantedAmount = uint128(totalGrant - claimed[msg.sender]); claimed[msg.sender] = totalGrant; }
Other
#0 - c4-pre-sort
2023-07-30T05:43:57Z
141345 marked the issue as duplicate of #213
#1 - c4-judge
2023-08-11T16:34:14Z
0xean marked the issue as satisfactory