Reliq Finance Disclosed Report

Users lose funds to MEV sandwich attacks due to missing slippage protection

Created date
Dec 20 2025

Target

https://github.com/hackenproof-public/reliq-protocol

Vulnerability Details

When enterTheTemple() is called, external attackers can sandwich the transaction, causing users to receive significantly less relHYPE than expected. This results in direct theft of user funds by MEV bots.

The vulnerability is in the missing slippage parameter not in who can call the function. Even admin functions should protect users from external attacks.

function enterTheTemple() external onlyOwner nonReentrant {
    // ...
    uint256 totalBacking = backingToken.balanceOf(address(this));
    backingToken.approve(address(reliq), totalBacking);
    reliq.buy(address(this), totalBacking);  // No minimum output specified!
    totalReliqHYPEAcquired = reliq.balanceOf(address(this));
    // No check: require(totalReliqHYPEAcquired >= minExpected, "Too much slippage");
}

Why this matters: An attacker watching the mempool can sandwich this transaction:

  1. Front-run: Attacker buys a huge amount of relHYPE right before the owner's transaction, pumping up the price
  2. Victim's tx: Altar buys at the inflated price, receiving way less relHYPE per token
  3. Back-run: Attacker immediately sells, profiting from the price difference

The users are the ones who lose out they deposited 100 ETH worth of tokens but only get claims on maybe 70 ETH worth of relHYPE. The attacker stole 30 ETH of value.

Example: Let's say users deposited 1000 tokens total:

  • Normal case: Should receive ~1000 relHYPE (1:1 ratio)
  • Sandwich attack: Attacker inflates price by 30%
  • Altar receives: ~770 relHYPE instead
  • Users collectively lose 230 relHYPE worth of value
  • Attacker profits the 30% difference

Recommendation Fix

Add a minimum output parameter:

function enterTheTemple(uint256 minReliqHYPE) external onlyOwner nonReentrant {
    require(block.timestamp >= deadline, "Altar: deadline not passed");
    require(!isReliqHYPEClaim, "Altar: ReliqHYPE claim already done");

    uint256 totalBacking = backingToken.balanceOf(address(this));
    backingToken.approve(address(reliq), totalBacking);
    reliq.buy(address(this), totalBacking);
    totalReliqHYPEAcquired = reliq.balanceOf(address(this));
    
    require(totalReliqHYPEAcquired >= minReliqHYPE, "Altar: slippage too high");  // ADD THIS
    
    isReliqHYPEClaim = true;
    emit TempleEntered(totalBacking, totalReliqHYPEAcquired);
}

This is a real attack vector that's been exploited in DeFi before. Without slippage protection, users are sitting ducks for MEV bots.

Validation steps

How to reproduce:

  1. Users sacrifice 100 tokens
  2. Deadline passes
  3. Attacker sees enterTheTemple() in mempool
  4. Attacker front-runs with large buy (inflates relHYPE price)
  5. enterTheTemple() executes at bad price
  6. Attacker back-runs with sell (extracts profit)
  7. Users get way less relHYPE than they should have

Paste this test code in test\PreDeposit\Altar.t.sol

function test_NoSlippageProtection() public {
    console.log("=== No Slippage Protection ===");
    
    // Alice sacrifices
    vm.startPrank(alice);
    backing.approve(address(altar), 100 ether);
    altar.sacrifice(100 ether, alice);
    vm.stopPrank();
    
    vm.warp(altar.deadline() + 1);
    
    uint256 backingAmount = backing.balanceOf(address(altar));
    console.log("Backing to spend:", backingAmount);
    
    // Owner enters temple (no min output specified)
    altar.enterTheTemple();
    
    uint256 reliqReceived = altar.totalReliqHYPEAcquired();
    console.log("ReliqHYPE received:", reliqReceived);
    
    // In our mock, we get 2x
    // But in reality, could get much less due to:
    // - Price manipulation
    // - Sandwich attacks
    // - Fees
    
    console.log("MEDIUM: No minimum relHYPE check - vulnerable to sandwich attacks");
    
    // If reliq.buy() returned 0, it would still succeed!
    assertTrue(reliqReceived > 0, "In this mock, received tokens");
}

Run the test code:

forge test --match-test test_NoSlippageProtection -vv

Result Output

Ran 1 test for test/PreDeposit/Altar.t.sol:AltarTest
[PASS] test_NoSlippageProtection() (gas: 298301)
Logs:
  === No Slippage Protection ===
  Backing to spend: 100000000000000000000
  ReliqHYPE received: 200000000000000000000
  MEDIUM: No minimum relHYPE check - vulnerable to sandwich attacks

Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 10.36ms (3.83ms CPU time)

Ran 1 test suite in 61.90ms (10.36ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)

Attachments

hidden
CommentsReport History
Comments on this report are hidden
Details
Statedisclosed
Severity
Medium
Bounty$91
Visibilitypartially
VulnerabilityBlockchain
Participants (4)
company admin
author