ghost-dao-contracts/test/staking/StakingDistributor.t.sol
Uncle Fatso 46b33b4c75
initial push for smart-contracts
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2025-04-28 14:17:04 +03:00

263 lines
8.5 KiB
Solidity

pragma solidity 0.8.20;
import {Test} from "forge-std/Test.sol";
import "../../src/FatsoERC20.sol";
import "../../src/StinkyERC20.sol";
import "../../src/GhstERC20.sol";
import "../../src/GhostAuthority.sol";
import "../../src/StakingDistributor.sol";
import "../../src/Treasury.sol";
import "../../src/Staking.sol";
import "../../src/mocks/ERC20Mock.sol";
contract StakingDistributorTest is Test {
address public constant owner = 0x0000000000000000000000000000000000000001;
address public constant governor = 0x0000000000000000000000000000000000000002;
address public constant guardian = 0x0000000000000000000000000000000000000003;
address public constant other = 0x0000000000000000000000000000000000000004;
address public constant alice = 0x0000000000000000000000000000000000000005;
address public constant bob = 0x0000000000000000000000000000000000000006;
uint48 public constant EPOCH_LENGTH = 2200;
uint48 public constant EPOCH_NUMBER = 1;
uint48 public constant EPOCH_END_TIME = 1337;
uint256 public constant INITIAL_INDEX = 10819917194513808e56;
uint256 public constant amount = 69 * 1e18;
Fatso ftso;
Stinky stnk;
Ghost ghst;
ERC20Mock reserve;
GhostTreasury treasury;
GhostStaking staking;
GhostDistributor distributor;
GhostAuthority authority;
uint256 public constant TEN_PERCENT = 1e5;
function setUp() public {
vm.startPrank(owner);
authority = new GhostAuthority(
governor,
guardian,
owner,
owner
);
reserve = new ERC20Mock("Reserve Token", "RET");
ftso = new Fatso(address(authority));
stnk = new Stinky(INITIAL_INDEX);
ghst = new Ghost(address(stnk));
staking = new GhostStaking(
address(ftso),
address(stnk),
address(ghst),
EPOCH_LENGTH,
EPOCH_NUMBER,
EPOCH_END_TIME,
address(authority)
);
treasury = new GhostTreasury(address(ftso), 69, address(authority));
distributor = new GhostDistributor(
address(treasury),
address(ftso),
address(staking),
address(authority),
TEN_PERCENT
);
stnk.initialize(address(staking), address(treasury), address(ghst));
ghst.initialize(address(staking));
vm.stopPrank();
vm.startPrank(governor);
staking.setDistributor(address(distributor));
authority.pushVault(address(treasury));
vm.stopPrank();
}
function test_distribute_onlyByStaking() public {
_prepareTreasury();
vm.expectRevert();
vm.prank(other);
distributor.distribute();
vm.prank(address(staking));
distributor.distribute();
}
function test_bounty_onlyByGovernor(address who) public {
vm.assume(who != governor);
_prepareTreasury();
assertEq(ftso.balanceOf(address(staking)), 0);
vm.prank(governor);
distributor.setBounty(1337);
vm.prank(address(staking));
distributor.retrieveBounty();
assertEq(ftso.balanceOf(address(staking)), 1337);
}
function test_nextRewardFor_zeroIfAddressIsEmpty() public view {
assertEq(ftso.balanceOf(bob), 0);
assertEq(distributor.nextRewardFor(bob), 0);
}
function test_nextRewardFor_nextRewardForAddress() public {
_prepareTreasury();
vm.startPrank(bob);
reserve.mint(bob, amount);
reserve.approve(address(treasury), amount);
uint256 send = treasury.deposit(address(reserve), amount, treasury.tokenValue(address(reserve), amount));
vm.stopPrank();
assertEq(ftso.balanceOf(bob), send);
assertEq(distributor.nextRewardFor(bob), send * TEN_PERCENT / 1e6);
}
function test_setBounty_shouldRevertIfNotByGovernor(address who) public {
vm.assume(who != governor);
assertEq(distributor.bounty(), 0);
vm.expectRevert();
vm.prank(who);
distributor.setBounty(69);
assertEq(distributor.bounty(), 0);
}
function test_setBounty_governorShouldSet() public {
_prepareTreasury();
assertEq(distributor.bounty(), 0);
vm.prank(governor);
distributor.setBounty(1337);
assertEq(distributor.bounty(), 1337);
}
function test_setPools_shouldRevertIfNotGovernor(address who) public {
vm.assume(who != governor);
address[] memory newPools = new address[](1);
newPools[0] = who;
vm.expectRevert();
vm.prank(who);
distributor.setPools(newPools);
}
function test_setPools_governorShouldSet() public {
address[] memory newPools = new address[](1);
newPools[0] = other;
vm.prank(governor);
distributor.setPools(newPools);
assertEq(distributor.pools(0), other);
}
function test_removePools_shouldRevertIfNotGovernor(address who) public {
vm.assume(who != governor);
address[] memory newPools = new address[](1);
newPools[0] = other;
vm.prank(governor);
distributor.setPools(newPools);
vm.expectRevert();
vm.prank(who);
distributor.removePool(0);
}
function test_removePools_governorShouldRemove() public {
address[] memory newPools = new address[](1);
newPools[0] = other;
vm.startPrank(governor);
distributor.setPools(newPools);
assertEq(distributor.pools(0), other);
distributor.removePool(0);
vm.stopPrank();
}
function test_addPool_shouldRevertIfNotGovernor(address who) public {
vm.assume(who != governor);
vm.expectRevert();
vm.prank(who);
distributor.addPool(other);
}
function test_addPool_shouldPushPoolWhenIndexTaken() public {
vm.prank(governor);
distributor.addPool(other);
assertEq(distributor.pools(0), other);
}
function test_setAdjustment_shouldRevertIfNotGovernor(address who) public {
vm.assume(who != governor && who != guardian);
vm.expectRevert();
vm.prank(who);
distributor.setAdjustment(69, 1337, true);
}
function test_setAdjustment_governorShouldIncreaseAdjustment() public {
vm.prank(governor);
distributor.setAdjustment(69, 1337, false);
}
function test_setAdjustment_shouldPopulateAdjustmentToRewardRateAfterRebase() public {
vm.prank(governor);
distributor.setAdjustment(69, TEN_PERCENT * 2, true);
_prepareTreasury();
assertEq(distributor.rewardRate(), TEN_PERCENT);
(,, uint256 end,) = staking.epoch();
skip(end);
staking.rebase();
assertEq(distributor.rewardRate(), TEN_PERCENT + 69);
}
function test_setAdjustment_willNotAdjustIfRateIsZero() public {
vm.prank(governor);
distributor.setAdjustment(0, 1337, true);
_prepareTreasury();
assertEq(distributor.rewardRate(), TEN_PERCENT);
(,, uint256 end,) = staking.epoch();
skip(end);
staking.rebase();
assertEq(distributor.rewardRate(), TEN_PERCENT);
}
function test_setAdjustment_willStopIncreaseWhenTargetMet() public {
vm.prank(governor);
distributor.setAdjustment(69, 1337, true);
_prepareTreasury();
assertEq(distributor.rewardRate(), TEN_PERCENT);
(,, uint256 end,) = staking.epoch();
skip(end);
staking.rebase();
assertEq(distributor.rewardRate(), 1337);
}
function test_setAdjustment_willStopDecreaseWhenTargetMet() public {
vm.prank(governor);
distributor.setAdjustment(TEN_PERCENT, 1337, false);
_prepareTreasury();
assertEq(distributor.rewardRate(), TEN_PERCENT);
(,, uint256 end,) = staking.epoch();
skip(end);
staking.rebase();
assertEq(distributor.rewardRate(), 1337);
}
function _prepareTreasury() internal {
vm.startPrank(governor);
treasury.enable(ITreasury.STATUS.REWARDMANAGER, address(distributor), address(0));
treasury.enable(ITreasury.STATUS.RESERVEDEPOSITOR, alice, address(0));
treasury.enable(ITreasury.STATUS.RESERVEDEPOSITOR, bob, address(0));
treasury.enable(ITreasury.STATUS.RESERVETOKEN, address(reserve), address(0));
vm.stopPrank();
vm.startPrank(alice);
reserve.mint(alice, amount);
reserve.approve(address(treasury), amount);
treasury.deposit(address(reserve), amount, treasury.tokenValue(address(reserve), amount));
vm.stopPrank();
}
}