Files
smom-dbis-138/test/bridge/USDWPublicWrapVault.t.sol
defiQUG 76aa419320 feat: bridges, PMM, flash workflow, token-aggregation, and deployment docs
- CCIP/trustless bridge contracts, GRU tokens, DEX/PMM tests, reserve vault.
- Token-aggregation service routes, planner, chain config, relay env templates.
- Config snapshots and multi-chain deployment markdown updates.
- gitignore services/btc-intake/dist/ (tsc output); do not track dist.

Run forge build && forge test before deploy (large solc graph).

Made-with: Cursor
2026-04-07 23:40:52 -07:00

125 lines
4.3 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Test} from "forge-std/Test.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {USDWPublicWrapVault} from "../../contracts/bridge/integration/USDWPublicWrapVault.sol";
import {CompliantWrappedToken} from "../../contracts/tokens/CompliantWrappedToken.sol";
contract MockNativeUSDW is ERC20 {
uint8 private immutable _decimalsValue;
constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {
_decimalsValue = decimals_;
}
function decimals() public view override returns (uint8) {
return _decimalsValue;
}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
}
contract USDWPublicWrapVaultTest is Test {
address internal admin = address(0xA11CE);
address internal operator = address(0xB0B);
address internal user = address(0xCAFE);
address internal bridgeUser = address(0xD00D);
MockNativeUSDW internal nativeUsdw;
MockNativeUSDW internal strayToken;
CompliantWrappedToken internal wrappedUsdw;
USDWPublicWrapVault internal vault;
function setUp() public {
vm.startPrank(admin);
nativeUsdw = new MockNativeUSDW("USD DWIN", "USDW", 18);
strayToken = new MockNativeUSDW("Stray", "STRAY", 18);
wrappedUsdw = new CompliantWrappedToken("Wrapped cUSDW", "cWUSDW", 6, admin);
vault = new USDWPublicWrapVault(admin, address(nativeUsdw), address(wrappedUsdw));
vault.grantRole(vault.RESERVE_OPERATOR_ROLE(), operator);
wrappedUsdw.grantRole(wrappedUsdw.MINTER_ROLE(), address(vault));
wrappedUsdw.grantRole(wrappedUsdw.BURNER_ROLE(), address(vault));
vm.stopPrank();
nativeUsdw.mint(user, 100e18);
nativeUsdw.mint(operator, 100e18);
strayToken.mint(address(vault), 5e18);
}
function testWrapNormalizesNativeAmountToWrappedDecimals() public {
vm.startPrank(user);
nativeUsdw.approve(address(vault), 5e18);
uint256 wrappedAmount = vault.wrap(5e18, user);
vm.stopPrank();
assertEq(wrappedAmount, 5e6);
assertEq(wrappedUsdw.balanceOf(user), 5e6);
assertEq(nativeUsdw.balanceOf(address(vault)), 5e18);
assertEq(nativeUsdw.balanceOf(user), 95e18);
}
function testUnwrapBurnsWrappedAndReleasesNativeUsd() public {
vm.startPrank(user);
nativeUsdw.approve(address(vault), 7e18);
vault.wrap(7e18, user);
uint256 unwrapped = vault.unwrap(2e6, user);
vm.stopPrank();
assertEq(unwrapped, 2e18);
assertEq(wrappedUsdw.balanceOf(user), 5e6);
assertEq(nativeUsdw.balanceOf(user), 95e18);
assertEq(nativeUsdw.balanceOf(address(vault)), 5e18);
}
function testBridgeMintedSupplyCanUnwrapAgainstSeededLiquidity() public {
vm.prank(operator);
nativeUsdw.approve(address(vault), 20e18);
vm.prank(operator);
vault.seedLiquidity(20e18);
vm.prank(admin);
wrappedUsdw.mint(bridgeUser, 3e6);
vm.prank(bridgeUser);
uint256 released = vault.unwrap(3e6, bridgeUser);
assertEq(released, 3e18);
assertEq(nativeUsdw.balanceOf(bridgeUser), 3e18);
assertEq(nativeUsdw.balanceOf(address(vault)), 17e18);
assertEq(wrappedUsdw.balanceOf(bridgeUser), 0);
}
function testWrapRejectsNonCanonicalNativeAmount() public {
vm.startPrank(user);
nativeUsdw.approve(address(vault), 1e18 + 1);
vm.expectRevert(abi.encodeWithSelector(USDWPublicWrapVault.NonCanonicalAmount.selector, 1e18 + 1));
vault.wrap(1e18 + 1, user);
vm.stopPrank();
}
function testPauseBlocksWrapAndUnwrap() public {
vm.prank(admin);
vault.pause();
vm.startPrank(user);
nativeUsdw.approve(address(vault), 1e18);
vm.expectRevert();
vault.wrap(1e18, user);
vm.stopPrank();
}
function testRecoverNonUnderlyingTokenButProtectNativeReserve() public {
vm.prank(admin);
vault.recoverNonUnderlyingToken(address(strayToken), admin, 5e18);
assertEq(strayToken.balanceOf(admin), 5e18);
vm.prank(admin);
vm.expectRevert(USDWPublicWrapVault.UnderlyingTokenProtected.selector);
vault.recoverNonUnderlyingToken(address(nativeUsdw), admin, 1);
}
}