Files
smom-dbis-138/test/flash/DBISEngineXXautUsdcBorrowVault.t.sol
defiQUG 76143a8fe3 feat(token-aggregation): reports, PMM quotes, config; Engine X flash vaults
- Expand token-aggregation API (report routes), canonical tokens, pools
- Add flash vault contracts + tests (indexed, DODO cwUSDC, XAUT borrow)
- PMM pools JSON, deploy/export scripts, metamask verified list

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 12:56:30 -07:00

176 lines
6.6 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Test} from "forge-std/Test.sol";
import {DBISEngineXXautUsdcBorrowVault} from "../../contracts/flash/DBISEngineXXautUsdcBorrowVault.sol";
import {MockMintableToken} from "../dbis/MockMintableToken.sol";
contract DBISEngineXXautUsdcBorrowVaultTest is Test {
MockMintableToken internal xaut;
MockMintableToken internal usdc;
MockMintableToken internal cwusdc;
DBISEngineXXautUsdcBorrowVault internal vault;
address internal constant BORROWER = address(0xB0B);
address internal constant LENDER = address(0x1EAD);
address internal constant LIQUIDATOR = address(0xA11CE);
bytes32 internal constant PRICE_SOURCE_HASH = bytes32(uint256(0x5052494345));
bytes32 internal constant SWAP_TX = bytes32(uint256(0x51574150));
bytes32 internal constant ISO_HASH = bytes32(uint256(0x150));
bytes32 internal constant AUDIT_HASH = bytes32(uint256(0xA0017));
bytes32 internal constant PEG_HASH = bytes32(uint256(0x9E6));
uint256 internal constant XAUT_PRICE6 = 3_226_640_000;
uint256 internal constant LTV_BPS = 7_500;
uint256 internal constant LIQUIDATION_THRESHOLD_BPS = 8_000;
uint256 internal constant MIN_HEALTH_FACTOR_BPS = 11_000;
uint256 internal constant LIQUIDATION_BONUS_BPS = 500;
uint256 internal constant LENDER_USDC = 5_000_000_000;
event CwusdcSourcedRepay(
address indexed account,
address indexed payer,
uint256 amount,
bytes32 indexed publicSwapTxHash,
bytes32 iso20022DocumentHash,
bytes32 auditEnvelopeHash,
bytes32 pegProofHash
);
function setUp() public {
xaut = new MockMintableToken("Tether Gold", "XAUt", 6, address(this));
usdc = new MockMintableToken("USD Coin", "USDC", 6, address(this));
cwusdc = new MockMintableToken("Wrapped cWUSDC", "cWUSDC", 6, address(this));
vault = new DBISEngineXXautUsdcBorrowVault(
address(xaut),
address(usdc),
address(cwusdc),
address(this),
XAUT_PRICE6,
LTV_BPS,
LIQUIDATION_THRESHOLD_BPS,
MIN_HEALTH_FACTOR_BPS,
LIQUIDATION_BONUS_BPS,
0,
PRICE_SOURCE_HASH
);
usdc.mint(LENDER, LENDER_USDC);
vm.startPrank(LENDER);
usdc.approve(address(vault), type(uint256).max);
vault.fundLender(LENDER_USDC);
vm.stopPrank();
xaut.mint(BORROWER, 1_000_000);
usdc.mint(BORROWER, 1_000_000_000);
vm.startPrank(BORROWER);
xaut.approve(address(vault), type(uint256).max);
usdc.approve(address(vault), type(uint256).max);
vm.stopPrank();
usdc.mint(LIQUIDATOR, 1_000_000_000);
vm.prank(LIQUIDATOR);
usdc.approve(address(vault), type(uint256).max);
}
function testBorrowRepayAndWithdrawCollateral() public {
vm.startPrank(BORROWER);
vault.supplyCollateral(1_000_000);
assertEq(vault.collateralValueUsd6(BORROWER), XAUT_PRICE6, "1 XAUt value");
vault.borrowUsdc(2_000_000_000, BORROWER);
assertEq(usdc.balanceOf(BORROWER), 3_000_000_000, "borrowed USDC");
assertEq(vault.lenderUsdcAvailable(), 3_000_000_000, "lender bucket lent out");
assertEq(vault.healthFactorBps(BORROWER), 12_906, "health factor");
vault.repayUsdc(2_000_000_000);
vault.withdrawCollateral(1_000_000, BORROWER);
vm.stopPrank();
(uint256 collateral, uint256 debt) = vault.positions(BORROWER);
assertEq(collateral, 0, "collateral closed");
assertEq(debt, 0, "debt closed");
assertEq(xaut.balanceOf(BORROWER), 1_000_000, "xaut returned");
assertEq(vault.lenderUsdcAvailable(), LENDER_USDC, "lender restored");
}
function testBorrowRejectsDebtAboveEffectiveCollateralLimit() public {
vm.startPrank(BORROWER);
vault.supplyCollateral(1_000_000);
vm.expectRevert(bytes("exceeds collateral"));
vault.borrowUsdc(2_400_000_000, BORROWER);
vm.stopPrank();
}
function testBorrowRejectsGlobalBorrowCap() public {
vault.setRiskParams(LTV_BPS, LIQUIDATION_THRESHOLD_BPS, MIN_HEALTH_FACTOR_BPS, LIQUIDATION_BONUS_BPS, 1_000_000_000);
vm.startPrank(BORROWER);
vault.supplyCollateral(1_000_000);
vm.expectRevert(bytes("max borrow exceeded"));
vault.borrowUsdc(1_000_000_001, BORROWER);
vm.stopPrank();
}
function testRepayFromCwusdcProofStillSettlesInUsdcAndAnchorsHashes() public {
vm.startPrank(BORROWER);
vault.supplyCollateral(1_000_000);
vault.borrowUsdc(1_000_000_000, BORROWER);
vm.expectEmit(true, true, true, true, address(vault));
emit CwusdcSourcedRepay(BORROWER, BORROWER, 250_000_000, SWAP_TX, ISO_HASH, AUDIT_HASH, PEG_HASH);
vault.repayUsdcFromCwusdcProof(250_000_000, SWAP_TX, ISO_HASH, AUDIT_HASH, PEG_HASH);
vm.stopPrank();
(, uint256 debt) = vault.positions(BORROWER);
assertEq(debt, 750_000_000, "debt reduced");
assertEq(vault.totalCwusdcProofRepayUsdc(), 250_000_000, "proof-sourced repay counter");
}
function testLiquidationAfterPriceDrop() public {
vm.startPrank(BORROWER);
vault.supplyCollateral(1_000_000);
vault.borrowUsdc(2_000_000_000, BORROWER);
vm.stopPrank();
vault.setXautUsdPrice6(2_000_000_000, bytes32(uint256(0x44524f50)));
assertEq(vault.healthFactorBps(BORROWER), 8_000, "unhealthy after price drop");
vm.prank(LIQUIDATOR);
uint256 seized = vault.liquidate(BORROWER, 100_000_000);
assertEq(seized, 52_500, "5 percent bonus on 0.05 XAUt");
assertEq(xaut.balanceOf(LIQUIDATOR), 52_500, "liquidator receives XAUt");
(, uint256 debt) = vault.positions(BORROWER);
assertEq(debt, 1_900_000_000, "debt after partial liquidation");
}
function testOwnerCanWithdrawOnlyUnborrowedLenderUsdc() public {
vm.prank(BORROWER);
vault.supplyCollateral(1_000_000);
vm.prank(BORROWER);
vault.borrowUsdc(500_000_000, BORROWER);
vault.withdrawLenderUsdc(address(this), 4_500_000_000);
assertEq(vault.lenderUsdcAvailable(), 0, "available bucket withdrawn");
vm.expectRevert(bytes("insufficient lender usdc"));
vault.withdrawLenderUsdc(address(this), 1);
}
function testPauseBlocksMutableUserFlows() public {
vault.pause();
vm.expectRevert(bytes("paused"));
vm.prank(BORROWER);
vault.supplyCollateral(1);
vault.unpause();
vm.prank(BORROWER);
vault.supplyCollateral(1);
}
}