126 lines
4.1 KiB
Solidity
126 lines
4.1 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 {Chain138LPLocker} from "../../contracts/wrapped-lp-public/Chain138LPLocker.sol";
|
|
import {WLPReceiptToken} from "../../contracts/wrapped-lp-public/WLPReceiptToken.sol";
|
|
import {PublicChainMintController} from "../../contracts/wrapped-lp-public/PublicChainMintController.sol";
|
|
import {WLPRedemptionGateway} from "../../contracts/wrapped-lp-public/WLPRedemptionGateway.sol";
|
|
import {WrappedLPNAVVault} from "../../contracts/wrapped-lp-public/WrappedLPNAVVault.sol";
|
|
import {WLPNAVOracle} from "../../contracts/wrapped-lp-public/WLPNAVOracle.sol";
|
|
|
|
contract MockERC20 is ERC20 {
|
|
constructor(string memory n, string memory s) ERC20(n, s) {}
|
|
|
|
function mint(address to, uint256 a) external {
|
|
_mint(to, a);
|
|
}
|
|
}
|
|
|
|
contract WrappedLPProgramTest is Test {
|
|
MockERC20 lp;
|
|
Chain138LPLocker locker;
|
|
WLPReceiptToken wlp;
|
|
PublicChainMintController mintCtl;
|
|
WLPRedemptionGateway gateway;
|
|
|
|
address admin = address(this);
|
|
address relayer = address(0xBEEF);
|
|
address user = address(0xA11CE);
|
|
|
|
function setUp() public {
|
|
lp = new MockERC20("DODO LP", "DLP");
|
|
locker = new Chain138LPLocker(address(lp), admin);
|
|
wlp = new WLPReceiptToken("Wrapped LP", "wLP", 18, admin);
|
|
mintCtl = new PublicChainMintController(address(wlp), address(locker), admin);
|
|
gateway = new WLPRedemptionGateway(address(wlp), admin);
|
|
|
|
wlp.grantRole(wlp.MINTER_ROLE(), address(mintCtl));
|
|
wlp.grantRole(wlp.BURNER_ROLE(), address(gateway));
|
|
mintCtl.grantRole(mintCtl.RELAYER_ROLE(), relayer);
|
|
locker.grantRole(locker.BRIDGE_RELEASE_ROLE(), relayer);
|
|
}
|
|
|
|
function test_lock_mint_release_invariant() public {
|
|
uint256 amt = 1000e18;
|
|
lp.mint(user, amt);
|
|
vm.startPrank(user);
|
|
lp.approve(address(locker), amt);
|
|
bytes32 lockRef = locker.deposit(amt);
|
|
vm.stopPrank();
|
|
|
|
assertEq(locker.totalEscrowed(), amt);
|
|
|
|
vm.prank(relayer);
|
|
mintCtl.mintForLock(lockRef, user, amt);
|
|
assertEq(wlp.balanceOf(user), amt);
|
|
|
|
vm.expectRevert();
|
|
vm.prank(relayer);
|
|
mintCtl.mintForLock(lockRef, user, amt);
|
|
|
|
vm.prank(user);
|
|
gateway.requestRedeem(amt);
|
|
assertEq(wlp.balanceOf(user), 0);
|
|
|
|
vm.prank(relayer);
|
|
locker.releaseAmount(user, amt);
|
|
assertEq(locker.totalEscrowed(), 0);
|
|
assertEq(lp.balanceOf(user), amt);
|
|
}
|
|
|
|
function test_nav_vault_cap() public {
|
|
MockERC20 usdc = new MockERC20("USDC", "USDC");
|
|
WrappedLPNAVVault vault = new WrappedLPNAVVault(
|
|
usdc,
|
|
"Wrapped LP NAV Vault",
|
|
"wLPV",
|
|
admin
|
|
);
|
|
vault.setDepositCap(1_000_000e18);
|
|
usdc.mint(user, 2_000_000e18);
|
|
vm.startPrank(user);
|
|
usdc.approve(address(vault), type(uint256).max);
|
|
vm.expectRevert();
|
|
vault.deposit(1_500_000e18, user);
|
|
vm.stopPrank();
|
|
}
|
|
|
|
function test_nav_oracle_stale() public {
|
|
WLPNAVOracle oracle = new WLPNAVOracle(admin, 3600);
|
|
oracle.grantRole(oracle.KEEPER_ROLE(), relayer);
|
|
vm.prank(relayer);
|
|
oracle.submitAnswer(1e8);
|
|
assertFalse(oracle.isStale());
|
|
vm.warp(block.timestamp + 4000);
|
|
assertTrue(oracle.isStale());
|
|
}
|
|
|
|
/// @notice Fuzz: distinct deposits yield distinct lockRefs and independent mints.
|
|
function testFuzz_lockRef_unique(uint128 amtA, uint128 amtB) public {
|
|
vm.assume(amtA > 0 && amtB > 0);
|
|
vm.assume(amtA != amtB);
|
|
|
|
uint256 a = uint256(amtA) * 1e10;
|
|
uint256 b = uint256(amtB) * 1e10;
|
|
|
|
lp.mint(user, a + b);
|
|
vm.startPrank(user);
|
|
lp.approve(address(locker), a + b);
|
|
bytes32 rA = locker.deposit(a);
|
|
bytes32 rB = locker.deposit(b);
|
|
vm.stopPrank();
|
|
|
|
assertTrue(rA != rB);
|
|
|
|
vm.startPrank(relayer);
|
|
mintCtl.mintForLock(rA, user, a);
|
|
mintCtl.mintForLock(rB, user, b);
|
|
vm.stopPrank();
|
|
|
|
assertEq(wlp.balanceOf(user), a + b);
|
|
}
|
|
}
|