harb/onchain/test/Stake.t.sol
2024-06-19 10:33:28 +02:00

106 lines
4.1 KiB
Solidity

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import "forge-std/console.sol";
import {TwabController} from "pt-v5-twab-controller/TwabController.sol";
import "../src/Harb.sol";
import "../src/Stake.sol";
contract StakeTest is Test {
TwabController tc;
Harb harb;
Stake stakingPool;
address liquidityPool;
address liquidityManager;
address taxPool;
event PositionCreated(uint256 indexed positionId, address indexed owner, uint256 share, uint32 creationTime, uint32 taxRate);
event PositionRemoved(uint256 indexed positionId, uint256 share, uint32 lastTaxTime);
function setUp() public {
tc = new TwabController(60 * 60, uint32(block.timestamp));
harb = new Harb("HARB", "HARB", tc);
taxPool = harb.TAX_POOL();
stakingPool = new Stake(address(harb));
harb.setStakingPool(address(stakingPool));
liquidityPool = makeAddr("liquidityPool");
harb.setLiquidityPool(liquidityPool);
liquidityManager = makeAddr("liquidityManager");
harb.setLiquidityManager(liquidityManager);
}
function testBasicStaking() public {
// Setup
uint256 stakeAmount = 1 ether;
address staker = makeAddr("staker");
vm.startPrank(liquidityManager);
harb.mint(stakeAmount * 5);
harb.transfer(staker, stakeAmount);
vm.stopPrank();
vm.startPrank(staker);
// Approve and stake
harb.approve(address(stakingPool), stakeAmount);
uint256[] memory empty;
uint256 sharesExpected = stakingPool.assetsToShares(stakeAmount);
vm.expectEmit(address(stakingPool));
emit PositionCreated(654321, staker, sharesExpected, uint32(block.timestamp), 1);
uint256 positionId = stakingPool.snatch(stakeAmount, staker, 1, empty);
// Check results
assertEq(stakingPool.outstandingStake(), stakingPool.assetsToShares(stakeAmount), "Outstanding stake did not update correctly");
(uint256 share, address owner, uint32 creationTime, , uint32 taxRate) = stakingPool.positions(positionId);
assertEq(stakingPool.sharesToAssets(share), stakeAmount, "Stake amount in position is incorrect");
assertEq(owner, staker, "Stake owner is incorrect");
assertEq(creationTime, uint32(block.timestamp), "Creation time is incorrect");
assertEq(taxRate, 1, "Tax rate should be initialized to 1");
vm.stopPrank();
}
function testUnstaking() public {
// Setup: Create a staking position first
uint256 stakeAmount = 1 ether;
address staker = makeAddr("staker");
vm.startPrank(liquidityManager);
harb.mint(stakeAmount * 5); // Ensuring the staker has enough balance
harb.transfer(staker, stakeAmount);
vm.stopPrank();
// Staker stakes tokens
vm.startPrank(staker);
harb.approve(address(stakingPool), stakeAmount);
uint256[] memory empty;
uint256 positionId = stakingPool.snatch(stakeAmount, staker, 1, empty);
// Simulate time passage to accumulate tax liability
vm.warp(block.timestamp + 3 days);
// Calculate expected tax due at the moment of unstaking
uint256 taxAmount = stakingPool.taxDue(positionId, 0);
uint256 assetsAfterTax = stakeAmount - taxAmount;
// Expect the PositionRemoved event with the expected parameters
vm.expectEmit(true, true, true, true);
emit PositionRemoved(positionId, stakingPool.assetsToShares(stakeAmount - taxAmount), uint32(block.timestamp));
// Perform unstaking
stakingPool.exitPosition(positionId);
// Check results after unstaking
assertEq(harb.balanceOf(staker), assetsAfterTax, "Assets after tax not returned correctly");
assertEq(stakingPool.outstandingStake(), 0, "Outstanding stake not updated correctly");
// Ensure the position is cleared
(, address owner, uint32 time, , ) = stakingPool.positions(positionId);
assertEq(time, 0, "Position time not cleared");
assertEq(owner, address(0), "Position owner not cleared");
vm.stopPrank();
}
}