Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

The winners are unable to claim due to mistake in `makeMerkle` and incorrect merkle root

Summary

The protocol uses makeMerkle.js file to generate the merkle root. The merkle root checks if a given address is eligible to receive airdrop. But there is an issue in makeMerkle and the generated merkle root will be invalid. That leads to incorrect functionality of the protocol.

Vulnerability Details

The protocol uses merkle proof to ensure that a given address is eligible to receive an airdrop. To generate the merkle root the protocol uses the makeMerkle.js file, then the generated merkle root is used in the deploy script:

address public s_zkSyncUSDC = 0x1D17CbCf0D6d143135be902365d2e5E2a16538d4;
@> bytes32 public s_merkleRoot = 0xf69aaa25bd4dd10deb2ccd8235266f7cc815f6e9d539e9f4d47cae16e0c36a05;
// 4 users, 25 USDC each
uint256 public s_amountToAirdrop = 4 * (25 * 1e6);
// Deploy the airdropper
function run() public {
vm.startBroadcast();
@> MerkleAirdrop airdrop = deployMerkleDropper(s_merkleRoot, IERC20(s_zkSyncUSDC));
// Send USDC -> Merkle Air Dropper
IERC20(0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4).transfer(address(airdrop), s_amountToAirdrop);
vm.stopBroadcast();
}

The protocol wants to give to 4 lucky addresses per 25 USDC tokens. The USDC tokens has 6 decimals. The problem is that in the makeMerkle.js file the amount that each address should receive is written as: const amount = (25 * 1e18).toString(). That means the merkle proof will require the amount passed in the MerkleAirdrop::claim function to be 25 * 1e18. But the USDC tokens have 6 decimals and the user will pass the amount as 25 * 1e6. Therefore, the selected winners will not be able to claim their USDC tokens due to the wrong amount in makeMerkle.js file and the wrong generated and used merkle root in Deploy script.

Impact

The makeMerkle.js file is out of scope, but in the docs is said that this file will be used to generate the merkle root that will be used in the Deploy script. That means the mistake in the amount in the makeMerkle file will have a high imapct into the protocol, if the protocol will be deployed with the wrong merkle root. The Deploy script is in the scope and we can see that the used merkle root is the merkle root generated for the const amount = (25 * 1e18).toString().
We can change the amount with the correct value: const amount = (25 * 1e18).toString() and generate the right merkle root through command: yarn run makeMerkle. The correct merkle root is: 0x3b2e22da63ae414086bec9c9da6b685f790c6fab200c7918f2879f08793d77bd. It is worth noting that in the test file MerkleAirdropTest.t.sol is used the correct merkle root, therefore the test testUsersCanClaim works correctly. But if you change the merkle root in the test file with this from the Deploy script (and the proof array), you will see that the test fails due to [FAIL. Reason: MerkleAirdrop__InvalidProof()]. This is because the merkle proof requires the amount to be 25 * 1e18, not 25 * 1e6.

Tools Used

Manual Review

Recommendations

Change the amount variable in the makeMerkle to: const amount = (25 * 1e6).toString(), generate new merkle root and change the merkle root in the Deploy script with the correct merkle root: 0x3b2e22da63ae414086bec9c9da6b685f790c6fab200c7918f2879f08793d77bd.

+ bytes32 public s_merkleRoot = 0x3b2e22da63ae414086bec9c9da6b685f790c6fab200c7918f2879f08793d77bd`;
- bytes32 public s_merkleRoot = 0xf69aaa25bd4dd10deb2ccd8235266f7cc815f6e9d539e9f4d47cae16e0c36a05;
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

wrong-usdc-decimals-in-merkle

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.