188 lines
5.2 KiB
Solidity
188 lines
5.2 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import "forge-std/Test.sol";
|
|
import "../src/Treasury.sol";
|
|
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
|
|
contract MockStablecoin is ERC20 {
|
|
constructor() ERC20("USD Coin", "USDC") {}
|
|
|
|
function decimals() public pure override returns (uint8) {
|
|
return 6;
|
|
}
|
|
|
|
function mint(address to, uint256 amount) external {
|
|
_mint(to, amount);
|
|
}
|
|
}
|
|
|
|
contract TreasuryTest is Test {
|
|
Treasury treasury;
|
|
MockStablecoin usdc;
|
|
|
|
address admin = address(1);
|
|
address feeCollector = address(2);
|
|
address issuer = address(3);
|
|
address buyer = address(4);
|
|
address seller = address(5);
|
|
address claimant1 = address(6);
|
|
address claimant2 = address(7);
|
|
|
|
function setUp() public {
|
|
vm.startPrank(admin);
|
|
|
|
usdc = new MockStablecoin();
|
|
treasury = new Treasury();
|
|
treasury.initialize(address(usdc), feeCollector, admin);
|
|
|
|
// Fund accounts
|
|
usdc.mint(issuer, 100_000e6);
|
|
usdc.mint(buyer, 100_000e6);
|
|
usdc.mint(seller, 100_000e6);
|
|
|
|
vm.stopPrank();
|
|
|
|
// Approvals
|
|
vm.prank(issuer);
|
|
usdc.approve(address(treasury), type(uint256).max);
|
|
vm.prank(buyer);
|
|
usdc.approve(address(treasury), type(uint256).max);
|
|
vm.prank(seller);
|
|
usdc.approve(address(treasury), type(uint256).max);
|
|
}
|
|
|
|
// === Guarantee Fund ===
|
|
|
|
function test_DepositGuaranteeFund() public {
|
|
vm.prank(issuer);
|
|
treasury.depositGuaranteeFund(10000e6);
|
|
assertEq(treasury.guaranteeFunds(issuer), 10000e6);
|
|
}
|
|
|
|
function test_WithdrawGuaranteeFund() public {
|
|
vm.prank(issuer);
|
|
treasury.depositGuaranteeFund(10000e6);
|
|
|
|
vm.prank(admin);
|
|
treasury.withdrawGuaranteeFund(issuer, 5000e6);
|
|
assertEq(treasury.guaranteeFunds(issuer), 5000e6);
|
|
}
|
|
|
|
function test_ActivateGuaranteeFund() public {
|
|
vm.prank(issuer);
|
|
treasury.depositGuaranteeFund(10000e6);
|
|
|
|
address[] memory claimants = new address[](2);
|
|
claimants[0] = claimant1;
|
|
claimants[1] = claimant2;
|
|
uint256[] memory amounts = new uint256[](2);
|
|
amounts[0] = 3000e6;
|
|
amounts[1] = 2000e6;
|
|
|
|
vm.prank(admin);
|
|
treasury.activateGuaranteeFund(issuer, claimants, amounts);
|
|
|
|
assertEq(usdc.balanceOf(claimant1), 3000e6);
|
|
assertEq(usdc.balanceOf(claimant2), 2000e6);
|
|
assertEq(treasury.guaranteeFunds(issuer), 5000e6);
|
|
}
|
|
|
|
function test_ActivateInsufficientReverts() public {
|
|
vm.prank(issuer);
|
|
treasury.depositGuaranteeFund(1000e6);
|
|
|
|
address[] memory claimants = new address[](1);
|
|
claimants[0] = claimant1;
|
|
uint256[] memory amounts = new uint256[](1);
|
|
amounts[0] = 5000e6;
|
|
|
|
vm.prank(admin);
|
|
vm.expectRevert("Treasury: insufficient guarantee fund");
|
|
treasury.activateGuaranteeFund(issuer, claimants, amounts);
|
|
}
|
|
|
|
// === Escrow ===
|
|
|
|
function test_EscrowAndRelease() public {
|
|
vm.prank(admin);
|
|
treasury.escrow(1, buyer, 1000e6);
|
|
|
|
assertEq(usdc.balanceOf(address(treasury)), 1000e6);
|
|
|
|
vm.prank(admin);
|
|
treasury.release(1, seller, 950e6, 50e6);
|
|
|
|
assertEq(usdc.balanceOf(seller), 100_000e6 + 950e6);
|
|
assertEq(usdc.balanceOf(feeCollector), 50e6);
|
|
}
|
|
|
|
function test_EscrowRefund() public {
|
|
uint256 buyerBefore = usdc.balanceOf(buyer);
|
|
|
|
vm.prank(admin);
|
|
treasury.escrow(1, buyer, 1000e6);
|
|
|
|
vm.prank(admin);
|
|
treasury.refundEscrow(1);
|
|
|
|
assertEq(usdc.balanceOf(buyer), buyerBefore);
|
|
}
|
|
|
|
function test_DoubleReleaseReverts() public {
|
|
vm.prank(admin);
|
|
treasury.escrow(1, buyer, 1000e6);
|
|
|
|
vm.prank(admin);
|
|
treasury.release(1, seller, 950e6, 50e6);
|
|
|
|
vm.prank(admin);
|
|
vm.expectRevert("Treasury: already settled");
|
|
treasury.release(1, seller, 950e6, 50e6);
|
|
}
|
|
|
|
function test_ReleaseExceedsEscrowReverts() public {
|
|
vm.prank(admin);
|
|
treasury.escrow(1, buyer, 1000e6);
|
|
|
|
vm.prank(admin);
|
|
vm.expectRevert("Treasury: exceeds escrow");
|
|
treasury.release(1, seller, 1000e6, 100e6);
|
|
}
|
|
|
|
function test_DuplicateEscrowReverts() public {
|
|
vm.prank(admin);
|
|
treasury.escrow(1, buyer, 1000e6);
|
|
|
|
vm.prank(admin);
|
|
vm.expectRevert("Treasury: escrow exists");
|
|
treasury.escrow(1, buyer, 500e6);
|
|
}
|
|
|
|
// === Sales Revenue ===
|
|
|
|
function test_FreezeSalesRevenue() public {
|
|
vm.prank(issuer);
|
|
treasury.freezeSalesRevenue(5000e6);
|
|
assertEq(treasury.frozenSalesRevenue(issuer), 5000e6);
|
|
}
|
|
|
|
function test_ReleaseSalesRevenue() public {
|
|
vm.prank(issuer);
|
|
treasury.freezeSalesRevenue(5000e6);
|
|
|
|
vm.prank(admin);
|
|
treasury.releaseSalesRevenue(issuer, 3000e6);
|
|
assertEq(treasury.frozenSalesRevenue(issuer), 2000e6);
|
|
}
|
|
|
|
// === Fee Collector ===
|
|
|
|
function test_SetPlatformFeeCollector() public {
|
|
address newCollector = address(99);
|
|
vm.prank(admin);
|
|
treasury.setPlatformFeeCollector(newCollector);
|
|
assertEq(treasury.platformFeeCollector(), newCollector);
|
|
}
|
|
}
|