Summary
Wrong value of merkleroot is used in deploy.s.sol
which will make contract unusable
Vulnerability Details
In Deploy.s.sol
file following merkleroot is being used 0xf69aaa25bd4dd10deb2ccd8235266f7cc815f6e9d539e9f4d47cae16e0c36a05
Which is incorrect. This flaw is due to current makeMerkle.js
file where amount param is wrong. Instead of using 1e6 for decimals, 1e18 being used which generate the above merkleroot.
Using this merkleroot, nobody will be able to claim the funds and funds will be lost.
Impact
Funds for airdrop will be lost and contract will be unustable.
Tools Used
Foundry, Manual Review
Recommendations
Correct the script makeMerkle.js
to get correct merkleroot and use that value in the main script.
replace const amount = (25 * 1e18).toString()
in makeMerkle.js
with const amount = (25 * 1e6).toString()
then run yarn run makeMerkle
or node makeMerkle
and it will print following result
Merkle Root: 0x3b2e22da63ae414086bec9c9da6b685f790c6fab200c7918f2879f08793d77bd
Proof for address: 0x20F41376c713072937eb02Be70ee1eD0D639966C with amount: 25000000:
[
'0x32cee63464b09930b5c3f59f955c86694a4c640a03aa57e6f743d8a3ca5c8838',
'0x8ff683185668cbe035a18fccec4080d7a0331bb1bbc532324f40501de5e8ea5c'
]
then update the merkleRoot value in Deploy.s.sol
as follows
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import { MerkleAirdrop, IERC20 } from "../src/MerkleAirdrop.sol";
import { Script } from "forge-std/Script.sol";
contract Deploy is Script {
address public s_zkSyncUSDC = 0x1D17CbCf0D6d143135be902365d2e5E2a16538d4;
- bytes32 public s_merkleRoot = 0xf69aaa25bd4dd10deb2ccd8235266f7cc815f6e9d539e9f4d47cae16e0c36a05;
+ bytes32 public s_merkleRoot = 0x3b2e22da63ae414086bec9c9da6b685f790c6fab200c7918f2879f08793d77bd;
// 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();
}
function deployMerkleDropper(bytes32 merkleRoot, IERC20 zkSyncUSDC) public returns (MerkleAirdrop) {
return (new MerkleAirdrop(merkleRoot, zkSyncUSDC));
}
}