-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
30 changed files
with
5,510 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; | ||
import {IMinter} from "./interfaces/IMinter.sol"; | ||
import {IRewardsDistributor} from "./interfaces/IRewardsDistributor.sol"; | ||
import {IVoter} from "./interfaces/IVoter.sol"; | ||
import {IVotingEscrow} from "./interfaces/IVotingEscrow.sol"; | ||
|
||
/// @title Minter | ||
/// @author velodrome.finance, @figs999, @pegahcarter | ||
/// @notice Controls minting of emissions and rebases for the Protocol | ||
contract Minter is IMinter { | ||
/// @inheritdoc IMinter | ||
IVoter public immutable voter; | ||
/// @inheritdoc IMinter | ||
IVotingEscrow public immutable ve; | ||
/// @inheritdoc IMinter | ||
IRewardsDistributor public immutable rewardsDistributor; | ||
|
||
/// @inheritdoc IMinter | ||
uint256 public constant WEEK = 1 weeks; | ||
/// @inheritdoc IMinter | ||
uint256 public veRate = 1000; // 10% | ||
/// @inheritdoc IMinter | ||
uint256 public weekly = 100_000 * 1e18; | ||
/// @inheritdoc IMinter | ||
uint256 public activePeriod; | ||
/// @inheritdoc IMinter | ||
uint256 public epochCount; | ||
/// @inheritdoc IMinter | ||
address public team; | ||
/// @inheritdoc IMinter | ||
address public pendingTeam; | ||
|
||
constructor( | ||
address _voter, // the voting & distribution system | ||
address _ve, // the ve(3,3) system that will be locked into | ||
address _rewardsDistributor // the distribution system that ensures users aren't diluted | ||
) { | ||
voter = IVoter(_voter); | ||
ve = IVotingEscrow(_ve); | ||
team = msg.sender; | ||
rewardsDistributor = IRewardsDistributor(_rewardsDistributor); | ||
activePeriod = ((block.timestamp) / WEEK) * WEEK; // allow emissions this coming epoch | ||
} | ||
|
||
/// @inheritdoc IMinter | ||
function setTeam(address _team) external { | ||
if (msg.sender != team) revert NotTeam(); | ||
if (_team == address(0)) revert ZeroAddress(); | ||
pendingTeam = _team; | ||
} | ||
|
||
/// @inheritdoc IMinter | ||
function acceptTeam() external { | ||
if (msg.sender != pendingTeam) revert NotPendingTeam(); | ||
team = pendingTeam; | ||
delete pendingTeam; | ||
emit AcceptTeam(team); | ||
} | ||
|
||
/// @inheritdoc IMinter | ||
function updatePeriod() external returns (uint256 _period) { | ||
_period = activePeriod; | ||
if (block.timestamp >= _period + WEEK) { | ||
epochCount++; | ||
_period = (block.timestamp / WEEK) * WEEK; | ||
activePeriod = _period; | ||
uint256 _emission = weekly; | ||
|
||
uint256 _balanceOf = address(this).balance; | ||
if (_balanceOf < _emission) { | ||
revert InsufficientFund(); | ||
} | ||
uint256 _veEmission = (_emission * veRate) / 10000; | ||
|
||
payable(address(rewardsDistributor)).transfer(_veEmission); | ||
rewardsDistributor.checkpointToken(); // checkpoint token balance that was just minted in rewards distributor | ||
|
||
voter.notifyRewardAmount{value: _emission - _veEmission}(); | ||
|
||
emit Mint(msg.sender, _emission); | ||
} | ||
} | ||
|
||
/// @inheritdoc IMinter | ||
function changeWeekly(uint256 _weekly) external { | ||
if (msg.sender != team) revert NotTeam(); | ||
|
||
weekly = _weekly; | ||
emit WeeklyChanged(_weekly); | ||
} | ||
|
||
/// @inheritdoc IMinter | ||
function changeVeRate(uint256 _rate) external { | ||
if (msg.sender != team) revert NotTeam(); | ||
if (_rate > 5000) revert InvalidRate(); | ||
|
||
veRate = _rate; | ||
emit VeRateChanged(_rate); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
interface IGauge { | ||
error NotAlive(); | ||
error NotAuthorized(); | ||
error NotVoter(); | ||
error NotTeam(); | ||
error RewardRateTooHigh(); | ||
error ZeroAmount(); | ||
error ZeroRewardRate(); | ||
|
||
event Deposit(address indexed from, address indexed to, uint256 amount); | ||
event Withdraw(address indexed from, uint256 amount); | ||
event NotifyReward(address indexed from, uint256 amount); | ||
event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1); | ||
event ClaimRewards(address indexed from, uint256 amount); | ||
|
||
/// @notice Address of the pool LP token which is deposited (staked) for rewards | ||
function stakingToken() external view returns (address); | ||
|
||
/// @notice Address of the token (AERO) rewarded to stakers | ||
function rewardToken() external view returns (address); | ||
|
||
/// @notice Address of the FeesVotingReward contract linked to the gauge | ||
function feesVotingReward() external view returns (address); | ||
|
||
/// @notice Address of Protocol Voter | ||
function voter() external view returns (address); | ||
|
||
/// @notice Address of Protocol Voting Escrow | ||
function ve() external view returns (address); | ||
|
||
/// @notice Returns if gauge is linked to a legitimate Protocol pool | ||
function isPool() external view returns (bool); | ||
|
||
/// @notice Timestamp end of current rewards period | ||
function periodFinish() external view returns (uint256); | ||
|
||
/// @notice Current reward rate of rewardToken to distribute per second | ||
function rewardRate() external view returns (uint256); | ||
|
||
/// @notice Most recent timestamp contract has updated state | ||
function lastUpdateTime() external view returns (uint256); | ||
|
||
/// @notice Most recent stored value of rewardPerToken | ||
function rewardPerTokenStored() external view returns (uint256); | ||
|
||
/// @notice Amount of stakingToken deposited for rewards | ||
function totalSupply() external view returns (uint256); | ||
|
||
/// @notice Get the amount of stakingToken deposited by an account | ||
function balanceOf(address) external view returns (uint256); | ||
|
||
/// @notice Cached rewardPerTokenStored for an account based on their most recent action | ||
function userRewardPerTokenPaid(address) external view returns (uint256); | ||
|
||
/// @notice Cached amount of rewardToken earned for an account | ||
function rewards(address) external view returns (uint256); | ||
|
||
/// @notice View to see the rewardRate given the timestamp of the start of the epoch | ||
function rewardRateByEpoch(uint256) external view returns (uint256); | ||
|
||
/// @notice Cached amount of fees generated from the Pool linked to the Gauge of token0 | ||
function fees0() external view returns (uint256); | ||
|
||
/// @notice Cached amount of fees generated from the Pool linked to the Gauge of token1 | ||
function fees1() external view returns (uint256); | ||
|
||
/// @notice Get the current reward rate per unit of stakingToken deposited | ||
function rewardPerToken() external view returns (uint256 _rewardPerToken); | ||
|
||
/// @notice Returns the last time the reward was modified or periodFinish if the reward has ended | ||
function lastTimeRewardApplicable() external view returns (uint256 _time); | ||
|
||
/// @notice Returns accrued balance to date from last claim / first deposit. | ||
function earned(address _account) external view returns (uint256 _earned); | ||
|
||
/// @notice Total amount of rewardToken to distribute for the current rewards period | ||
function left() external view returns (uint256 _left); | ||
|
||
/// @notice Retrieve rewards for an address. | ||
/// @dev Throws if not called by same address or voter. | ||
/// @param _account . | ||
function getReward(address _account) external; | ||
|
||
/// @notice Deposit LP tokens into gauge for msg.sender | ||
/// @param _amount . | ||
function deposit(uint256 _amount) external; | ||
|
||
/// @notice Deposit LP tokens into gauge for any user | ||
/// @param _amount . | ||
/// @param _recipient Recipient to give balance to | ||
function deposit(uint256 _amount, address _recipient) external; | ||
|
||
/// @notice Withdraw LP tokens for user | ||
/// @param _amount . | ||
function withdraw(uint256 _amount) external; | ||
|
||
/// @dev Notifies gauge of gauge rewards. Assumes gauge reward tokens is 18 decimals. | ||
/// If not 18 decimals, rewardRate may have rounding issues. | ||
function notifyRewardAmount(uint256 amount) external; | ||
|
||
/// @dev Notifies gauge of gauge rewards without distributing its fees. | ||
/// Assumes gauge reward tokens is 18 decimals. | ||
/// If not 18 decimals, rewardRate may have rounding issues. | ||
function notifyRewardWithoutClaim(uint256 amount) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {IVoter} from "./IVoter.sol"; | ||
import {IVotingEscrow} from "./IVotingEscrow.sol"; | ||
import {IRewardsDistributor} from "./IRewardsDistributor.sol"; | ||
|
||
interface IMinter { | ||
error NotTeam(); | ||
error ZeroAddress(); | ||
error InvalidRate(); | ||
error NotPendingTeam(); | ||
error InsufficientFund(); | ||
|
||
event Mint(address indexed _sender, uint256 _weekly); | ||
event AcceptTeam(address indexed _newTeam); | ||
event WeeklyChanged(uint256 weekly); | ||
event VeRateChanged(uint256 rate); | ||
|
||
/// @notice Interface of Voter.sol | ||
function voter() external view returns (IVoter); | ||
|
||
/// @notice Interface of IVotingEscrow.sol | ||
function ve() external view returns (IVotingEscrow); | ||
|
||
/// @notice Interface of RewardsDistributor.sol | ||
function rewardsDistributor() external view returns (IRewardsDistributor); | ||
|
||
/// @notice Duration of epoch in seconds | ||
function WEEK() external view returns (uint256); | ||
|
||
/// @notice Weekly emission of IOTX | ||
function weekly() external view returns (uint256); | ||
|
||
/// @notice VotingEscrow holder rate | ||
function veRate() external view returns (uint256); | ||
|
||
/// @notice Timestamp of start of epoch that updatePeriod was last called in | ||
function activePeriod() external view returns (uint256); | ||
|
||
/// @notice Number of epochs in which updatePeriod was called | ||
function epochCount() external view returns (uint256); | ||
|
||
/// @notice Current team address in charge of emissions | ||
function team() external view returns (address); | ||
|
||
/// @notice Possible team address pending approval of current team | ||
function pendingTeam() external view returns (address); | ||
|
||
/// @notice Creates a request to change the current team's address | ||
/// @param _team Address of the new team to be chosen | ||
function setTeam(address _team) external; | ||
|
||
/// @notice Accepts the request to replace the current team's address | ||
/// with the requested one, present on variable pendingTeam | ||
function acceptTeam() external; | ||
|
||
/// @notice Processes emissions and rebases. Callable once per epoch (1 week). | ||
/// @return _period Start of current epoch. | ||
function updatePeriod() external returns (uint256 _period); | ||
|
||
/// @notice Change weekly emission. | ||
function changeWeekly(uint256 _weekly) external; | ||
|
||
/// @notice Change ve rate of emission. | ||
function changeVeRate(uint256 _rate) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
interface IReward { | ||
error InvalidReward(); | ||
error NotAuthorized(); | ||
error NotGauge(); | ||
error NotEscrowToken(); | ||
error NotSingleToken(); | ||
error NotVotingEscrow(); | ||
error NotWhitelisted(); | ||
error ZeroAmount(); | ||
|
||
event Deposit(address indexed from, uint256 indexed tokenId, uint256 amount); | ||
event Withdraw(address indexed from, uint256 indexed tokenId, uint256 amount); | ||
event NotifyReward(address indexed from, address indexed reward, uint256 indexed epoch, uint256 amount); | ||
event ClaimRewards(address indexed from, address indexed reward, uint256 amount); | ||
|
||
/// @notice A checkpoint for marking balance | ||
struct Checkpoint { | ||
uint256 timestamp; | ||
uint256 balanceOf; | ||
} | ||
|
||
/// @notice A checkpoint for marking supply | ||
struct SupplyCheckpoint { | ||
uint256 timestamp; | ||
uint256 supply; | ||
} | ||
|
||
/// @notice Epoch duration constant (7 days) | ||
function DURATION() external view returns (uint256); | ||
|
||
/// @notice Address of Voter.sol | ||
function voter() external view returns (address); | ||
|
||
/// @notice Address of VotingEscrow.sol | ||
function ve() external view returns (address); | ||
|
||
/// @dev Address which has permission to externally call _deposit() & _withdraw() | ||
function authorized() external view returns (address); | ||
|
||
/// @notice Total amount currently deposited via _deposit() | ||
function totalSupply() external view returns (uint256); | ||
|
||
/// @notice Current amount deposited by tokenId | ||
function balanceOf(uint256 tokenId) external view returns (uint256); | ||
|
||
/// @notice Amount of tokens to reward depositors for a given epoch | ||
/// @param token Address of token to reward | ||
/// @param epochStart Startime of rewards epoch | ||
/// @return Amount of token | ||
function tokenRewardsPerEpoch(address token, uint256 epochStart) external view returns (uint256); | ||
|
||
/// @notice Most recent timestamp a veNFT has claimed their rewards | ||
/// @param token Address of token rewarded | ||
/// @param tokenId veNFT unique identifier | ||
/// @return Timestamp | ||
function lastEarn(address token, uint256 tokenId) external view returns (uint256); | ||
|
||
/// @notice True if a token is or has been an active reward token, else false | ||
function isReward(address token) external view returns (bool); | ||
|
||
/// @notice The number of checkpoints for each tokenId deposited | ||
function numCheckpoints(uint256 tokenId) external view returns (uint256); | ||
|
||
/// @notice The total number of checkpoints | ||
function supplyNumCheckpoints() external view returns (uint256); | ||
|
||
/// @notice Deposit an amount into the rewards contract to earn future rewards associated to a veNFT | ||
/// @dev Internal notation used as only callable internally by `authorized`. | ||
/// @param amount Amount deposited for the veNFT | ||
/// @param tokenId Unique identifier of the veNFT | ||
function _deposit(uint256 amount, uint256 tokenId) external; | ||
|
||
/// @notice Withdraw an amount from the rewards contract associated to a veNFT | ||
/// @dev Internal notation used as only callable internally by `authorized`. | ||
/// @param amount Amount deposited for the veNFT | ||
/// @param tokenId Unique identifier of the veNFT | ||
function _withdraw(uint256 amount, uint256 tokenId) external; | ||
|
||
/// @notice Claim the rewards earned by a veNFT staker | ||
/// @param tokenId Unique identifier of the veNFT | ||
/// @param tokens Array of tokens to claim rewards of | ||
function getReward(uint256 tokenId, address[] memory tokens) external; | ||
|
||
/// @notice Add rewards for stakers to earn | ||
/// @param token Address of token to reward | ||
/// @param amount Amount of token to transfer to rewards | ||
function notifyRewardAmount(address token, uint256 amount) external; | ||
|
||
/// @notice Determine the prior balance for an account as of a block number | ||
/// @dev Block number must be a finalized block or else this function will revert to prevent misinformation. | ||
/// @param tokenId The token of the NFT to check | ||
/// @param timestamp The timestamp to get the balance at | ||
/// @return The balance the account had as of the given block | ||
function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp) external view returns (uint256); | ||
|
||
/// @notice Determine the prior index of supply staked by of a timestamp | ||
/// @dev Timestamp must be <= current timestamp | ||
/// @param timestamp The timestamp to get the index at | ||
/// @return Index of supply checkpoint | ||
function getPriorSupplyIndex(uint256 timestamp) external view returns (uint256); | ||
|
||
/// @notice Get number of rewards tokens | ||
function rewardsListLength() external view returns (uint256); | ||
|
||
/// @notice Calculate how much in rewards are earned for a specific token and veNFT | ||
/// @param token Address of token to fetch rewards of | ||
/// @param tokenId Unique identifier of the veNFT | ||
/// @return Amount of token earned in rewards | ||
function earned(address token, uint256 tokenId) external view returns (uint256); | ||
} |
Oops, something went wrong.