文件 1 的 16:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 16: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;
}
}
文件 3 的 16:ERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "../../GSN/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
constructor (string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
_decimals = 18;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _setupDecimals(uint8 decimals_) internal {
_decimals = decimals_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
文件 4 的 16: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);
}
文件 5 的 16:Initializable.sol
pragma solidity >=0.4.24 <0.7.0;
contract Initializable {
bool private initialized;
bool private initializing;
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
function isConstructor() private view returns (bool) {
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
uint256[50] private ______gap;
}
文件 6 的 16:LinkTokenInterface.sol
pragma solidity ^0.6.0;
interface LinkTokenInterface {
function allowance(address owner, address spender) external view returns (uint256 remaining);
function approve(address spender, uint256 value) external returns (bool success);
function balanceOf(address owner) external view returns (uint256 balance);
function decimals() external view returns (uint8 decimalPlaces);
function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
function increaseApproval(address spender, uint256 subtractedValue) external;
function name() external view returns (string memory tokenName);
function symbol() external view returns (string memory tokenSymbol);
function totalSupply() external view returns (uint256 totalTokensIssued);
function transfer(address to, uint256 value) external returns (bool success);
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
function transferFrom(address from, address to, uint256 value) external returns (bool success);
}
文件 7 的 16:Math.sol
pragma solidity >=0.6.0 <0.8.0;
library Math {
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
}
文件 8 的 16:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../GSN/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 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;
}
}
文件 9 的 16:RandomNumberConsumer.sol
pragma solidity >=0.6.6;
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
contract RandomNumberConsumer is VRFConsumerBase {
bytes32 internal keyHash;
uint256 public fee;
address public VRFCoordinator;
address public multiSigSafe;
address public randomizedCounter;
uint256 public randomResult;
constructor(
address VRFCoordinator_,
bytes32 keyhash_,
address LINK,
address multiSigSafe_,
address randomizedCounter_,
uint256 fee_
)
public
VRFConsumerBase(
VRFCoordinator_,
LINK
)
{
VRFCoordinator = VRFCoordinator_;
keyHash = keyhash_;
fee = fee_;
multiSigSafe = multiSigSafe_;
randomizedCounter = randomizedCounter_;
}
function setFee(uint256 fee_) external {
require(
msg.sender == randomizedCounter,
"Only counter can call this function"
);
fee = fee_;
}
function getRandomNumber(uint256 userProvidedSeed)
public
returns (bytes32 requestId)
{
require(
msg.sender == randomizedCounter,
"Only counter can call this function"
);
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK");
return requestRandomness(keyHash, fee, userProvidedSeed);
}
function fulfillRandomness(bytes32 requestId, uint256 randomness)
internal
override
{
randomResult = randomness;
}
function withdrawLink() external {
require(
msg.sender == multiSigSafe,
"Only multi sig safe can withdraw link"
);
require(
LINK.transfer(msg.sender, LINK.balanceOf(address(this))),
"Unable to transfer"
);
}
}
文件 10 的 16:RandomizedCounter.sol
pragma solidity >=0.6.6;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./RandomNumberConsumer.sol";
contract LPTokenWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public y;
function setStakeToken(address _y) internal {
y = IERC20(_y);
}
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
y.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
y.safeTransfer(msg.sender, amount);
}
}
contract RandomizedCounter is Ownable, Initializable, LPTokenWrapper {
using Address for address;
event LogEmergencyWithdraw(uint256 timestamp);
event LogSetCountThreshold(uint256 countThreshold_);
event LogSetBeforePeriodFinish(bool beforePeriodFinish_);
event LogSetCountInSequence(bool countInSequence_);
event LogSetRewardPercentage(uint256 rewardPercentage_);
event LogSetRevokeReward(bool revokeReward_);
event LogSetRevokeRewardPrecentage(uint256 revokeRewardPrecentage_);
event LogSetNormalDistribution(
uint256 noramlDistributionMean_,
uint256 normalDistributionDeviation_,
uint256[100] normalDistribution_
);
event LogCountThreshold(uint256 count_, uint256 index, uint256 threshold_);
event LogSetRandomNumberConsumer(
RandomNumberConsumer randomNumberConsumer_
);
event LogSetDuration(uint256 duration_);
event LogSetPoolEnabled(bool poolEnabled_);
event LogSetRandomNumberConsumerFee(uint256 fee_);
event LogSetEnableUserLpLimit(bool enableUserLpLimit_);
event LogSetEnablePoolLpLimit(bool enablePoolLpLimit_);
event LogSetUserLpLimit(uint256 userLpLimit_);
event LogSetPoolLpLimit(uint256 poolLpLimit_);
event LogCountThresholdHit(
uint256 rewardAmount_,
uint256 count_,
uint256 randomThreshold
);
event LogRewardAdded(uint256 reward);
event LogRewardRevoked(uint256 precentageRevoked, uint256 amountRevoked);
event LogStaked(address indexed user, uint256 amount);
event LogWithdrawn(address indexed user, uint256 amount);
event LogRewardPaid(address indexed user, uint256 reward);
event LogManualPoolStarted(uint256 startedAt);
IERC20 public rewardToken;
address public policy;
uint256 public duration;
bool public poolEnabled;
uint256 public periodFinish;
uint256 public rewardRate;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
uint256 public rewardPercentage;
uint256 public rewardDistributed;
bool public enableUserLpLimit;
uint256 public userLpLimit;
bool public enablePoolLpLimit;
uint256 public poolLpLimit;
uint256 public revokeRewardPrecentage;
bool public revokeReward;
uint256 public count;
bool public countInSequence;
RandomNumberConsumer public randomNumberConsumer;
IERC20 public link;
bool public beforePeriodFinish;
uint256 public noramlDistributionMean;
uint256 public normalDistributionDeviation;
uint256[100] public normalDistribution;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
modifier enabled() {
require(poolEnabled, "Pool isn't enabled");
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function setRewardPercentage(uint256 rewardPercentage_) external onlyOwner {
rewardPercentage = rewardPercentage_;
emit LogSetRewardPercentage(rewardPercentage);
}
function setCountInSequence(bool countInSequence_) external onlyOwner {
countInSequence = countInSequence_;
count = 0;
emit LogSetCountInSequence(!countInSequence);
}
function setRevokeReward(bool revokeReward_) external onlyOwner {
revokeReward = revokeReward_;
emit LogSetRevokeReward(revokeReward);
}
function setRevokeRewardPercentage(uint256 revokeRewardPrecentage_)
external
onlyOwner
{
revokeRewardPrecentage = revokeRewardPrecentage_;
emit LogSetRevokeRewardPrecentage(revokeRewardPrecentage_);
}
function setBeforePeriodFinish(bool beforePeriodFinish_)
external
onlyOwner
{
beforePeriodFinish = beforePeriodFinish_;
emit LogSetBeforePeriodFinish(beforePeriodFinish);
}
function setDuration(uint256 duration_) external onlyOwner {
require(duration >= 1);
duration = duration_;
emit LogSetDuration(duration);
}
function setPoolEnabled(bool poolEnabled_) external onlyOwner {
poolEnabled = poolEnabled_;
count = 0;
emit LogSetPoolEnabled(poolEnabled);
}
function setEnableUserLpLimit(bool enableUserLpLimit_) external onlyOwner {
enableUserLpLimit = enableUserLpLimit_;
emit LogSetEnableUserLpLimit(enableUserLpLimit);
}
function setUserLpLimit(uint256 userLpLimit_) external onlyOwner {
require(
userLpLimit_ <= poolLpLimit,
"User lp limit can't be more than pool limit"
);
userLpLimit = userLpLimit_;
emit LogSetUserLpLimit(userLpLimit);
}
function setEnablePoolLpLimit(bool enablePoolLpLimit_) external onlyOwner {
enablePoolLpLimit = enablePoolLpLimit_;
emit LogSetEnablePoolLpLimit(enablePoolLpLimit);
}
function setPoolLpLimit(uint256 poolLpLimit_) external onlyOwner {
require(
poolLpLimit_ >= userLpLimit,
"Pool lp limit can't be less than user lp limit"
);
poolLpLimit = poolLpLimit_;
emit LogSetPoolLpLimit(poolLpLimit);
}
function setRandomNumberConsumer(RandomNumberConsumer randomNumberConsumer_)
external
onlyOwner
{
randomNumberConsumer = RandomNumberConsumer(randomNumberConsumer_);
emit LogSetRandomNumberConsumer(randomNumberConsumer);
}
function setNormalDistribution(
uint256 normalDistributionMean_,
uint256 normalDistributionDeviation_,
uint256[100] calldata normalDistribution_
) external onlyOwner {
noramlDistributionMean = normalDistributionMean_;
normalDistributionDeviation = normalDistributionDeviation_;
normalDistribution = normalDistribution_;
emit LogSetNormalDistribution(
noramlDistributionMean,
normalDistributionDeviation,
normalDistribution
);
}
function setRandomNumberConsumerFee(uint256 fee_) external onlyOwner {
randomNumberConsumer.setFee(fee_);
emit LogSetRandomNumberConsumerFee(fee_);
}
function initialize(
address rewardToken_,
address pairToken_,
address policy_,
address randomNumberConsumer_,
address link_,
uint256 rewardPercentage_,
uint256 duration_,
uint256 userLpLimit_,
uint256 poolLpLimit_,
uint256 revokeRewardPrecentage_,
uint256 normalDistributionMean_,
uint256 normalDistributionDeviation_,
uint256[100] memory normalDistribution_
) public initializer {
setStakeToken(pairToken_);
rewardToken = IERC20(rewardToken_);
link = IERC20(link_);
randomNumberConsumer = RandomNumberConsumer(randomNumberConsumer_);
policy = policy_;
count = 0;
duration = duration_;
userLpLimit = userLpLimit_;
poolLpLimit = poolLpLimit_;
rewardPercentage = rewardPercentage_;
revokeRewardPrecentage = revokeRewardPrecentage_;
countInSequence = true;
normalDistribution = normalDistribution_;
noramlDistributionMean = normalDistributionMean_;
normalDistributionDeviation = normalDistributionDeviation_;
}
function checkStabilizerAndGetReward(
int256 supplyDelta_,
int256 rebaseLag_,
uint256 exchangeRate_,
uint256 debasePolicyBalance
) external returns (uint256 rewardAmount_) {
require(
msg.sender == policy,
"Only debase policy contract can call this"
);
if (supplyDelta_ > 0) {
count = count.add(1);
uint256 randomThreshold;
bool isValid;
(randomThreshold, isValid) = getOffChainRandomThreshold();
if (count >= randomThreshold && isValid) {
count = 0;
uint256 rewardToClaim = debasePolicyBalance
.mul(rewardPercentage)
.div(10**18);
if (
debasePolicyBalance >= rewardToClaim &&
(beforePeriodFinish || block.timestamp >= periodFinish)
) {
notifyRewardAmount(true);
emit LogCountThresholdHit(
rewardToClaim,
count,
randomThreshold
);
return rewardToClaim;
}
}
} else if (countInSequence) {
count = 0;
if (revokeReward && block.timestamp < periodFinish) {
notifyRewardAmount(false);
uint256 rewardToRevoke = rewardToken
.balanceOf(address(this))
.mul(revokeRewardPrecentage)
.div(10**18);
rewardToken.safeTransfer(policy, rewardToRevoke);
emit LogRewardRevoked(revokeRewardPrecentage, rewardToRevoke);
}
}
return 0;
}
function getOffChainRandomThreshold() internal returns (uint256, bool) {
if (
link.balanceOf(address(randomNumberConsumer)) >=
randomNumberConsumer.fee()
) {
randomNumberConsumer.getRandomNumber(block.timestamp);
} else {
return (0, false);
}
uint256 randomNumber = normalDistribution[randomNumberConsumer
.randomResult()
.mod(100)];
return (randomNumber, true);
}
function emergencyWithdraw() external onlyOwner {
rewardToken.safeTransfer(policy, rewardToken.balanceOf(address(this)));
emit LogEmergencyWithdraw(block.timestamp);
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardToken.balanceOf(address(this)).div(duration))
.mul(10**18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(10**18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
enabled
{
require(
!address(msg.sender).isContract(),
"Caller must not be a contract"
);
require(amount > 0, "Cannot stake 0");
if (enableUserLpLimit) {
require(amount <= userLpLimit, "Can't stake more than lp limit");
}
if (enablePoolLpLimit) {
uint256 lpBalance = totalSupply();
require(
amount.add(lpBalance) <= poolLpLimit,
"Can't stake pool lp limit reached"
);
}
super.stake(amount);
emit LogStaked(msg.sender, amount);
}
function withdraw(uint256 amount) public override updateReward(msg.sender) {
require(amount > 0, "Cannot withdraw 0");
super.withdraw(amount);
emit LogWithdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) enabled {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
rewardToken.safeTransfer(msg.sender, reward);
emit LogRewardPaid(msg.sender, reward);
rewardDistributed = rewardDistributed.add(reward);
}
}
function notifyRewardAmount(bool updatePeriod)
internal
updateReward(address(0))
{
lastUpdateTime = block.timestamp;
if (updatePeriod) {
periodFinish = block.timestamp.add(duration);
}
}
}
文件 11 的 16:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 12 的 16:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
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) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
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) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
文件 13 的 16:SafeMathChainlink.sol
pragma solidity ^0.6.0;
library SafeMathChainlink {
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");
uint256 c = a - b;
return c;
}
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");
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
}
文件 14 的 16:Token.sol
pragma solidity ^0.6.6;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract Token is ERC20 {
constructor(string memory name, string memory symbol)
public
ERC20(name, symbol)
{
_mint(msg.sender, 100000 * 10**18);
}
}
文件 15 的 16:VRFConsumerBase.sol
pragma solidity ^0.6.0;
import "./vendor/SafeMathChainlink.sol";
import "./interfaces/LinkTokenInterface.sol";
import "./VRFRequestIDBase.sol";
abstract contract VRFConsumerBase is VRFRequestIDBase {
using SafeMathChainlink for uint256;
function fulfillRandomness(bytes32 requestId, uint256 randomness)
internal virtual;
function requestRandomness(bytes32 _keyHash, uint256 _fee, uint256 _seed)
internal returns (bytes32 requestId)
{
LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, _seed));
uint256 vRFSeed = makeVRFInputSeed(_keyHash, _seed, address(this), nonces[_keyHash]);
nonces[_keyHash] = nonces[_keyHash].add(1);
return makeRequestId(_keyHash, vRFSeed);
}
LinkTokenInterface immutable internal LINK;
address immutable private vrfCoordinator;
mapping(bytes32 => uint256 ) public nonces;
constructor(address _vrfCoordinator, address _link) public {
vrfCoordinator = _vrfCoordinator;
LINK = LinkTokenInterface(_link);
}
function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external {
require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill");
fulfillRandomness(requestId, randomness);
}
}
文件 16 的 16:VRFRequestIDBase.sol
pragma solidity ^0.6.0;
contract VRFRequestIDBase {
function makeVRFInputSeed(bytes32 _keyHash, uint256 _userSeed,
address _requester, uint256 _nonce)
internal pure returns (uint256)
{
return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce)));
}
function makeRequestId(
bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed));
}
}
{
"compilationTarget": {
"contracts/Randomized-Threshold-Counter/RandomizedCounter.sol": "RandomizedCounter"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"count_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"threshold_","type":"uint256"}],"name":"LogCountThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rewardAmount_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"count_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"randomThreshold","type":"uint256"}],"name":"LogCountThresholdHit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LogEmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startedAt","type":"uint256"}],"name":"LogManualPoolStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"LogRewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"LogRewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"precentageRevoked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountRevoked","type":"uint256"}],"name":"LogRewardRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"beforePeriodFinish_","type":"bool"}],"name":"LogSetBeforePeriodFinish","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"countInSequence_","type":"bool"}],"name":"LogSetCountInSequence","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"countThreshold_","type":"uint256"}],"name":"LogSetCountThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration_","type":"uint256"}],"name":"LogSetDuration","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enablePoolLpLimit_","type":"bool"}],"name":"LogSetEnablePoolLpLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enableUserLpLimit_","type":"bool"}],"name":"LogSetEnableUserLpLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"noramlDistributionMean_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"normalDistributionDeviation_","type":"uint256"},{"indexed":false,"internalType":"uint256[100]","name":"normalDistribution_","type":"uint256[100]"}],"name":"LogSetNormalDistribution","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"poolEnabled_","type":"bool"}],"name":"LogSetPoolEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"poolLpLimit_","type":"uint256"}],"name":"LogSetPoolLpLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract RandomNumberConsumer","name":"randomNumberConsumer_","type":"address"}],"name":"LogSetRandomNumberConsumer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee_","type":"uint256"}],"name":"LogSetRandomNumberConsumerFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"revokeReward_","type":"bool"}],"name":"LogSetRevokeReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"revokeRewardPrecentage_","type":"uint256"}],"name":"LogSetRevokeRewardPrecentage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rewardPercentage_","type":"uint256"}],"name":"LogSetRewardPercentage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"userLpLimit_","type":"uint256"}],"name":"LogSetUserLpLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LogStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LogWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beforePeriodFinish","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"supplyDelta_","type":"int256"},{"internalType":"int256","name":"rebaseLag_","type":"int256"},{"internalType":"uint256","name":"exchangeRate_","type":"uint256"},{"internalType":"uint256","name":"debasePolicyBalance","type":"uint256"}],"name":"checkStabilizerAndGetReward","outputs":[{"internalType":"uint256","name":"rewardAmount_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"count","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"countInSequence","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enablePoolLpLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableUserLpLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rewardToken_","type":"address"},{"internalType":"address","name":"pairToken_","type":"address"},{"internalType":"address","name":"policy_","type":"address"},{"internalType":"address","name":"randomNumberConsumer_","type":"address"},{"internalType":"address","name":"link_","type":"address"},{"internalType":"uint256","name":"rewardPercentage_","type":"uint256"},{"internalType":"uint256","name":"duration_","type":"uint256"},{"internalType":"uint256","name":"userLpLimit_","type":"uint256"},{"internalType":"uint256","name":"poolLpLimit_","type":"uint256"},{"internalType":"uint256","name":"revokeRewardPrecentage_","type":"uint256"},{"internalType":"uint256","name":"normalDistributionMean_","type":"uint256"},{"internalType":"uint256","name":"normalDistributionDeviation_","type":"uint256"},{"internalType":"uint256[100]","name":"normalDistribution_","type":"uint256[100]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"link","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"noramlDistributionMean","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"normalDistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"normalDistributionDeviation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"policy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLpLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"randomNumberConsumer","outputs":[{"internalType":"contract RandomNumberConsumer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revokeReward","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revokeRewardPrecentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"beforePeriodFinish_","type":"bool"}],"name":"setBeforePeriodFinish","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"countInSequence_","type":"bool"}],"name":"setCountInSequence","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration_","type":"uint256"}],"name":"setDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enablePoolLpLimit_","type":"bool"}],"name":"setEnablePoolLpLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enableUserLpLimit_","type":"bool"}],"name":"setEnableUserLpLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"normalDistributionMean_","type":"uint256"},{"internalType":"uint256","name":"normalDistributionDeviation_","type":"uint256"},{"internalType":"uint256[100]","name":"normalDistribution_","type":"uint256[100]"}],"name":"setNormalDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"poolEnabled_","type":"bool"}],"name":"setPoolEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolLpLimit_","type":"uint256"}],"name":"setPoolLpLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract RandomNumberConsumer","name":"randomNumberConsumer_","type":"address"}],"name":"setRandomNumberConsumer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee_","type":"uint256"}],"name":"setRandomNumberConsumerFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"revokeReward_","type":"bool"}],"name":"setRevokeReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"revokeRewardPrecentage_","type":"uint256"}],"name":"setRevokeRewardPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rewardPercentage_","type":"uint256"}],"name":"setRewardPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"userLpLimit_","type":"uint256"}],"name":"setUserLpLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"userLpLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"y","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]