编译器
0.6.11+commit.5ef660b1
文件 1 的 6:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 2 的 6:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
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);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 3 的 6:IStaking.sol
pragma solidity ^0.6.0;
import "@openzeppelin/contracts/access/Ownable.sol";
interface IStaking {
function getEpochId(uint timestamp) external view returns (uint);
function getEpochUserBalance(address user, address token, uint128 epoch) external view returns(uint);
function getEpochPoolSize(address token, uint128 epoch) external view returns (uint);
function epoch1Start() external view returns (uint);
function epochDuration() external view returns (uint);
}
文件 4 的 6:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 5 的 6:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 6 的 6:YieldFarm.sol
pragma solidity ^0.6.11;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces/IStaking.sol";
contract YieldFarm {
using SafeMath for uint;
using SafeMath for uint128;
uint public immutable TOTAL_DISTRIBUTED_AMOUNT;
uint public immutable NR_OF_EPOCHS;
address private immutable _token;
address private immutable _communityVault;
IERC20 private immutable _push;
IStaking private _staking;
uint[] private epochs;
uint private immutable _genesisEpochAmount;
uint private _deprecationPerEpoch;
uint128 public lastInitializedEpoch;
mapping(address => uint128) public lastEpochIdHarvested;
uint public epochDuration;
uint public epochStart;
event MassHarvest(address indexed user, uint256 epochsHarvested, uint256 totalValue);
event Harvest(address indexed user, uint128 indexed epochId, uint256 amount);
constructor(address pushTokenAddress, address token, address stakeContract, address communityVault, uint genesisEpochAmount, uint deprecationPerEpoch, uint nrOfEpochs) public {
_push = IERC20(pushTokenAddress);
_token = token;
_staking = IStaking(stakeContract);
_communityVault = communityVault;
epochDuration = _staking.epochDuration();
epochStart = _staking.epoch1Start() + epochDuration;
uint n = nrOfEpochs;
uint difference = (n.mul(n.sub(1))).div(2);
TOTAL_DISTRIBUTED_AMOUNT = (genesisEpochAmount.mul(n)).sub(difference.mul(deprecationPerEpoch));
NR_OF_EPOCHS = nrOfEpochs;
epochs = new uint[](nrOfEpochs + 1);
_genesisEpochAmount = genesisEpochAmount;
_deprecationPerEpoch = deprecationPerEpoch;
}
function massHarvest() external returns (uint){
uint totalDistributedValue;
uint epochId = _getEpochId().sub(1);
uint lastEpochIdHarvestedUser = lastEpochIdHarvested[msg.sender];
if (epochId > NR_OF_EPOCHS) {
epochId = NR_OF_EPOCHS;
}
for (uint128 i = lastEpochIdHarvested[msg.sender] + 1; i <= epochId; i++) {
totalDistributedValue += _harvest(i);
}
emit MassHarvest(msg.sender, epochId - lastEpochIdHarvestedUser, totalDistributedValue);
if (totalDistributedValue > 0) {
_push.transferFrom(_communityVault, msg.sender, totalDistributedValue);
}
return totalDistributedValue;
}
function harvest (uint128 epochId) external returns (uint){
require (_getEpochId() > epochId, "This epoch is in the future");
require(epochId <= NR_OF_EPOCHS, "Maximum number of epochs exceeded");
require (lastEpochIdHarvested[msg.sender].add(1) == epochId, "Harvest in order");
uint userReward = _harvest(epochId);
if (userReward > 0) {
_push.transferFrom(_communityVault, msg.sender, userReward);
}
emit Harvest(msg.sender, epochId, userReward);
return userReward;
}
function getPoolSize(uint128 epochId) external view returns (uint) {
return _getPoolSize(epochId);
}
function getCurrentEpoch() external view returns (uint) {
return _getEpochId();
}
function getEpochStake(address userAddress, uint128 epochId) external view returns (uint) {
return _getUserBalancePerEpoch(userAddress, epochId);
}
function userLastEpochIdHarvested() external view returns (uint){
return lastEpochIdHarvested[msg.sender];
}
function _initEpoch(uint128 epochId) internal {
require(lastInitializedEpoch.add(1) == epochId, "Epoch can be init only in order");
lastInitializedEpoch = epochId;
epochs[epochId] = _getPoolSize(epochId);
}
function _harvest (uint128 epochId) internal returns (uint) {
if (lastInitializedEpoch < epochId) {
_initEpoch(epochId);
}
lastEpochIdHarvested[msg.sender] = epochId;
if (epochs[epochId] == 0) {
return 0;
}
return _calcTotalAmountPerEpoch(epochId)
.mul(_getUserBalancePerEpoch(msg.sender, epochId))
.div(epochs[epochId]);
}
function _calcTotalAmountPerEpoch(uint256 epochId) internal view returns (uint) {
return _genesisEpochAmount.sub(epochId.mul(_deprecationPerEpoch));
}
function _getPoolSize(uint128 epochId) internal view returns (uint) {
return _staking.getEpochPoolSize(_token, _stakingEpochId(epochId));
}
function _getUserBalancePerEpoch(address userAddress, uint128 epochId) internal view returns (uint){
return _staking.getEpochUserBalance(userAddress, _token, _stakingEpochId(epochId));
}
function _getEpochId() internal view returns (uint128 epochId) {
if (block.timestamp < epochStart) {
return 0;
}
epochId = uint128(block.timestamp.sub(epochStart).div(epochDuration).add(1));
}
function _stakingEpochId(uint128 epochId) pure internal returns (uint128) {
return epochId + 1;
}
}
{
"compilationTarget": {
"contracts/staking/YieldFarm.sol": "YieldFarm"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"pushTokenAddress","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"stakeContract","type":"address"},{"internalType":"address","name":"communityVault","type":"address"},{"internalType":"uint256","name":"genesisEpochAmount","type":"uint256"},{"internalType":"uint256","name":"deprecationPerEpoch","type":"uint256"},{"internalType":"uint256","name":"nrOfEpochs","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint128","name":"epochId","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Harvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"epochsHarvested","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalValue","type":"uint256"}],"name":"MassHarvest","type":"event"},{"inputs":[],"name":"NR_OF_EPOCHS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_DISTRIBUTED_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint128","name":"epochId","type":"uint128"}],"name":"getEpochStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"epochId","type":"uint128"}],"name":"getPoolSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"epochId","type":"uint128"}],"name":"harvest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastEpochIdHarvested","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastInitializedEpoch","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massHarvest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"userLastEpochIdHarvested","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]