AirDropper

AI First Flight #5
Beginner FriendlyDeFiFoundry
EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

The Foundry EVM cheatcodes used in deploy script prevent the `Deploy.s.sol` from being tested

Impact: L
Likelihood: L

Root + Impact

Description

  • The following Foundry EVM cheatcodes are used in Deploy.s.sol::run() function:

    • vm.startBroadcast();

    • vm.stopBroadcast();

  • These cheatcodes do not work properly when used in a function that is called on ZkSync.

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();
}

Risk

Likelihood:

  • The issue occurs when the Deploy.s.sol::run() is used in tests.

Impact:

  • The deploy script cannot be thoroughly tested in a fork test because when cheatcodes are used in a called function on ZkSync Era Mainnet, they do not work properly.

Proof of Concept

Please, add DeployTest.t.sol contract and run the fork test test_cheatcodesDoNotWorkProperly_onZkSync on ZkSync Era Mainnet using the command forge test --mt test_cheatcodesDoNotWorkProperly_onZkSync --fork-url $ZK_SYNC_MAINNET_URL --zksync -vvvvv

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import { Test, console2 } from "forge-std/Test.sol";
import {TestExt} from "forge-zksync-std/TestExt.sol";
import { Deploy } from "script/Deploy.s.sol";
import { MerkleAirdrop } from "src/MerkleAirdrop.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract DeployTest is Test, TestExt{
Deploy deployer;
MerkleAirdrop airdrop;
function test_cheatcodesDoNotWorkProperly_onZkSync() public {
deployer = new Deploy();
deployer.run();
}
}

The test above will give an error: ERROR foundry_zksync_core::vm::tracers::cheatcode: call may fail or behave unexpectedly due to empty code target=0x7109709ecfa91a80626ff3989d68f67f5b1dd12d calldata="7fb5297f" and the test will revert.

The analisys of the error above leads to these conclusions:

  1. The code target=0x7109709ecfa91a80626ff3989d68f67f5b1dd12d is the address of Vm as proved in the test test_checkTheVmAddress below:

function test_checkTheVmAddress() public pure {
address addressFromError = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D;
assertEq(VM_ADDRESS, addressFromError);
}
  1. The calldata="7fb5297f" is the startBroadcast() as proved by the command forge inspect Vm methods:
    |------------------------------------------------------------------+------------|
    | startBroadcast() | 7fb5297f |
    |------------------------------------------------------------------+------------|

Recommended Mitigation

Redesign the deploy script to make it possible for testing:

  • add a separate function for MerkleAirdrop.sol funding;

  • call it from Deploy.s.sol::run() function.

Now, both functions Deploy.s.sol::deployMerkleDropper() and Deploy.s.sol::fundMerkleDropper() can be called from tests without issues instead of calling Deploy.s.sol::run().

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);
+ fundMerkleDropper(IERC20(0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4), address(airdrop));
vm.stopBroadcast();
}
function deployMerkleDropper(bytes32 merkleRoot, IERC20 zkSyncUSDC) public returns (MerkleAirdrop) {
return (new MerkleAirdrop(merkleRoot, zkSyncUSDC));
}
+ function fundMerkleDropper(IERC20 token, address to) public {
+ token.transfer(to, s_amountToAirdrop);
+ }
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 1 day ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!