Skip to content

Commit

Permalink
change minter to vault
Browse files Browse the repository at this point in the history
  • Loading branch information
ququzone committed Jan 19, 2024
1 parent 5f81863 commit 126245a
Show file tree
Hide file tree
Showing 26 changed files with 441 additions and 272 deletions.
2 changes: 1 addition & 1 deletion SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ All of these operations require ownership of the underlying NFT or tokens being
- Can unlock a permanently locked NFT to allow its voting power to decay.
- Can delegate votes to other `tokenId`s for use in marshall governance to other addresses based on voting power. Voting power retrieved from `getVotes` and `getPastVotes` does not reveal locked amount balances and are used only for voting.

### Minter
### Vault

The minting contract handles emissions for the Marshall DAO protocol. Emissions start fixed amount $IOTX per epoch (7 days). Liquidity providers and veIOTX holder will receive weekly emissions. The weekly emissions amount and the ratio of the LP and veIOTX can be adjust by DAO governor.

Expand Down
18 changes: 9 additions & 9 deletions contracts/RewardsDistributor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {IRewardsDistributor} from "./interfaces/IRewardsDistributor.sol";
import {IVotingEscrow} from "./interfaces/IVotingEscrow.sol";
import {IMinter} from "./interfaces/IMinter.sol";
import {IVault} from "./interfaces/IVault.sol";

