2023-05-27 15:29:13 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
pragma solidity ^0.6.12;
|
|
|
|
pragma experimental ABIEncoderV2;
|
|
|
|
|
|
|
|
import { console2 } from "@forge-std/console2.sol";
|
|
|
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
|
|
|
|
|
|
import { MockProposal } from "./MockProposal.sol";
|
|
|
|
import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.sol";
|
|
|
|
import { RelayerRegistry } from "@root/v4-patch/RelayerRegistry.sol";
|
|
|
|
import { TornadoStakingRewards } from "@root/v4-patch/TornadoStakingRewards.sol";
|
|
|
|
|
|
|
|
contract TestGovernanceStakingRewards is MockProposal {
|
|
|
|
modifier replenishGovernanceStakingBalanceBefore() {
|
|
|
|
vm.startPrank(_governanceAddress);
|
|
|
|
IERC20(_tokenAddress).transfer(getStakingProxyAddress(), 100_000 ether);
|
|
|
|
vm.stopPrank();
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
function burnTokens(address caller, uint256 amount, TornadoStakingRewards staking) internal {
|
|
|
|
vm.startPrank(caller);
|
|
|
|
staking.addBurnRewards(amount);
|
|
|
|
vm.stopPrank();
|
|
|
|
}
|
|
|
|
|
|
|
|
function testAccumulatedRewardCanBeUpdated()
|
|
|
|
public
|
|
|
|
executeAttackerProposalBefore
|
|
|
|
executeCurrentProposalBefore
|
|
|
|
{
|
|
|
|
TornadoStakingRewards staking = TornadoStakingRewards(getStakingProxyAddress());
|
|
|
|
|
|
|
|
uint256 accumulatedRewardPerTornBeforeBurning =
|
|
|
|
staking.accumulatedRewardPerTorn() / _tornMaximumSupply;
|
|
|
|
|
|
|
|
console2.log(
|
|
|
|
"Accumulated reward per TORN right after proposal execution: %s TORN",
|
2023-06-01 12:38:49 -07:00
|
|
|
accumulatedRewardPerTornBeforeBurning / _tornDecimals
|
2023-05-27 15:29:13 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
burnTokens(_governanceAddress, 10_000_000 ether, staking);
|
|
|
|
|
|
|
|
uint256 accumulatedRewardPerTornAfterBurning = staking.accumulatedRewardPerTorn() / _tornMaximumSupply;
|
|
|
|
|
|
|
|
console2.log(
|
|
|
|
"Accumulated reward per TORN after burning 10 000 000 TORN: ~ %s TORN",
|
2023-06-01 12:38:49 -07:00
|
|
|
accumulatedRewardPerTornAfterBurning / _tornDecimals
|
2023-05-27 15:29:13 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
require(
|
|
|
|
accumulatedRewardPerTornAfterBurning > accumulatedRewardPerTornBeforeBurning,
|
|
|
|
"Staking rewards isn't updated"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testStakerCanGetRewards()
|
|
|
|
public
|
|
|
|
executeAttackerProposalBefore
|
|
|
|
executeCurrentProposalBefore
|
|
|
|
replenishGovernanceStakingBalanceBefore
|
|
|
|
{
|
|
|
|
TornadoStakingRewards staking = TornadoStakingRewards(getStakingProxyAddress());
|
|
|
|
IERC20 TORN = IERC20(_tokenAddress);
|
|
|
|
|
|
|
|
uint256 toBurn = 10_000 ether;
|
|
|
|
|
2023-06-01 12:38:49 -07:00
|
|
|
retrieveAndLockBalance(TEST_STAKER_PRIVATE_KEY, TEST_STAKER_ADDRESS, PROPOSAL_THRESHOLD);
|
|
|
|
uint256 stakerLockedBalance = governance.lockedBalance(TEST_STAKER_ADDRESS);
|
|
|
|
require(stakerLockedBalance == PROPOSAL_THRESHOLD, "Invalid test staker locked balance");
|
2023-05-27 15:29:13 +00:00
|
|
|
|
2023-06-01 12:38:49 -07:00
|
|
|
uint256 stakerRewardsBeforeBurning = staking.checkReward(TEST_STAKER_ADDRESS);
|
|
|
|
console2.log("Staking rewards before burning: %s TORN", stakerRewardsBeforeBurning / _tornDecimals);
|
2023-05-27 15:29:13 +00:00
|
|
|
|
|
|
|
burnTokens(_governanceAddress, toBurn, staking);
|
|
|
|
|
2023-06-01 12:38:49 -07:00
|
|
|
uint256 stakerRewardsAfterBurning = staking.checkReward(TEST_STAKER_ADDRESS);
|
2023-05-27 18:56:29 +03:00
|
|
|
console2.log(
|
2023-06-01 12:38:49 -07:00
|
|
|
"Staking rewards after burning 10 000 TORN: %s TORN\n", stakerRewardsAfterBurning / _tornDecimals
|
2023-05-27 18:56:29 +03:00
|
|
|
);
|
2023-05-27 15:29:13 +00:00
|
|
|
require(stakerRewardsAfterBurning > stakerRewardsBeforeBurning, "Rewards isn't changed after burning");
|
|
|
|
|
|
|
|
// All TORN, locked by users in Governance, is on the userVault contract balance
|
|
|
|
uint256 governanceLockedAmount = TORN.balanceOf(address(governance.userVault()));
|
|
|
|
uint256 receivedReward = stakerRewardsAfterBurning - stakerRewardsBeforeBurning;
|
|
|
|
uint256 expectedRewards = stakerLockedBalance * toBurn / governanceLockedAmount;
|
|
|
|
|
2023-06-01 12:38:49 -07:00
|
|
|
console2.log("Expected staking rewards: %s TORN", expectedRewards / _tornDecimals);
|
|
|
|
console2.log("Staker received rewards: %s TORN\n", receivedReward / _tornDecimals);
|
2023-05-27 15:29:13 +00:00
|
|
|
|
|
|
|
require(receivedReward == expectedRewards, "Expected and received rewards don't match");
|
|
|
|
|
2023-06-01 12:38:49 -07:00
|
|
|
uint256 stakerTORNbalanceBeforeGettingRewards = TORN.balanceOf(TEST_STAKER_ADDRESS);
|
2023-05-27 15:29:13 +00:00
|
|
|
console2.log(
|
|
|
|
"Staker balance before getting (withdrawal) collected rewards: %s TORN",
|
2023-06-01 12:38:49 -07:00
|
|
|
stakerTORNbalanceBeforeGettingRewards / _tornDecimals
|
2023-05-27 15:29:13 +00:00
|
|
|
);
|
|
|
|
|
2023-06-01 12:38:49 -07:00
|
|
|
vm.startPrank(TEST_STAKER_ADDRESS);
|
2023-05-27 15:29:13 +00:00
|
|
|
staking.getReward();
|
|
|
|
vm.stopPrank();
|
|
|
|
|
2023-06-01 12:38:49 -07:00
|
|
|
uint256 stakerTORNbalanceAfterGettingRewards = TORN.balanceOf(TEST_STAKER_ADDRESS);
|
2023-05-27 15:29:13 +00:00
|
|
|
console2.log(
|
|
|
|
"Staker balance after getting (withdrawal) collected rewards: %s TORN",
|
2023-06-01 12:38:49 -07:00
|
|
|
stakerTORNbalanceAfterGettingRewards / _tornDecimals
|
2023-05-27 15:29:13 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
require(
|
|
|
|
stakerTORNbalanceAfterGettingRewards > stakerTORNbalanceBeforeGettingRewards,
|
|
|
|
"Rewards isn't withdrawed"
|
|
|
|
);
|
|
|
|
require(
|
|
|
|
stakerTORNbalanceAfterGettingRewards - stakerTORNbalanceBeforeGettingRewards == receivedReward,
|
|
|
|
"Incorrect rewards amount withdrawed"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testCanBurnFromRelayerRegistry() public {
|
|
|
|
TornadoStakingRewards staking = TornadoStakingRewards(getStakingProxyAddress());
|
|
|
|
address relayerRegistryAddress = getRelayerRegistryProxyAddress();
|
|
|
|
|
|
|
|
uint256 accumulatedRewardPerTornBeforeBurning = staking.accumulatedRewardPerTorn();
|
|
|
|
|
|
|
|
burnTokens(relayerRegistryAddress, 10_000 ether, staking);
|
|
|
|
|
|
|
|
require(
|
|
|
|
staking.accumulatedRewardPerTorn() > accumulatedRewardPerTornBeforeBurning,
|
|
|
|
"Burn from relayer registry failed"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|