🧠Exercise

Imagine you're reviewing a smart contract code snippet, and your task is to find the vulnerabilities. Below is a simplified contract named InsecureMerkleRoot.

contract InsecureMerkleRoot {
    bytes32 merkleRoot;
    mapping (bytes32 => bool) public alreadyClaimed;
    uint constant AIRDROP_AMOUNT = 10;
    
    function airdrop(bytes[] calldata proof, bytes32 leaf) external {

        require(MerkleProof.verifyCalldata(proof, merkleRoot, leaf), "not verified");
        require(!alreadyClaimed[leaf], "already claimed airdrop");
        alreadyClaimed[leaf] = true;

        mint(msg.sender, AIRDROP_AMOUNT);
    }
    
    function mint(address to, uint amount) private {
        /* Minting tokens logic */
    }
}

Please provide a brief explanation for the following:

  1. How can an attacker exploit this contract using the public knowledge of the addresses selected for the airdrop?

  2. What potential issue can arise due to the fact that the leaf isn't hashed?

  3. What does the term 'frontrun' mean in the context of this contract? And why is it problematic?

Answers:

  1. Knowing the addresses selected for the airdrop, an attacker can recreate the merkle tree and generate a valid proof. This allows them to claim the airdrop tokens falsely.

  2. Without hashing the leaf, the contract exposes itself to a potential attack where the attacker could submit a leaf equal to the merkle root. Since the MerkleProof.verifyCalldata method will evaluate to true in this case, the attacker can bypass the verification process.

  3. 'Frontrun' in this context means that once a valid proof is submitted to the network, an attacker can create a transaction with a higher gas price to get it included in the blockchain before the original transaction. This is problematic as an attacker could claim the airdrop using the same proof before the legitimate user, potentially emptying the airdrop before the legitimate claims are processed.

Last updated