/*
* @title Curve Fee Distribution modified for ve(3,3) emissions
Expand All @@ -28,7 +28,7 @@ contract RewardsDistributor is IRewardsDistributor {
/// @inheritdoc IRewardsDistributor
IVotingEscrow public immutable ve;
/// @inheritdoc IRewardsDistributor
address public minter;
address public vault;
/// @inheritdoc IRewardsDistributor
uint256 public tokenLastBalance;

Expand All @@ -37,7 +37,7 @@ contract RewardsDistributor is IRewardsDistributor {
startTime = _t;
lastTokenTime = _t;
ve = IVotingEscrow(_ve);
minter = msg.sender;
vault = msg.sender;
}

receive() external payable {}
Expand Down Expand Up @@ -78,7 +78,7 @@ contract RewardsDistributor is IRewardsDistributor {

/// @inheritdoc IRewardsDistributor
function checkpointToken() external {
if (msg.sender != minter) revert NotMinter();
if (msg.sender != vault) revert NotVault();
_checkpointToken();
}

Expand Down Expand Up @@ -131,7 +131,7 @@ contract RewardsDistributor is IRewardsDistributor {

/// @inheritdoc IRewardsDistributor
function claim(uint256 _tokenId) external returns (uint256) {
if (IMinter(minter).activePeriod() < ((block.timestamp / WEEK) * WEEK)) revert UpdatePeriod();
if (IVault(vault).activePeriod() < ((block.timestamp / WEEK) * WEEK)) revert UpdatePeriod();
uint256 _timestamp = block.timestamp;
uint256 _lastTokenTime = lastTokenTime;
_lastTokenTime = (_lastTokenTime / WEEK) * WEEK;
Expand All @@ -151,7 +151,7 @@ contract RewardsDistributor is IRewardsDistributor {

/// @inheritdoc IRewardsDistributor
function claimMany(uint256[] calldata _tokenIds) external returns (bool) {
if (IMinter(minter).activePeriod() < ((block.timestamp / WEEK) * WEEK)) revert UpdatePeriod();
if (IVault(vault).activePeriod() < ((block.timestamp / WEEK) * WEEK)) revert UpdatePeriod();
uint256 _timestamp = block.timestamp;
uint256 _lastTokenTime = lastTokenTime;
_lastTokenTime = (_lastTokenTime / WEEK) * WEEK;
Expand Down Expand Up @@ -181,8 +181,8 @@ contract RewardsDistributor is IRewardsDistributor {
}

/// @inheritdoc IRewardsDistributor
function setMinter(address _minter) external {
if (msg.sender != minter) revert NotMinter();
minter = _minter;
function setVault(address _vault) external {
if (msg.sender != vault) revert NotVault();
vault = _vault;
}
}
42 changes: 21 additions & 21 deletions contracts/Minter.sol → contracts/Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,35 @@
pragma solidity ^0.8.0;

import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {IMinter} from "./interfaces/IMinter.sol";
import {IVault} from "./interfaces/IVault.sol";
import {IRewardsDistributor} from "./interfaces/IRewardsDistributor.sol";
import {IVoter} from "./interfaces/IVoter.sol";
import {IVotingEscrow} from "./interfaces/IVotingEscrow.sol";

/// @title Minter
/// @title Vault
/// @author velodrome.finance, @figs999, @pegahcarter
/// @notice Controls minting of emissions and rebases for the Protocol
contract Minter is IMinter {
/// @inheritdoc IMinter
contract Vault is IVault {
/// @inheritdoc IVault
IVoter public immutable voter;
/// @inheritdoc IMinter
/// @inheritdoc IVault
IVotingEscrow public immutable ve;
/// @inheritdoc IMinter
/// @inheritdoc IVault
IRewardsDistributor public immutable rewardsDistributor;

/// @inheritdoc IMinter
/// @inheritdoc IVault
uint256 public constant WEEK = 1 weeks;
/// @inheritdoc IMinter
/// @inheritdoc IVault
uint256 public veRate = 1000; // 10%
/// @inheritdoc IMinter
/// @inheritdoc IVault
uint256 public weekly = 100_000 * 1e18;
/// @inheritdoc IMinter
/// @inheritdoc IVault
uint256 public activePeriod;
/// @inheritdoc IMinter
/// @inheritdoc IVault
uint256 public epochCount;
/// @inheritdoc IMinter
/// @inheritdoc IVault
address public team;
/// @inheritdoc IMinter
/// @inheritdoc IVault
address public pendingTeam;

constructor(
Expand All @@ -45,22 +45,22 @@ contract Minter is IMinter {
activePeriod = ((block.timestamp) / WEEK) * WEEK; // allow emissions this coming epoch
}

/// @inheritdoc IMinter
/// @inheritdoc IVault
function setTeam(address _team) external {
if (msg.sender != team) revert NotTeam();
if (_team == address(0)) revert ZeroAddress();
pendingTeam = _team;
}

/// @inheritdoc IMinter
/// @inheritdoc IVault
function acceptTeam() external {
if (msg.sender != pendingTeam) revert NotPendingTeam();
team = pendingTeam;
delete pendingTeam;
emit AcceptTeam(team);
}

/// @inheritdoc IMinter
/// @inheritdoc IVault
function updatePeriod() external returns (uint256 _period) {
_period = activePeriod;
if (block.timestamp >= _period + WEEK) {
Expand All @@ -80,19 +80,19 @@ contract Minter is IMinter {

voter.notifyRewardAmount{value: _emission - _veEmission}();

emit Mint(msg.sender, _emission);
emit Emission(msg.sender, _emission);
}
}

/// @inheritdoc IMinter
/// @inheritdoc IVault
function changeWeekly(uint256 _weekly) external {
if (msg.sender != team) revert NotTeam();

weekly = _weekly;
emit WeeklyChanged(_weekly);
}

/// @inheritdoc IMinter
/// @inheritdoc IVault
function changeVeRate(uint256 _rate) external {
if (msg.sender != team) revert NotTeam();
if (_rate > 5000) revert InvalidRate();
Expand All @@ -101,7 +101,7 @@ contract Minter is IMinter {
emit VeRateChanged(_rate);
}

/// @inheritdoc IMinter
/// @inheritdoc IVault
function withdraw(address payable _recipcient, uint256 _amount) external {
if (msg.sender != team) revert NotTeam();
_recipcient.transfer(_amount);
Expand All @@ -112,7 +112,7 @@ contract Minter is IMinter {
emit Donation(msg.sender, msg.value);
}

/// @inheritdoc IMinter
/// @inheritdoc IVault
function donate() external payable {
if (msg.value == 0) revert ZeroDonation();
emit Donation(msg.sender, msg.value);
Expand Down
24 changes: 12 additions & 12 deletions contracts/Voter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {IVotingRewardsFactory} from "./interfaces/factories/IVotingRewardsFactory.sol";
import {IGauge} from "./interfaces/IGauge.sol";
import {IGaugeFactory} from "./interfaces/factories/IGaugeFactory.sol";
import {IMinter} from "./interfaces/IMinter.sol";
import {IVault} from "./interfaces/IVault.sol";
import {IReward} from "./interfaces/IReward.sol";
import {IVoter} from "./interfaces/IVoter.sol";
import {IVotingEscrow} from "./interfaces/IVotingEscrow.sol";
Expand All @@ -28,7 +28,7 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
/// @notice Rewards are released over 7 days
uint256 internal constant DURATION = 7 days;
/// @inheritdoc IVoter
address public minter;
address public vault;
/// @inheritdoc IVoter
address public governor;
/// @inheritdoc IVoter
Expand Down Expand Up @@ -78,7 +78,7 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
ve = _ve;
factoryRegistry = _factoryRegistry;
address _sender = _msgSender();
minter = _sender;
vault = _sender;
governor = _sender;
emergencyCouncil = _sender;
maxVotingNum = 30;
Expand Down Expand Up @@ -108,13 +108,13 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
}

/// @dev requires initialization with at least rewardToken
function initialize(address[] calldata _tokens, address _minter) external {
if (_msgSender() != minter) revert NotMinter();
function initialize(address[] calldata _tokens, address _vault) external {
if (_msgSender() != vault) revert NotVault();
uint256 _length = _tokens.length;
for (uint256 i = 0; i < _length; i++) {
_whitelistToken(_tokens[i], true);
}
minter = _minter;
vault = _vault;
}

/// @inheritdoc IVoter
Expand Down Expand Up @@ -294,10 +294,10 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
function killGauge(address _gauge) external {
if (_msgSender() != emergencyCouncil) revert NotEmergencyCouncil();
if (!isAlive[_gauge]) revert GaugeAlreadyKilled();
// Return claimable back to minter
// Return claimable back to valut
uint256 _claimable = claimable[_gauge];
if (_claimable > 0) {
payable(minter).transfer(_claimable);
payable(vault).transfer(_claimable);
delete claimable[_gauge];
}
isAlive[_gauge] = false;
Expand All @@ -320,7 +320,7 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
/// @inheritdoc IVoter
function notifyRewardAmount() external payable {
address sender = _msgSender();
if (sender != minter) revert NotMinter();
if (sender != vault) revert NotVault();
uint256 _amount = msg.value;
uint256 _ratio = (_amount * 1e18) / Math.max(totalWeight, 1); // 1e18 adjustment is removed during claim
if (_ratio > 0) {
Expand Down Expand Up @@ -362,7 +362,7 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {
if (isAlive[_gauge]) {
claimable[_gauge] += _share;
} else {
payable(minter).transfer(_share); // send rewards back to Minter so they're not stuck in Voter
payable(vault).transfer(_share); // send rewards back to Vault so they're not stuck in Voter
}
}
} else {
Expand Down Expand Up @@ -399,15 +399,15 @@ contract Voter is IVoter, ERC2771Context, ReentrancyGuard {

/// @inheritdoc IVoter
function distribute(uint256 _start, uint256 _finish) external nonReentrant {
IMinter(minter).updatePeriod();
IVault(vault).updatePeriod();
for (uint256 x = _start; x < _finish; x++) {
_distribute(gauges[pools[x]]);
}
}

/// @inheritdoc IVoter
function distribute(address[] memory _gauges) external nonReentrant {
IMinter(minter).updatePeriod();
IVault(vault).updatePeriod();
uint256 _length = _gauges.length;
for (uint256 x = 0; x < _length; x++) {
_distribute(_gauges[x]);
Expand Down
18 changes: 9 additions & 9 deletions contracts/interfaces/IRewardsDistributor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface IRewardsDistributor {
event CheckpointToken(uint256 time, uint256 tokens);
event Claimed(uint256 indexed tokenId, uint256 indexed epochStart, uint256 indexed epochEnd, uint256 amount);

error NotMinter();
error NotVault();
error NotManagedOrNormalNFT();
error UpdatePeriod();

Expand All @@ -20,15 +20,15 @@ interface IRewardsDistributor {
/// @notice Timestamp of most recent claim of tokenId
function timeCursorOf(uint256 tokenId) external view returns (uint256);

/// @notice The last timestamp Minter has called checkpointToken()
/// @notice The last timestamp Vault has called checkpointToken()
function lastTokenTime() external view returns (uint256);

/// @notice Interface of VotingEscrow.sol
function ve() external view returns (IVotingEscrow);

/// @notice Address of Minter.sol
/// @notice Address of Vault.sol
/// Authorized caller of checkpointToken()
function minter() external view returns (address);
function vault() external view returns (address);

/// @notice Amount of token in contract when checkpointToken() was last called
function tokenLastBalance() external view returns (uint256);
Expand All @@ -44,18 +44,18 @@ interface IRewardsDistributor {

/// @notice Claims rebases for a given token ID
/// @dev Allows claiming of rebases up to 50 epochs old
/// `Minter.updatePeriod()` must be called before claiming
/// `Vault.updatePeriod()` must be called before claiming
/// @param tokenId The token ID to claim for
/// @return The amount of rebases claimed
function claim(uint256 tokenId) external returns (uint256);

/// @notice Claims rebases for a list of token IDs
/// @dev `Minter.updatePeriod()` must be called before claiming
/// @dev `Vault.updatePeriod()` must be called before claiming
/// @param tokenIds The token IDs to claim for
/// @return Whether or not the claim succeeded
function claimMany(uint256[] calldata tokenIds) external returns (bool);

/// @notice Used to set minter once on initialization
/// @dev Callable once by Minter only, Minter is immutable
function setMinter(address _minter) external;
/// @notice Used to set vault once on initialization
/// @dev Callable once by vault only, Vault is immutable
function setVault(address _vault) external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import {IVoter} from "./IVoter.sol";
import {IVotingEscrow} from "./IVotingEscrow.sol";
import {IRewardsDistributor} from "./IRewardsDistributor.sol";

interface IMinter {
interface IVault {
error NotTeam();
error ZeroAddress();
error ZeroDonation();
error InvalidRate();
error NotPendingTeam();
error InsufficientFund();

event Mint(address indexed sender, uint256 weekly);
event Emission(address indexed sender, uint256 weekly);
event AcceptTeam(address indexed _newTeam);
event WeeklyChanged(uint256 weekly);
event VeRateChanged(uint256 rate);
Expand Down
10 changes: 5 additions & 5 deletions contracts/interfaces/IVoter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface IVoter {
error NotApprovedOrOwner();
error NotGovernor();
error NotEmergencyCouncil();
error NotMinter();
error NotVault();
error NotWhitelistedNFT();
error NotWhitelistedToken();
error SameValue();
Expand Down Expand Up @@ -68,8 +68,8 @@ interface IVoter {
/// @notice Factory registry for valid gauge / rewards factories
function factoryRegistry() external view returns (address);

/// @notice Address of Minter.sol
function minter() external view returns (address);
/// @notice Address of Vault.sol
function vault() external view returns (address);

/// @notice Standard OZ IGovernor using ve for vote weights.
function governor() external view returns (address);
Expand Down Expand Up @@ -123,9 +123,9 @@ interface IVoter {
/// @notice Number of pools with a Gauge
function length() external view returns (uint256);

/// @notice Called by Minter to distribute weekly emissions rewards for disbursement amongst gauges.
/// @notice Called by Vault to distribute weekly emissions rewards for disbursement amongst gauges.
/// @dev Assumes totalWeight != 0 (Will never be zero as long as users are voting).
/// Throws if not called by minter.
/// Throws if not called by vault.
function notifyRewardAmount() external payable;

/// @dev Utility to distribute to gauges of pools in range _start to _finish.
Expand Down
Loading

0 comments on commit 126245a

Please sign in to comment.