OnlyPwner - Diversion Challenge Writeup

OnlyPwner - Diversion Challenge Writeup-魔法少女雪殇
OnlyPwner - Diversion Challenge Writeup
此内容为付费阅读,请付费后查看
300
立即购买
您当前未登录!建议登陆后购买,可保存购买订单
付费阅读

挑战概述

目标

用户初始拥有 10 WETH,需要通过攻击使余额超过 20 WETH

解题条件 (IsSolved.sol)

if (WETH.balanceOf(user) > 20 ether) {
    console.log("is-solved:true");
}

初始状态

组件状态
VUL-WETH 流动池1000 VUL : 1000 WETH
Farming 合约whale 质押了 1000 WETH
Oracle 价格VUL:WETH = 0.98:1
用户10 WETH

合约分析

Farming.sol - 核心漏洞合约

contract Farming is ReentrancyGuard, IFarming {
    IWETH public WETH;
    IMintableERC20 public VUL;
    IOracle public ORACLE;
    IUniswapV2Router02 public UNISWAPV2_ROUTER02;

    mapping(address => uint256) public shares;
    uint256 public totalShares = 0;

    uint256 lastAccumulateTimestamp;
    uint256 yieldVulPerSecond;  // 每秒产生 0.1 VUL

关键函数 1: deposit()

function deposit(uint256 amount) external nonReentrant {
    require(amount > 0, "Farming: Amount must be greater than 0");
    
    // 先累积收益
    accumulateYield(getDefaultPath());

    uint currentBalance = WETH.balanceOf(address(this));
    uint currentShares = totalShares;

    // 计算新 shares
    uint newShares;
    if (currentShares == 0) {
        newShares = amount;
    } else {
        newShares = (amount * currentShares) / currentBalance;
    }

    shares[msg.sender] += newShares;
    totalShares += newShares;

    WETH.transferFrom(msg.sender, address(this), amount);
}

关键函数 2: accumulateYield() - 漏洞所在

// ⚠️ 漏洞:public 函数,任何人可调用,且可传入自定义 path
function accumulateYield(address[] memory path) public {
    uint256 secs = block.timestamp - lastAccumulateTimestamp;
    uint256 yield = secs * yieldVulPerSecond;

    if (yield == 0) {
        return;
    }

    lastAccumulateTimestamp = block.timestamp;

    VUL.mint(address(this), yield);  // mint VUL 作为收益
    swapYieldToWeth(path);           // 通过自定义路径 swap
}

关键函数 3: swapYieldToWeth()

function swapYieldToWeth(address[] memory path) private {
    // 仅检查路径起点和终点
    require(path.length > 1, "Farming: Path must have at least 2 elements");
    require(path[0] == address(VUL), "Farming: Path must start with VUL");
    require(path[path.length - 1] == address(WETH), "Farming: Path must end with WETH");

    uint256 amount = VUL.balanceOf(address(this));
    uint256 expectedWethAmount = (ORACLE.vulToWethPrice() * amount) / 1e18;

    VUL.approve(address(UNISWAPV2_ROUTER02), amount);
    
    // ⚠️ 使用用户提供的 path 进行 swap
    UNISWAPV2_ROUTER02.swapExactTokensForTokensSupportingFeeOnTransferTokens(
        amount,
        expectedWethAmount,
        path,           // 自定义路径!
        address(this),
        block.timestamp
    );
}

漏洞分析

漏洞 1: accumulateYield() 是 public 函数

任何人都可以调用此函数,触发收益累积和 swap。

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情

    暂无评论内容