AirDropper is a gas optimized protocol built to assist with token distribution on the zkSync Era chain.
High - 100xp
Medium - 20xp
Low - 2xp
Starts: April 25, 2024 Noon UTC
Ends: May 02, 2024 Noon UTC
This code was created for Codehawks as the first flight. It is made with bugs and flaws on purpose. Don't use any part of this code without reviewing it and audit it.
Our team is looking to airdrop 100 USDC tokens on the zkSync era chain to 4 lucky addresses based on their activity on the Ethereum L1. The Ethereum addresses are:
0x20F41376c713072937eb02Be70ee1eD0D639966C
0x277D26a45Add5775F21256159F089769892CEa5B
0x0c8Ca207e27a1a8224D1b602bf856479b03319e7
0xf6dBa02C01AF48Cf926579F77C9f874Ca640D91D
Each address will recieve 25 USDC.
The codebase was designed to be deployed to the zkSync era chain and therefore uses the zksync-foundry fork of foundry.
We have a single smart contract MerkleAirdrop.sol
that we think looks very good. We based it off the Uniswap Merkle-Distributor. It uses a merkle proof to verify that the user is eligible for the airdrop.
The way users claim
their airdrop is by calling the claim
function, and passing:
The claim
function requires a 1e9
ETH fee to be paid, and the owner of the contract is the only one who should be allowed to withdraw it with claimFees
.
Let's imagine you're doing an airdrop, what's the first solution that comes to mind? Probably just creating a list of addresses that are elligible to recieve the drop, and just checking users against that list. The smart contract might look like this:
mapping(address => bool) public isEligible;
function addEligible(address _address) external {
isEligible[_address] = true;
}
function claim() external {
if(isEligible[msg.sender]) {
// send the airdrop
}
}
The claim
function looks easy enough, but we have to populate the list by calling addEligible
for every address. If we have a lot of addresses, this is going to end up costing SO MUCH GAS!
Ok, so clearly we need a better solution, this is where merkle trees come in. It's recommended you read up on Merkle trees to understand this. But you can audit this codebase without really understanding it. You can get by in doing this audit if you just think "so long as the inputs
in makeMerkle.js
are correct, the process
will work correctly".
But, this is a great time to learn something new :)
This file is not in scope for the audit, but it's good to know how it works because it's how we are generating the s_merkleRoot
in our Deploy.s.sol
. The output of this file is:
s_merkleRoot
If you have node
and yarn
installed, you can run the file by:
yarn
yarn run makeMerkle
Assume that so long as the inputs are correct, the proofs and merkle root are correct.
The Cyfrin/CodeHawks team has convinced us that we need to add our Deploy script to being in scope for this competitive audit. All this does is deploy and set up our smart contract. Once this codebase passes audit, we plan on running the script in the makefile to deploy this.
We use the script found in makeMerkle.js
to create the s_merkleRoot
.
git --version
and you see a response like git version x.x.x
forge --version
and you see a response like forge 0.2.0 (816e00b 2023-03-16T00:05:26.396218Z)
cargo --version
and you see a response like cargo 1.57.0 (f1edd0429 2022-01-05)
Optional:
node --version
and you see a response like v16.13.0
yarn --version
and you see a response like 1.22.17
foundry-zksync
There are a few prerequiste steps to installing this tool. Please see the official documentation before installing this.Once you have the prerequisites, you can follow their quickstart
This will override your existing foundry
installation. You can know it's been done properly if you can run the following:
forge build --help | grep zksync
and see an output like:
--zksync
git clone https://github.com/cyfrin/2024-04-airdropper
cd 2024-04-airdropper
make
This will build the smart contracts with forge build --zksync
.
forge test --zksync
./src/
└── MerkleAirdrop.sol
./script/
└── Deploy.s.sol
0.8.24
Onwer - The one who can withdraw the fees earned by the claim
function.
Rank | Username | ||||
1 | B | 880 | 4 (0) | 0 (0) | 0 |
2 | N NightHawK | 800 | 4 (0) | 0 (0) | 0 |
3 | V Vesper | 800 | 4 (0) | 0 (0) | 0 |
4 | f f3d0ss | 680 | 3 (0) | 0 (0) | 0 |
5 | m mgnfyview | 680 | 3 (0) | 0 (0) | 0 |
6 | f farismaulana | 680 | 3 (0) | 0 (0) | 0 |
7 | v vile | 606 | 3 (0) | 0 (0) | 1 |
8 | n | 604 | 3 (0) | 0 (0) | 1 |
9 | T Thaddeus19 | 600 | 3 (0) | 0 (0) | 0 |
10 | 0 0xanmol | 600 | 3 (0) | 0 (0) | 0 |
11 | s shivam21 | 600 | 3 (0) | 0 (0) | 0 |
12 | J Josh4324 | 600 | 3 (0) | 0 (0) | 0 |
13 | s | 600 | 3 (0) | 0 (0) | 0 |
14 | 0 0xb0k0 | 600 | 3 (0) | 0 (0) | 0 |
15 | n | 600 | 3 (0) | 0 (0) | 0 |
16 | L | 600 | 3 (0) | 0 (0) | 0 |
17 | B BornTBH | 600 | 3 (0) | 0 (0) | 0 |
18 | p | 600 | 3 (0) | 0 (0) | 0 |
19 | m mirkopezo | 600 | 3 (0) | 0 (0) | 0 |
20 | F FalseGenius | 600 | 3 (0) | 0 (0) | 0 |
21 | 4 | 600 | 3 (0) | 0 (0) | 0 |
22 | C CarlosAlbaWork | 600 | 3 (0) | 0 (0) | 0 |
23 | 0 0xAee | 400 | 2 (0) | 0 (0) | 0 |
24 | u unnamed | 400 | 0 (0) | 0 (0) | 0 |
25 | Y Yasmine | 400 | 0 (0) | 0 (0) | 0 |
26 | a abhishekthakur | 400 | 2 (0) | 0 (0) | 0 |
27 | a aymericrt | 400 | 2 (0) | 0 (0) | 0 |
28 | h | 400 | 2 (0) | 0 (0) | 0 |
29 | C CryptoKook | 400 | 2 (0) | 0 (0) | 0 |
30 | k kostov | 400 | 2 (0) | 0 (0) | 0 |
31 | l lefg | 400 | 2 (0) | 0 (0) | 0 |
32 | 0 0xDimo | 400 | 2 (0) | 0 (0) | 0 |
33 | s seeu | 400 | 2 (0) | 0 (0) | 0 |
34 | k k3ySk1lls | 400 | 2 (0) | 0 (0) | 0 |
35 | C Coffee | 400 | 2 (0) | 0 (0) | 0 |
36 | i imth3AK | 204 | 1 (0) | 0 (0) | 1 |
37 | b blackSquirrel | 204 | 1 (0) | 0 (0) | 1 |
38 | t takeshikovacs | 200 | 1 (0) | 0 (0) | 0 |
39 | l lilizhu | 200 | 1 (0) | 0 (0) | 0 |
40 | p papalardo | 200 | 1 (0) | 0 (0) | 0 |
41 | 0 0x8840 | 200 | 1 (0) | 0 (0) | 0 |
42 | S Sajjad | 200 | 1 (0) | 0 (0) | 0 |
43 | s shishir | 200 | 1 (0) | 0 (0) | 0 |
44 | s sakar | 200 | 1 (0) | 0 (0) | 0 |
45 | A Audix | 200 | 1 (0) | 0 (0) | 0 |
46 | j jo13 | 200 | 1 (0) | 0 (0) | 0 |
47 | A Awacs | 200 | 1 (0) | 0 (0) | 0 |
48 | 0 0xsalami | 200 | 1 (0) | 0 (0) | 0 |
49 | S Sungyuk1 | 200 | 1 (0) | 0 (0) | 0 |
50 | m mangocola | 200 | 1 (0) | 0 (0) | 0 |
51 | g good0000vegetable | 200 | 1 (0) | 0 (0) | 0 |
52 | s simon0417 | 200 | 1 (0) | 0 (0) | 0 |
53 | p peterTheAuditor | 200 | 1 (0) | 0 (0) | 0 |
54 | u uba7 | 200 | 1 (0) | 0 (0) | 0 |