Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: medium
Valid

Funds will never reach the curveVault

Summary

Problem is that we have sent all the funds upon deposit into the reserveRTokenAddress.

After it, the _rebalanceLiquidity is called, which takes the currentBalance of the reserveRTokenAddress , after it check it against the reserve.totalLiquidity and calc. the excess or shortage. Then it approve the funds and try to deposit the crvUSD into the vault. However, the problem is that this funds are not in the contract, they resides in the reserveRTokenAddress

Vulnerability Details

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Test, console} from "lib/forge-std/src/Test.sol";
//Import which is neccessery for the LendingPool.sol
import "contracts/core/pools/LendingPool/LendingPool.sol";
import "contracts/core/tokens/RToken.sol";
import "contracts/core/tokens/DebtToken.sol";
import "contracts/core/tokens/RAACNFT.sol";
import "contracts/core/tokens/RAACToken.sol";
import "contracts/core/minters/RAACMinter/RAACMinter.sol";
import "contracts/core/pools/StabilityPool/StabilityPool.sol";
import "contracts/core/pools/StabilityPool/StabilityPool.sol";
interface ITokenERC20{
function approve(address spender, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
}
contract ArsenTest is Test{
//Actual, non-modifier contracts
RToken public rToken;
DebtToken public dToken;
RAACNFT public raacNFT;
RAACToken public raacToken;
//deploy minters
RAACMinter public raacMinter;
//Mock contracts
HousePrices public housePrices;
PriceOracle public priceOracle;
//deploy the Lending Pool
LendingPool public lendingPool;
//deploy Stability Pool
StabilityPool public stabilityPool;
address public attacker = address(8888);
address public user_1 = address(1111);
address public user_2 = address(2222);
address CRV_USD = address(0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E);
string ETH_RPC_URL = "https://mainnet.infura.io/v3/2cef90f9f3f44a1fb5201d8547183d42";
function setUp() public{
uint256 ethFork = vm.createFork(ETH_RPC_URL);
vm.selectFork(ethFork);
housePrices = new HousePrices();
priceOracle = new PriceOracle();
rToken = new RToken(
"rToken",
"RTOKEN",
address(this), //init owner
CRV_USD //crvUsd addr
);
dToken = new DebtToken(
"Debt Token",
"DBTTOKEN",
address(this) //init owner
);
raacNFT = new RAACNFT(
CRV_USD, //token
address(housePrices), //house prices
address(this) //init owner
);
raacToken = new RAACToken(
address(this),
500, //initialSwapTaxRate
500 //initialBurnTaxRate
);
lendingPool = new LendingPool(
CRV_USD, //crvUsd addr
address(rToken), //rToken
address(dToken), //debtToken
address(raacNFT), //raacNFT
address(priceOracle),//priceOracle addr
100000000000000000000000000 //init prime rate
);
stabilityPool = new StabilityPool(address(this));
raacMinter = new RAACMinter(
address(raacToken),
address(stabilityPool),
address(lendingPool),
address(this)
);
stabilityPool.initialize(
address(rToken),
address(dToken),
address(raacToken),
address(raacMinter), //raacMinter
CRV_USD,
address(lendingPool)
);
//@audit TO DO - set the setParameter , like threshold, e.t.c for the Lending Pool
//set the reserve pool for RToken to be able to mint stuff
rToken.setReservePool(address(lendingPool));
//set the reserve pool for the DToken to be able to mint stuff
dToken.setReservePool(address(lendingPool));
}
//forge test --match-test test_deposit -vvvv
function test_deposit() public{
deal(CRV_USD, attacker, 1_000e18); //deal 200 crvUSD to the attacker
vm.startPrank(attacker);//start
ITokenERC20(CRV_USD).approve(address(lendingPool), 1_000e18);
lendingPool.deposit(1_000e18); //deposit 1_000_000e18 crvUSD into the pool
console.log("THe crvUSD balance of lending Pool after the deposit", ITokenERC20(CRV_USD).balanceOf(address(lendingPool)));
console.log("THe crvUSD balance of rToken after the deposit", ITokenERC20(CRV_USD).balanceOf(address(rToken)));
vm.stopPrank();
lendingPool.setCurveVault(address(0x0655977FEb2f289A4aB78af67BAB0d17aAb84367));
deal(CRV_USD, user_1, 1_000e18); //deal 200 crvUSD to the attacker
vm.startPrank(user_1);
ITokenERC20(CRV_USD).approve(address(lendingPool), 1_000e18);
vm.expectRevert(); //because the 0 value
lendingPool.deposit(1_000e18);
vm.stopPrank();
}
}
//@note MOCK CONTRACTS FOR THE POC PURPOSES ONLY
contract HousePrices{
function tokenToHousePrice(uint256 _tokenId) external view returns (uint256){
return 10_000e18;
}
}
contract PriceOracle{
function getLatestPrice(uint256 _tokenId) external view returns (uint256, uint256){
return(10_000e18, block.timestamp);
}
}

Impact

Logic broken

Tools Used

Recommendations

Ensure the funds can reach the Vault

Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool::_depositIntoVault and _withdrawFromVault don't transfer tokens between RToken and LendingPool, breaking Curve vault interactions

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool::_depositIntoVault and _withdrawFromVault don't transfer tokens between RToken and LendingPool, breaking Curve vault interactions

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.