263 lines
8.5 KiB
Solidity
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();
|
|
}
|
|
}
|