Skip to content
Quantix Security Labs

Spot Price Oracle

Describe a single-transaction sequence that borrows more than the collateral is worth, estimate what it costs, and replace the price source.
AdvancedSolidity · ArbitrumOracle manipulation45–60 minutes

Briefing

A small lending market values collateral using the reserves of a constant-product pool. Flash loans of the borrowable asset are available from other protocols.

SpotLending.solsolidity
// Quantix Security Research Network — training challenge.// Intentionally vulnerable. Written for education; do not deploy.// SPDX-License-Identifier: MITpragma solidity 0.8.24; interface IPair {    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 ts);} interface IERC20 {    function transfer(address, uint256) external returns (bool);    function transferFrom(address, address, uint256) external returns (bool);} contract SpotLending {    IPair public immutable pair;          // token0 = COLL, token1 = USD    IERC20 public immutable coll;    IERC20 public immutable usd;    uint256 public constant LTV_BPS = 7_500;     mapping(address => uint256) public collateral;    mapping(address => uint256) public debt;     constructor(IPair _pair, IERC20 _coll, IERC20 _usd) {        pair = _pair;        coll = _coll;        usd = _usd;    }     /// USD per 1e18 COLL, from current pool reserves.    function price() public view returns (uint256) {        (uint112 r0, uint112 r1, ) = pair.getReserves();        return (uint256(r1) * 1e18) / r0;    }     function depositCollateral(uint256 amount) external {        require(coll.transferFrom(msg.sender, address(this), amount), "transfer failed");        collateral[msg.sender] += amount;    }     function borrow(uint256 amount) external {        uint256 value = (collateral[msg.sender] * price()) / 1e18;        require(debt[msg.sender] + amount <= (value * LTV_BPS) / 10_000, "undercollateralised");        debt[msg.sender] += amount;        require(usd.transfer(msg.sender, amount), "transfer failed");    }}

Hints

Reveal one at a time. Each moves a step closer to the answer.

  1. H1

    Hidden

  2. H2

    Hidden

  3. H3

    Hidden

Solution

Try writing your own explanation and fix before opening it.

References