forked from mstable/mStable-contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Meta & Ecosystem Rewards (mstable#90)
* Implemented MTA token * Implemented Rewards mechanisms * Tested suite
- Loading branch information
1 parent
d4180e0
commit 950abdd
Showing
37 changed files
with
4,703 additions
and
41 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 |
---|---|---|
|
@@ -54,6 +54,7 @@ package-lock.json | |
.coverage_artifacts/ | ||
.coverage_contracts/ | ||
coverage.json | ||
cache | ||
|
||
# sol-merger | ||
flat/ | ||
|
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
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
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
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
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
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,25 @@ | ||
pragma solidity 0.5.16; | ||
|
||
/** | ||
* @title IMetaToken | ||
* @dev Interface for MetaToken | ||
*/ | ||
interface IMetaToken { | ||
/** @dev Basic ERC20 funcs */ | ||
function name() external view returns (string memory); | ||
function symbol() external view returns (string memory); | ||
function decimals() external view returns (uint8); | ||
function totalSupply() external view returns (uint256); | ||
function balanceOf(address account) external view returns (uint256); | ||
function transfer(address recipient, uint256 amount) external returns (bool); | ||
function allowance(address owner, address spender) external view returns (uint256); | ||
function approve(address spender, uint256 amount) external returns (bool); | ||
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | ||
|
||
/** @dev Burnable */ | ||
function burn(uint256 amount) external; | ||
function burnFrom(address account, uint256 amount) external; | ||
|
||
/** @dev Mintable */ | ||
function mint(address account, uint256 amount) external returns (bool); | ||
} |
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,8 @@ | ||
pragma solidity 0.5.16; | ||
|
||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
|
||
interface IRewardsDistributionRecipient { | ||
function notifyRewardAmount(uint256 reward) external; | ||
function getRewardToken() external view returns (IERC20); | ||
} |
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,56 @@ | ||
pragma solidity 0.5.16; | ||
|
||
import { Module } from "../shared/Module.sol"; | ||
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
import { Roles } from "@openzeppelin/contracts/access/Roles.sol"; | ||
|
||
/** | ||
* @title GovernedMinterRole | ||
* @author OpenZeppelin (forked from @openzeppelin/contracts/access/roles/MinterRole.sol) | ||
* @dev Forked from OpenZeppelin 'MinterRole' with changes: | ||
* - `addMinter` modified from `onlyMinter` to `onlyGovernor` | ||
* - `removeMinter` function added, callable by `onlyGovernor` | ||
*/ | ||
contract GovernedMinterRole is Module { | ||
|
||
using Roles for Roles.Role; | ||
|
||
event MinterAdded(address indexed account); | ||
event MinterRemoved(address indexed account); | ||
|
||
Roles.Role private _minters; | ||
|
||
constructor(address _nexus) internal Module(_nexus) { | ||
} | ||
|
||
modifier onlyMinter() { | ||
require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role"); | ||
_; | ||
} | ||
|
||
function isMinter(address account) public view returns (bool) { | ||
return _minters.has(account); | ||
} | ||
|
||
function addMinter(address account) public onlyGovernor { | ||
_addMinter(account); | ||
} | ||
|
||
function removeMinter(address account) public onlyGovernor { | ||
_removeMinter(account); | ||
} | ||
|
||
function renounceMinter() public { | ||
_removeMinter(msg.sender); | ||
} | ||
|
||
function _addMinter(address account) internal { | ||
_minters.add(account); | ||
emit MinterAdded(account); | ||
} | ||
|
||
function _removeMinter(address account) internal { | ||
_minters.remove(account); | ||
emit MinterRemoved(account); | ||
} | ||
} |
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,53 @@ | ||
pragma solidity 0.5.16; | ||
|
||
import { GovernedMinterRole } from "./GovernedMinterRole.sol"; | ||
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
import { ERC20Detailed } from "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol"; | ||
import { ERC20Burnable } from "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol"; | ||
|
||
/** | ||
* @title MetaToken | ||
* @author Stability Labs Pty. Ltd. | ||
* @dev MetaToken is an ERC20 token, with mint privileges governed by mStable | ||
* governors | ||
*/ | ||
contract MetaToken is | ||
ERC20, | ||
GovernedMinterRole, | ||
ERC20Detailed, | ||
ERC20Burnable | ||
{ | ||
|
||
/** | ||
* @dev MetaToken simply implements a detailed ERC20 token, | ||
* and a governed list of minters | ||
*/ | ||
constructor( | ||
address _nexus, | ||
address _initialRecipient | ||
) | ||
public | ||
GovernedMinterRole(_nexus) | ||
ERC20Detailed( | ||
"Meta", | ||
"MTA", | ||
18 | ||
) | ||
{ | ||
// 100m initial supply | ||
_mint(_initialRecipient, 100000000 * (10 ** 18)); | ||
} | ||
|
||
// Forked from @openzeppelin | ||
/** | ||
* @dev See {ERC20-_mint}. | ||
* | ||
* Requirements: | ||
* | ||
* - the caller must have the {MinterRole}. | ||
*/ | ||
function mint(address account, uint256 amount) public onlyMinter returns (bool) { | ||
_mint(account, amount); | ||
return true; | ||
} | ||
} |
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,28 @@ | ||
|
||
|
||
## Files | ||
|
||
Why so many? | ||
|
||
Actually only 3 are base contracts | ||
|
||
### RewardsDistributor | ||
|
||
Allows reward allocators ("FundManagers") to distribute rewards. | ||
|
||
### StakingRewards | ||
|
||
`StakingRewards` is `RewardsDistributionRecipient` | ||
--------------> is `StakingTokenWrapper` | ||
|
||
This preserves the code written, tested, audited and deployed by `Synthetix` (StakingRewards & StakingTokenWrapper). | ||
|
||
Originally: Synthetix (forked from /Synthetixio/synthetix/contracts/StakingRewards.sol) | ||
Audit: https://github.com/sigp/public-audits/blob/master/synthetix/unipool/review.pdf` | ||
|
||
### StakingRewardsWithPlatformToken | ||
|
||
`StakingRewardsWithPlatformToken` is `RewardsDistributionRecipient` | ||
-------------------------------> is `StakingTokenWrapper` | ||
|
||
`StakingRewardsWithPlatformToken` deploys `PlatformTokenVendor` during its constructor |
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,49 @@ | ||
pragma solidity 0.5.16; | ||
|
||
import { Module } from "../shared/Module.sol"; | ||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import { IRewardsDistributionRecipient } from "../interfaces/IRewardsDistributionRecipient.sol"; | ||
|
||
/** | ||
* @title RewardsDistributionRecipient | ||
* @author Originally: Synthetix (forked from /Synthetixio/synthetix/contracts/RewardsDistributionRecipient.sol) | ||
* Changes by: Stability Labs Pty. Ltd. | ||
* @notice RewardsDistributionRecipient gets notified of additional rewards by the rewardsDistributor | ||
* @dev Changes: Addition of Module and abstract `getRewardToken` func + cosmetic | ||
*/ | ||
contract RewardsDistributionRecipient is IRewardsDistributionRecipient, Module { | ||
|
||
// @abstract | ||
function notifyRewardAmount(uint256 reward) external; | ||
function getRewardToken() external view returns (IERC20); | ||
|
||
// This address has the ability to distribute the rewards | ||
address public rewardsDistributor; | ||
|
||
/** @dev Recipient is a module, governed by mStable governance */ | ||
constructor(address _nexus, address _rewardsDistributor) | ||
internal | ||
Module(_nexus) | ||
{ | ||
rewardsDistributor = _rewardsDistributor; | ||
} | ||
|
||
/** | ||
* @dev Only the rewards distributor can notify about rewards | ||
*/ | ||
modifier onlyRewardsDistributor() { | ||
require(msg.sender == rewardsDistributor, "Caller is not reward distributor"); | ||
_; | ||
} | ||
|
||
/** | ||
* @dev Change the rewardsDistributor - only called by mStable governor | ||
* @param _rewardsDistributor Address of the new distributor | ||
*/ | ||
function setRewardsDistribution(address _rewardsDistributor) | ||
external | ||
onlyGovernor | ||
{ | ||
rewardsDistributor = _rewardsDistributor; | ||
} | ||
} |
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,87 @@ | ||
pragma solidity 0.5.16; | ||
|
||
import { IRewardsDistributionRecipient } from "../interfaces/IRewardsDistributionRecipient.sol"; | ||
|
||
import { InitializableGovernableWhitelist } from "../governance/InitializableGovernableWhitelist.sol"; | ||
import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; | ||
|
||
/** | ||
* @title RewardsDistributor | ||
* @author Stability Labs Pty. Ltd. | ||
* @notice RewardsDistributor allows Fund Managers to send rewards (usually in MTA) | ||
* to specified Reward Recipients. | ||
*/ | ||
contract RewardsDistributor is InitializableGovernableWhitelist { | ||
|
||
using SafeERC20 for IERC20; | ||
|
||
event RemovedFundManager(address indexed _address); | ||
event DistributedReward(address funder, address recipient, address rewardToken, uint256 amount); | ||
|
||
/** @dev Recipient is a module, governed by mStable governance */ | ||
constructor( | ||
address _nexus, | ||
address[] memory _fundManagers | ||
) | ||
public | ||
{ | ||
InitializableGovernableWhitelist._initialize(_nexus, _fundManagers); | ||
} | ||
|
||
/** | ||
* @dev Allows the mStable governance to add a new FundManager | ||
* @param _address FundManager to add | ||
*/ | ||
function addFundManager(address _address) | ||
external | ||
onlyGovernor | ||
{ | ||
_addWhitelist(_address); | ||
} | ||
|
||
/** | ||
* @dev Allows the mStable governance to remove inactive FundManagers | ||
* @param _address FundManager to remove | ||
*/ | ||
function removeFundManager(address _address) | ||
external | ||
onlyGovernor | ||
{ | ||
require(_address != address(0), "Address is zero"); | ||
require(whitelist[_address], "Address is not whitelisted"); | ||
|
||
whitelist[_address] = false; | ||
|
||
emit RemovedFundManager(_address); | ||
} | ||
|
||
/** | ||
* @dev Distributes reward tokens to list of recipients and notifies them | ||
* of the transfer. Only callable by FundManagers | ||
* @param _recipients Array of Reward recipients to credit | ||
* @param _amounts Amounts of reward tokens to distribute | ||
*/ | ||
function distributeRewards( | ||
IRewardsDistributionRecipient[] calldata _recipients, | ||
uint256[] calldata _amounts | ||
) | ||
external | ||
onlyWhitelisted | ||
{ | ||
uint256 len = _recipients.length; | ||
require(len > 0, "Must choose recipients"); | ||
require(len == _amounts.length, "Mismatching inputs"); | ||
|
||
for(uint i = 0; i < len; i++){ | ||
uint256 amount = _amounts[i]; | ||
IRewardsDistributionRecipient recipient = _recipients[i]; | ||
// Send the RewardToken to recipient | ||
IERC20 rewardToken = recipient.getRewardToken(); | ||
rewardToken.safeTransferFrom(msg.sender, address(recipient), amount); | ||
// Only after successfull tx - notify the contract of the new funds | ||
recipient.notifyRewardAmount(amount); | ||
|
||
emit DistributedReward(msg.sender, address(recipient), address(rewardToken), amount); | ||
} | ||
} | ||
} |
Oops, something went wrong.