LCOV - code coverage report
Current view: top level - reference - TornadoStakingRewards.sol (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 19 0.0 %
Date: 2023-06-19 00:07:36 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // SPDX-License-Identifier: MIT
       2             : 
       3             : pragma solidity ^0.6.12;
       4             : pragma experimental ABIEncoderV2;
       5             : 
       6             : import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
       7             : import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
       8             : import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
       9             : import { Initializable } from "@openzeppelin/contracts/proxy/Initializable.sol";
      10             : import { EnsResolve } from "torn-token/contracts/ENS.sol";
      11             : 
      12             : interface ITornadoVault {
      13             :     function withdrawTorn(address recipient, uint256 amount) external;
      14             : }
      15             : 
      16             : interface ITornadoGovernance {
      17             :     function lockedBalance(address account) external view returns (uint256);
      18             : 
      19             :     function userVault() external view returns (ITornadoVault);
      20             : }
      21             : 
      22             : /**
      23             :  * @notice This is the staking contract of the governance staking upgrade.
      24             :  *         This contract should hold the staked funds which are received upon relayer registration,
      25             :  *         and properly attribute rewards to addresses without security issues.
      26             :  * @dev CONTRACT RISKS:
      27             :  *      - Relayer staked TORN at risk if contract is compromised.
      28             :  *
      29             :  */
      30             : contract TornadoStakingRewards is Initializable, EnsResolve {
      31             :     using SafeMath for uint256;
      32             :     using SafeERC20 for IERC20;
      33             : 
      34             :     /// @notice 1e25
      35             :     uint256 public immutable ratioConstant;
      36             :     ITornadoGovernance public immutable Governance;
      37             :     IERC20 public immutable torn;
      38             :     address public immutable relayerRegistry;
      39             : 
      40             :     /// @notice the sum torn_burned_i/locked_amount_i*coefficient where i is incremented at each burn
      41             :     uint256 public accumulatedRewardPerTorn;
      42             :     /// @notice notes down accumulatedRewardPerTorn for an address on a lock/unlock/claim
      43             :     mapping(address => uint256) public accumulatedRewardRateOnLastUpdate;
      44             :     /// @notice notes down how much an account may claim
      45             :     mapping(address => uint256) public accumulatedRewards;
      46             : 
      47             :     event RewardsUpdated(address indexed account, uint256 rewards);
      48             :     event RewardsClaimed(address indexed account, uint256 rewardsClaimed);
      49             : 
      50             :     modifier onlyGovernance() {
      51             :         require(msg.sender == address(Governance), "only governance");
      52             :         _;
      53             :     }
      54             : 
      55             :     // Minor code change here we won't resolve the registry by ENS
      56             :     constructor(address governanceAddress, address tornAddress, address _relayerRegistry) public {
      57             :         Governance = ITornadoGovernance(governanceAddress);
      58             :         torn = IERC20(tornAddress);
      59             :         relayerRegistry = _relayerRegistry;
      60             :         ratioConstant = IERC20(tornAddress).totalSupply();
      61             :     }
      62             : 
      63             :     /**
      64             :      * @notice This function should safely send a user his rewards.
      65             :      * @dev IMPORTANT FUNCTION:
      66             :      *      We know that rewards are going to be updated every time someone locks or unlocks
      67             :      *      so we know that this function can't be used to falsely increase the amount of
      68             :      *      lockedTorn by locking in governance and subsequently calling it.
      69             :      *      - set rewards to 0 greedily
      70             :      */
      71             :     function getReward() external {
      72           0 :         uint256 rewards = _updateReward(msg.sender, Governance.lockedBalance(msg.sender));
      73           0 :         rewards = rewards.add(accumulatedRewards[msg.sender]);
      74           0 :         accumulatedRewards[msg.sender] = 0;
      75           0 :         torn.safeTransfer(msg.sender, rewards);
      76           0 :         emit RewardsClaimed(msg.sender, rewards);
      77             :     }
      78             : 
      79             :     /**
      80             :      * @notice This function should increment the proper amount of rewards per torn for the contract
      81             :      * @dev IMPORTANT FUNCTION:
      82             :      *      - calculation must not overflow with extreme values
      83             :      *        (amount <= 1e25) * 1e25 / (balance of vault <= 1e25) -> (extreme values)
      84             :      * @param amount amount to add to the rewards
      85             :      */
      86             :     function addBurnRewards(uint256 amount) external {
      87           0 :         require(msg.sender == address(Governance) || msg.sender == relayerRegistry, "unauthorized");
      88           0 :         accumulatedRewardPerTorn = accumulatedRewardPerTorn.add(
      89             :             amount.mul(ratioConstant).div(torn.balanceOf(address(Governance.userVault())))
      90             :         );
      91             :     }
      92             : 
      93             :     /**
      94             :      * @notice This function should allow governance to properly update the accumulated rewards rate for an
      95             :      * account
      96             :      * @param account address of account to update data for
      97             :      * @param amountLockedBeforehand the balance locked beforehand in the governance contract
      98             :      *
      99             :      */
     100             :     function updateRewardsOnLockedBalanceChange(address account, uint256 amountLockedBeforehand)
     101             :         external
     102             :         onlyGovernance
     103             :     {
     104           0 :         uint256 claimed = _updateReward(account, amountLockedBeforehand);
     105           0 :         accumulatedRewards[account] = accumulatedRewards[account].add(claimed);
     106             :     }
     107             : 
     108             :     /**
     109             :      * @notice This function should allow governance rescue tokens from the staking rewards contract
     110             :      *
     111             :      */
     112             :     function withdrawTorn(uint256 amount) external onlyGovernance {
     113           0 :         if (amount == type(uint256).max) amount = torn.balanceOf(address(this));
     114           0 :         torn.safeTransfer(address(Governance), amount);
     115             :     }
     116             : 
     117             :     /**
     118             :      * @notice This function should calculated the proper amount of rewards attributed to user since the last
     119             :      * update
     120             :      * @dev IMPORTANT FUNCTION:
     121             :      *      - calculation must not overflow with extreme values
     122             :      *        (accumulatedReward <= 1e25) * (lockedBeforehand <= 1e25) / 1e25
     123             :      *      - result may go to 0, since this implies on 1 TORN locked => accumulatedReward <= 1e7, meaning a
     124             :      * very small reward
     125             :      * @param account address of account to calculate rewards for
     126             :      * @param amountLockedBeforehand the balance locked beforehand in the governance contract
     127             :      * @return claimed the rewards attributed to user since the last update
     128             :      */
     129             :     function _updateReward(address account, uint256 amountLockedBeforehand)
     130             :         private
     131             :         returns (uint256 claimed)
     132             :     {
     133           0 :         if (amountLockedBeforehand != 0) {
     134           0 :             claimed = (accumulatedRewardPerTorn.sub(accumulatedRewardRateOnLastUpdate[account])).mul(
     135             :                 amountLockedBeforehand
     136             :             ).div(ratioConstant);
     137             :         }
     138           0 :         accumulatedRewardRateOnLastUpdate[account] = accumulatedRewardPerTorn;
     139           0 :         emit RewardsUpdated(account, claimed);
     140             :     }
     141             : 
     142             :     /**
     143             :      * @notice This function should show a user his rewards.
     144             :      * @param account address of account to calculate rewards for
     145             :      */
     146             :     function checkReward(address account) external view returns (uint256 rewards) {
     147           0 :         uint256 amountLocked = Governance.lockedBalance(account);
     148           0 :         if (amountLocked != 0) {
     149           0 :             rewards = (accumulatedRewardPerTorn.sub(accumulatedRewardRateOnLastUpdate[account])).mul(
     150             :                 amountLocked
     151             :             ).div(ratioConstant);
     152             :         }
     153           0 :         rewards = rewards.add(accumulatedRewards[account]);
     154             :     }
     155             : }

Generated by: LCOV version 1.16