Add Engine X virtual batch canary vault
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m8s
CI/CD Pipeline / Security Scanning (push) Successful in 2m27s
CI/CD Pipeline / Lint and Format (push) Failing after 40s
CI/CD Pipeline / Terraform Validation (push) Failing after 21s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 23s
Validation / validate-genesis (push) Successful in 25s
Validation / validate-terraform (push) Failing after 22s
Validation / validate-kubernetes (push) Failing after 7s
Validation / validate-smart-contracts (push) Failing after 7s
Validation / validate-security (push) Failing after 1m19s
Validation / validate-documentation (push) Failing after 13s
OMNL reconcile anchor / Run omnl:reconcile and upload artifacts (push) Failing after 25s
Verify Deployment / Verify Deployment (push) Failing after 45s

This commit is contained in:
defiQUG
2026-05-07 07:09:17 -07:00
parent bb64836886
commit 27f8e3a500
2 changed files with 543 additions and 0 deletions

View File

@@ -0,0 +1,246 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Test} from "forge-std/Test.sol";
import {DBISEngineXVirtualBatchVault} from "../../contracts/flash/DBISEngineXVirtualBatchVault.sol";
import {MockMintableToken} from "../dbis/MockMintableToken.sol";
contract DBISEngineXVirtualBatchVaultTest is Test {
MockMintableToken internal cwusdc;
MockMintableToken internal usdc;
MockMintableToken internal xaut;
DBISEngineXVirtualBatchVault internal vault;
address internal constant USER = address(0xBEEF);
address internal constant SURPLUS_RECEIVER = address(0xCAFE);
address internal constant OUTPUT_RECIPIENT = address(0xD00D);
address internal constant ROUNDING_RECEIVER = address(0xA11CE);
uint256 internal constant LIVE_POOL_RESERVE = 85_763_529;
uint256 internal constant LENDER_USDC = 5_000_000;
uint256 internal constant XAUT_USD_PRICE6 = 3_226_640_000;
uint256 internal constant LTV_BPS = 8_000;
uint256 internal constant MAX_ROUND_TRIP_LOSS_BPS = 100;
bytes32 internal constant ISO_HASH = bytes32(uint256(0x1001));
bytes32 internal constant AUDIT_HASH = bytes32(uint256(0x1002));
bytes32 internal constant PEG_HASH = bytes32(uint256(0x1003));
event VirtualProofAuditEvidence(
bytes32 indexed proofId,
address indexed operator,
address indexed outputRecipient,
uint256 exactOutputAmount,
uint256 outputRoundingAmount,
address roundingReceiver,
bytes32 iso20022DocumentHash,
bytes32 auditEnvelopeHash,
bytes32 pegProofHash
);
function setUp() public {
cwusdc = new MockMintableToken("Wrapped cWUSDC", "cWUSDC", 6, address(this));
usdc = new MockMintableToken("USD Coin", "USDC", 6, address(this));
xaut = new MockMintableToken("Tether Gold", "XAUt", 6, address(this));
vault = new DBISEngineXVirtualBatchVault(
address(cwusdc),
address(usdc),
address(xaut),
address(this),
SURPLUS_RECEIVER,
XAUT_USD_PRICE6,
LTV_BPS,
MAX_ROUND_TRIP_LOSS_BPS
);
cwusdc.mint(address(this), LIVE_POOL_RESERVE);
usdc.mint(address(this), LIVE_POOL_RESERVE + LENDER_USDC);
cwusdc.approve(address(vault), type(uint256).max);
usdc.approve(address(vault), type(uint256).max);
vault.seedPool(LIVE_POOL_RESERVE, LIVE_POOL_RESERVE);
vault.fundLender(LENDER_USDC);
cwusdc.mint(USER, 10_000_000_000_000_000);
xaut.mint(USER, 10_000_000);
vm.startPrank(USER);
cwusdc.approve(address(vault), type(uint256).max);
xaut.approve(address(vault), type(uint256).max);
vm.stopPrank();
}
function testPreviewMatchesLiveMaintainedLoopMath() public view {
(
uint256 collateralXaut,
uint256 cwusdcInPerLoop,
uint256 cwusdcOutPerLoop,
uint256 cwusdcLossPerLoop,
uint256 totalCwusdcInAmount,
uint256 totalCwusdcOutAmount,
uint256 totalNeutralizedCwusdcAmount
) = vault.previewVirtualProof(LENDER_USDC, 3);
assertEq(collateralXaut, 1_937, "collateral should match live 5 USDC floor");
assertEq(cwusdcInPerLoop, 5_325_523, "cwusdc in should match live proof");
assertEq(cwusdcOutPerLoop, 5_295_471, "cwusdc out should match live proof");
assertEq(cwusdcLossPerLoop, 30_052, "neutralized loss should match live proof");
assertEq(totalCwusdcInAmount, 15_976_569, "three-loop cWUSDC in should match live proof");
assertEq(totalCwusdcOutAmount, 15_886_413, "three-loop cWUSDC out should match live proof");
assertEq(totalNeutralizedCwusdcAmount, 90_156, "three-loop neutralization should match live proof");
}
function testVirtualProofNetSettlesAndKeepsPoolMaintained() public {
uint256 userCwusdcBefore = cwusdc.balanceOf(USER);
uint256 userXautBefore = xaut.balanceOf(USER);
vm.prank(USER);
vault.runVirtualProof(bytes32("proof-1"), LENDER_USDC, 3);
assertEq(vault.poolCwusdcReserve(), LIVE_POOL_RESERVE, "pool cWUSDC reserve should not drift");
assertEq(vault.poolUsdcReserve(), LIVE_POOL_RESERVE, "pool USDC reserve should not drift");
assertEq(vault.currentSurplusCwusdc(), 0, "pool surplus should stay neutralized");
assertEq(vault.lenderUsdcAvailable(), LENDER_USDC, "lender bucket should be reusable");
assertEq(cwusdc.balanceOf(USER), userCwusdcBefore - 90_156, "user only loses neutralized amount");
assertEq(cwusdc.balanceOf(SURPLUS_RECEIVER), 90_156, "receiver gets neutralized cWUSDC");
assertEq(xaut.balanceOf(USER), userXautBefore, "XAUt collateral should be returned");
assertEq(vault.totalVirtualLoops(), 3, "virtual loop counter");
assertEq(vault.totalVirtualDebtUsdc(), 15_000_000, "virtual debt counter");
assertEq(vault.totalVirtualCwusdcIn(), 15_976_569, "virtual cWUSDC in counter");
assertEq(vault.totalNeutralizedCwusdc(), 90_156, "neutralized counter");
assertTrue(vault.usedProofIds(bytes32("proof-1")), "proof id should be consumed");
}
function testVirtualProofCanSendOutputToRecipient() public {
uint256 userCwusdcBefore = cwusdc.balanceOf(USER);
uint256 userXautBefore = xaut.balanceOf(USER);
vm.prank(USER);
vault.runVirtualProofTo(bytes32("proof-to"), LENDER_USDC, 3, OUTPUT_RECIPIENT);
assertEq(vault.poolCwusdcReserve(), LIVE_POOL_RESERVE, "pool cWUSDC reserve should not drift");
assertEq(vault.poolUsdcReserve(), LIVE_POOL_RESERVE, "pool USDC reserve should not drift");
assertEq(cwusdc.balanceOf(USER), userCwusdcBefore - 15_976_569, "sender supplies gross cWUSDC");
assertEq(cwusdc.balanceOf(OUTPUT_RECIPIENT), 15_886_413, "recipient gets cWUSDC output");
assertEq(cwusdc.balanceOf(SURPLUS_RECEIVER), 90_156, "receiver gets neutralized cWUSDC");
assertEq(xaut.balanceOf(USER), userXautBefore, "XAUt collateral should be returned");
}
function testVirtualProofExactOutToAnchorsAuditProofsAndSendsRounding() public {
uint256 userCwusdcBefore = cwusdc.balanceOf(USER);
uint256 userXautBefore = xaut.balanceOf(USER);
uint256 exactOutput = 15_886_000;
bytes32 proofId = bytes32("proof-audit");
vm.expectEmit(true, true, true, true, address(vault));
emit VirtualProofAuditEvidence(
proofId, USER, OUTPUT_RECIPIENT, exactOutput, 413, ROUNDING_RECEIVER, ISO_HASH, AUDIT_HASH, PEG_HASH
);
vm.prank(USER);
vault.runVirtualProofExactOutTo(
proofId,
LENDER_USDC,
3,
OUTPUT_RECIPIENT,
exactOutput,
ROUNDING_RECEIVER,
ISO_HASH,
AUDIT_HASH,
PEG_HASH
);
assertEq(vault.poolCwusdcReserve(), LIVE_POOL_RESERVE, "pool cWUSDC reserve should not drift");
assertEq(vault.poolUsdcReserve(), LIVE_POOL_RESERVE, "pool USDC reserve should not drift");
assertEq(cwusdc.balanceOf(USER), userCwusdcBefore - 15_976_569, "sender supplies gross cWUSDC");
assertEq(cwusdc.balanceOf(OUTPUT_RECIPIENT), exactOutput, "recipient gets exact cWUSDC");
assertEq(cwusdc.balanceOf(ROUNDING_RECEIVER), 413, "rounding receiver gets output dust");
assertEq(cwusdc.balanceOf(SURPLUS_RECEIVER), 90_156, "receiver gets neutralized cWUSDC");
assertEq(xaut.balanceOf(USER), userXautBefore, "XAUt collateral should be returned");
}
function testVirtualLoopCountScalesTotalsButNotSequentialCollateral() public view {
uint256 loops = 938_874_924;
(
uint256 collateralXaut,
uint256 cwusdcInPerLoop,,
uint256 cwusdcLossPerLoop,
uint256 totalCwusdcInAmount,,
uint256 totalNeutralizedCwusdcAmount
) = vault.previewVirtualProof(LENDER_USDC, loops);
assertEq(collateralXaut, 1_937, "sequential virtual batch reuses one loop of XAUt collateral");
assertEq(cwusdcInPerLoop, 5_325_523, "per-loop input stays constant");
assertEq(cwusdcLossPerLoop, 30_052, "per-loop neutralization stays constant");
assertEq(totalCwusdcInAmount, 5_000_000_001_885_252, "virtual batch covers 5B cWUSDC gross");
assertEq(totalNeutralizedCwusdcAmount, 28_215_069_216_048, "5B batch neutralized amount");
}
function testPreviewRevertsWhenPoolIsNotMaintained() public {
DBISEngineXVirtualBatchVault unevenVault = new DBISEngineXVirtualBatchVault(
address(cwusdc),
address(usdc),
address(xaut),
address(this),
SURPLUS_RECEIVER,
XAUT_USD_PRICE6,
LTV_BPS,
MAX_ROUND_TRIP_LOSS_BPS
);
cwusdc.mint(address(this), LIVE_POOL_RESERVE + 1);
usdc.mint(address(this), LIVE_POOL_RESERVE + LENDER_USDC);
cwusdc.approve(address(unevenVault), type(uint256).max);
usdc.approve(address(unevenVault), type(uint256).max);
unevenVault.seedPool(LIVE_POOL_RESERVE + 1, LIVE_POOL_RESERVE);
unevenVault.fundLender(LENDER_USDC);
vm.expectRevert(bytes("pool not maintained"));
unevenVault.previewVirtualProof(LENDER_USDC, 1);
}
function testRunVirtualProofRejectsDuplicateProofIds() public {
vm.prank(USER);
vault.runVirtualProof(bytes32("proof-1"), LENDER_USDC, 1);
vm.expectRevert(bytes("proof used"));
vm.prank(USER);
vault.runVirtualProof(bytes32("proof-1"), LENDER_USDC, 1);
}
function testRunVirtualProofToRejectsZeroRecipient() public {
vm.expectRevert(bytes("zero output"));
vm.prank(USER);
vault.runVirtualProofTo(bytes32("proof-zero"), LENDER_USDC, 1, address(0));
}
function testRunVirtualProofExactOutToRejectsMissingAuditHashes() public {
vm.expectRevert(bytes("zero iso hash"));
vm.prank(USER);
vault.runVirtualProofExactOutTo(
bytes32("proof-no-iso"),
LENDER_USDC,
1,
OUTPUT_RECIPIENT,
1,
ROUNDING_RECEIVER,
bytes32(0),
AUDIT_HASH,
PEG_HASH
);
}
function testRunVirtualProofExactOutToRejectsOutputAbovePreview() public {
vm.expectRevert(bytes("exact output too high"));
vm.prank(USER);
vault.runVirtualProofExactOutTo(
bytes32("proof-too-high"),
LENDER_USDC,
1,
OUTPUT_RECIPIENT,
5_295_472,
ROUNDING_RECEIVER,
ISO_HASH,
AUDIT_HASH,
PEG_HASH
);
}
}