编译器
0.6.12+commit.27d51765
文件 1 的 14: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 functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(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 的 14: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 的 14: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);
}
文件 4 的 14:IMasterChef.sol
import "./IOREO.sol";
pragma solidity 0.6.12;
interface IMasterChef {
function poolLength() external view returns (uint256);
function pendingOreo(address _stakeToken, address _user) external view returns (uint256);
function userInfo(address _stakeToken, address _user)
external
view
returns (
uint256,
uint256,
address
);
function poolInfo(address _stakeToken)
external
view
returns (
uint256,
uint256,
uint256,
uint256
);
function devAddr() external view returns (address);
function refAddr() external view returns (address);
function bonusMultiplier() external view returns (uint256);
function totalAllocPoint() external view returns (uint256);
function oreoPerBlock() external view returns (uint256);
function addPool(
address _stakeToken,
uint256 _allocPoint,
uint256 _depositFee
) external;
function setPool(
address _stakeToken,
uint256 _allocPoint,
uint256 _depositFee
) external;
function updatePool(address _stakeToken) external;
function removePool(address _stakeToken) external;
function deposit(
address _for,
address _stakeToken,
uint256 _amount
) external;
function withdraw(
address _for,
address _stakeToken,
uint256 _amount
) external;
function depositOreo(address _for, uint256 _amount) external;
function withdrawOreo(address _for, uint256 _amount) external;
function harvest(address _for, address _stakeToken) external;
function harvest(address _for, address[] calldata _stakeToken) external;
function emergencyWithdraw(address _for, address _stakeToken) external;
function mintExtraReward(
address _stakeToken,
address _to,
uint256 _amount
) external;
function oreo() external returns (IOREO);
}
文件 5 的 14:IMasterChefCallback.sol
pragma solidity 0.6.12;
interface IMasterChefCallback {
function masterChefCall(
address stakeToken,
address userAddr,
uint256 unboostedReward
) external;
}
文件 6 的 14:IOREO.sol
pragma solidity 0.6.12;
interface IOREO {
function lock(address _account, uint256 _amount) external;
function lockOf(address _account) external view returns (uint256);
function unlock() external;
function mint(address _to, uint256 _amount) external;
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);
function startReleaseBlock() external view returns (uint256);
function endReleaseBlock() external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 7 的 14:IReferral.sol
pragma solidity 0.6.12;
interface IReferral {
function setMasterChef(address _masterChef) external;
function activate(address referrer) external;
function activateBySign(
address referee,
address referrer,
uint8 v,
bytes32 r,
bytes32 s
) external;
function isActivated(address _address) external view returns (bool);
function updateReferralReward(address accountAddress, uint256 reward) external;
function claimReward() external;
}
文件 8 的 14:IStake.sol
pragma solidity 0.6.12;
interface IStake {
function safeOreoTransfer(address _account, uint256 _amount) external;
}
文件 9 的 14:LinkList.sol
pragma solidity 0.6.12;
library LinkList {
address public constant start = address(1);
address public constant end = address(1);
address public constant empty = address(0);
struct List {
uint256 llSize;
mapping(address => address) next;
}
function init(List storage list) internal returns (List memory) {
list.next[start] = end;
return list;
}
function has(List storage list, address addr) internal view returns (bool) {
return list.next[addr] != empty;
}
function add(List storage list, address addr) internal returns (List memory) {
require(!has(list, addr), "LinkList::add:: addr is already in the list");
list.next[addr] = list.next[start];
list.next[start] = addr;
list.llSize++;
return list;
}
function remove(
List storage list,
address addr,
address prevAddr
) internal returns (List memory) {
require(has(list, addr), "LinkList::remove:: addr not whitelisted yet");
require(list.next[prevAddr] == addr, "LinkList::remove:: wrong prevConsumer");
list.next[prevAddr] = list.next[addr];
list.next[addr] = empty;
list.llSize--;
return list;
}
function getAll(List storage list) internal view returns (address[] memory) {
address[] memory addrs = new address[](list.llSize);
address curr = list.next[start];
for (uint256 i = 0; curr != end; i++) {
addrs[i] = curr;
curr = list.next[curr];
}
return addrs;
}
function getPreviousOf(List storage list, address addr) internal view returns (address) {
address curr = list.next[start];
require(curr != empty, "LinkList::getPreviousOf:: please init the linkedlist first");
for (uint256 i = 0; curr != end; i++) {
if (list.next[curr] == addr) return curr;
curr = list.next[curr];
}
return end;
}
function getNextOf(List storage list, address curr) internal view returns (address) {
return list.next[curr];
}
function length(List storage list) internal view returns (uint256) {
return list.llSize;
}
}
文件 10 的 14:MasterChef.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "../library/LinkList.sol";
import "./interfaces/IOREO.sol";
import "./interfaces/IStake.sol";
import "./interfaces/IMasterChef.sol";
import "./interfaces/IMasterChefCallback.sol";
import "./interfaces/IReferral.sol";
contract MasterChef is IMasterChef, Ownable, ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using LinkList for LinkList.List;
using Address for address;
struct UserInfo {
uint256 amount;
uint256 rewardDebt;
address fundedBy;
}
struct PoolInfo {
uint256 allocPoint;
uint256 lastRewardBlock;
uint256 accOreoPerShare;
uint256 depositFee;
}
IOREO public override oreo;
IStake public stake;
address public override devAddr;
uint256 public devBps;
address public override refAddr;
uint256 public refBps;
uint256 public override oreoPerBlock;
uint256 public override bonusMultiplier;
LinkList.List public pools;
mapping(address => PoolInfo) public override poolInfo;
mapping(address => mapping(address => UserInfo)) public override userInfo;
uint256 public override totalAllocPoint;
uint256 public startBlock;
mapping(address => bool) public stakeTokenCallerAllowancePool;
mapping(address => LinkList.List) public stakeTokenCallerContracts;
event Deposit(address indexed funder, address indexed fundee, address indexed stakeToken, uint256 amount);
event Withdraw(address indexed funder, address indexed fundee, address indexed stakeToken, uint256 amount);
event EmergencyWithdraw(address indexed user, address indexed stakeToken, uint256 amount);
event Harvest(address indexed funder, address indexed fundee, address indexed stakeToken, uint256 reward);
event SetStakeTokenCallerAllowancePool(address indexed stakeToken, bool isAllowed);
event AddStakeTokenCallerContract(address indexed stakeToken, address indexed caller);
event SetOreoPerBlock(uint256 prevOreoPerBlock, uint256 currentOreoPerBlock);
event RemoveStakeTokenCallerContract(address indexed stakeToken, address indexed caller);
event SetRefAddress(address indexed refAddress);
event SetDevAddress(address indexed devAddress);
event SetRefBps(uint256 refBps);
event SetDevBps(uint256 devBps);
event UpdateMultiplier(uint256 bonusMultiplier);
constructor(
IOREO _oreo,
IStake _stake,
address _devAddr,
address _refAddr,
uint256 _oreoPerBlock,
uint256 _startBlock
) public {
require(
_devAddr != address(0) && _devAddr != address(1),
"constructor: _devAddr must not be address(0) or address(1)"
);
require(
_refAddr != address(0) && _refAddr != address(1),
"constructor: _refAddr must not be address(0) or address(1)"
);
bonusMultiplier = 1;
oreo = _oreo;
stake = _stake;
devAddr = _devAddr;
refAddr = _refAddr;
oreoPerBlock = _oreoPerBlock;
startBlock = _startBlock;
devBps = 0;
refBps = 0;
pools.init();
pools.add(address(_oreo));
poolInfo[address(_oreo)] = PoolInfo({
allocPoint: 0,
lastRewardBlock: startBlock,
accOreoPerShare: 0,
depositFee: 0
});
totalAllocPoint = 0;
}
modifier onlyPermittedTokenFunder(address _beneficiary, address _stakeToken) {
require(_isFunder(_beneficiary, _stakeToken), "onlyPermittedTokenFunder: caller is not permitted");
_;
}
modifier onlyStakeTokenCallerContract(address _stakeToken) {
require(stakeTokenCallerContracts[_stakeToken].has(_msgSender()), "onlyStakeTokenCallerContract: bad caller");
_;
}
function setStakeTokenCallerAllowancePool(address _stakeToken, bool _isAllowed) external onlyOwner {
stakeTokenCallerAllowancePool[_stakeToken] = _isAllowed;
emit SetStakeTokenCallerAllowancePool(_stakeToken, _isAllowed);
}
function addStakeTokenCallerContract(address _stakeToken, address _caller) external onlyOwner {
require(
stakeTokenCallerAllowancePool[_stakeToken],
"addStakeTokenCallerContract: the pool doesn't allow a contract caller"
);
LinkList.List storage list = stakeTokenCallerContracts[_stakeToken];
if (list.getNextOf(LinkList.start) == LinkList.empty) {
list.init();
}
list.add(_caller);
emit AddStakeTokenCallerContract(_stakeToken, _caller);
}
function removeStakeTokenCallerContract(address _stakeToken, address _caller) external onlyOwner {
require(
stakeTokenCallerAllowancePool[_stakeToken],
"removeStakeTokenCallerContract: the pool doesn't allow a contract caller"
);
LinkList.List storage list = stakeTokenCallerContracts[_stakeToken];
list.remove(_caller, list.getPreviousOf(_caller));
emit RemoveStakeTokenCallerContract(_stakeToken, _caller);
}
function setDevAddress(address _devAddr) external onlyOwner {
require(
_devAddr != address(0) && _devAddr != address(1),
"setDevAddress: _devAddr must not be address(0) or address(1)"
);
devAddr = _devAddr;
emit SetDevAddress(_devAddr);
}
function setDevBps(uint256 _devBps) external onlyOwner {
require(_devBps <= 1000, "setDevBps::bad devBps");
massUpdatePools();
devBps = _devBps;
emit SetDevBps(_devBps);
}
function setRefAddress(address _refAddr) external onlyOwner {
require(
_refAddr != address(0) && _refAddr != address(1),
"setRefAddress: _refAddr must not be address(0) or address(1)"
);
refAddr = _refAddr;
emit SetRefAddress(_refAddr);
}
function setRefBps(uint256 _refBps) external onlyOwner {
require(_refBps <= 100, "setRefBps::bad refBps");
massUpdatePools();
refBps = _refBps;
emit SetRefBps(_refBps);
}
function setOreoPerBlock(uint256 _oreoPerBlock) external onlyOwner {
massUpdatePools();
uint256 prevOreoPerBlock = oreoPerBlock;
oreoPerBlock = _oreoPerBlock;
emit SetOreoPerBlock(prevOreoPerBlock, oreoPerBlock);
}
function addPool(
address _stakeToken,
uint256 _allocPoint,
uint256 _depositFee
) external override onlyOwner {
require(
_stakeToken != address(0) && _stakeToken != address(1),
"addPool: _stakeToken must not be address(0) or address(1)"
);
require(!pools.has(_stakeToken), "addPool: _stakeToken duplicated");
massUpdatePools();
uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock;
totalAllocPoint = totalAllocPoint.add(_allocPoint);
pools.add(_stakeToken);
poolInfo[_stakeToken] = PoolInfo({
allocPoint: _allocPoint,
lastRewardBlock: lastRewardBlock,
accOreoPerShare: 0,
depositFee: _depositFee
});
}
function setPool(
address _stakeToken,
uint256 _allocPoint,
uint256 _depositFee
) external override onlyOwner {
require(
_stakeToken != address(0) && _stakeToken != address(1),
"setPool: _stakeToken must not be address(0) or address(1)"
);
require(pools.has(_stakeToken), "setPool: _stakeToken not in the list");
massUpdatePools();
totalAllocPoint = totalAllocPoint.sub(poolInfo[_stakeToken].allocPoint).add(_allocPoint);
poolInfo[_stakeToken].allocPoint = _allocPoint;
poolInfo[_stakeToken].depositFee = _depositFee;
}
function removePool(address _stakeToken) external override onlyOwner {
require(_stakeToken != address(oreo), "removePool: can't remove OREO pool");
require(pools.has(_stakeToken), "removePool: pool not add yet");
require(IERC20(_stakeToken).balanceOf(address(this)) == 0, "removePool: pool not empty");
massUpdatePools();
totalAllocPoint = totalAllocPoint.sub(poolInfo[_stakeToken].allocPoint);
pools.remove(_stakeToken, pools.getPreviousOf(_stakeToken));
poolInfo[_stakeToken].allocPoint = 0;
poolInfo[_stakeToken].lastRewardBlock = 0;
poolInfo[_stakeToken].accOreoPerShare = 0;
poolInfo[_stakeToken].depositFee = 0;
}
function poolLength() external view override returns (uint256) {
return pools.length();
}
function getMultiplier(uint256 _lastRewardBlock, uint256 _currentBlock) private view returns (uint256) {
return _currentBlock.sub(_lastRewardBlock).mul(bonusMultiplier);
}
function updateMultiplier(uint256 _bonusMultiplier) public onlyOwner {
bonusMultiplier = _bonusMultiplier;
emit UpdateMultiplier(_bonusMultiplier);
}
function _isFunder(address _beneficiary, address _stakeToken) internal view returns (bool) {
if (stakeTokenCallerAllowancePool[_stakeToken]) return stakeTokenCallerContracts[_stakeToken].has(_msgSender());
return _beneficiary == _msgSender();
}
function pendingOreo(address _stakeToken, address _user) external view override returns (uint256) {
PoolInfo storage pool = poolInfo[_stakeToken];
UserInfo storage user = userInfo[_stakeToken][_user];
uint256 accOreoPerShare = pool.accOreoPerShare;
uint256 totalStakeToken = IERC20(_stakeToken).balanceOf(address(this));
if (block.number > pool.lastRewardBlock && totalStakeToken != 0) {
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 oreoReward = multiplier.mul(oreoPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
accOreoPerShare = accOreoPerShare.add(oreoReward.mul(1e12).div(totalStakeToken));
}
return user.amount.mul(accOreoPerShare).div(1e12).sub(user.rewardDebt);
}
function massUpdatePools() public {
address current = pools.next[LinkList.start];
while (current != LinkList.end) {
updatePool(current);
current = pools.getNextOf(current);
}
}
function updatePool(address _stakeToken) public override {
PoolInfo storage pool = poolInfo[_stakeToken];
if (block.number <= pool.lastRewardBlock) {
return;
}
uint256 totalStakeToken = IERC20(_stakeToken).balanceOf(address(this));
if (totalStakeToken == 0) {
pool.lastRewardBlock = block.number;
return;
}
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 oreoReward = multiplier.mul(oreoPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
oreo.mint(devAddr, oreoReward.mul(devBps).div(10000));
oreo.mint(address(stake), oreoReward.mul(refBps).div(10000));
oreo.mint(address(stake), oreoReward);
pool.accOreoPerShare = pool.accOreoPerShare.add(oreoReward.mul(1e12).div(totalStakeToken));
pool.lastRewardBlock = block.number;
}
function deposit(
address _for,
address _stakeToken,
uint256 _amount
) external override onlyPermittedTokenFunder(_for, _stakeToken) nonReentrant {
require(
_stakeToken != address(0) && _stakeToken != address(1),
"setPool: _stakeToken must not be address(0) or address(1)"
);
require(_stakeToken != address(oreo), "deposit: use depositOreo instead");
require(pools.has(_stakeToken), "deposit: no pool");
PoolInfo storage pool = poolInfo[_stakeToken];
UserInfo storage user = userInfo[_stakeToken][_for];
if (user.fundedBy != address(0)) require(user.fundedBy == _msgSender(), "deposit: only funder");
updatePool(_stakeToken);
if (user.amount > 0) _harvest(_for, _stakeToken);
if (user.fundedBy == address(0)) user.fundedBy = _msgSender();
if (_amount > 0) {
uint256 depositFeeAmount = _amount.mul(pool.depositFee).div(10000);
if (depositFeeAmount > 0) {
_amount = _amount.sub(depositFeeAmount);
IERC20(_stakeToken).safeTransferFrom(address(_msgSender()), devAddr, depositFeeAmount);
}
IERC20(_stakeToken).safeTransferFrom(address(_msgSender()), address(this), _amount);
user.amount = user.amount.add(_amount);
}
user.rewardDebt = user.amount.mul(pool.accOreoPerShare).div(1e12);
emit Deposit(_msgSender(), _for, _stakeToken, _amount);
}
function withdraw(
address _for,
address _stakeToken,
uint256 _amount
) external override nonReentrant {
require(
_stakeToken != address(0) && _stakeToken != address(1),
"setPool: _stakeToken must not be address(0) or address(1)"
);
require(_stakeToken != address(oreo), "withdraw: use withdrawOreo instead");
require(pools.has(_stakeToken), "withdraw: no pool");
PoolInfo storage pool = poolInfo[_stakeToken];
UserInfo storage user = userInfo[_stakeToken][_for];
require(user.fundedBy == _msgSender(), "withdraw: only funder");
require(user.amount >= _amount, "withdraw: not good");
updatePool(_stakeToken);
_harvest(_for, _stakeToken);
if (_amount > 0) {
user.amount = user.amount.sub(_amount);
IERC20(_stakeToken).safeTransfer(_msgSender(), _amount);
}
user.rewardDebt = user.amount.mul(pool.accOreoPerShare).div(1e12);
if (user.amount == 0) user.fundedBy = address(0);
emit Withdraw(_msgSender(), _for, _stakeToken, _amount);
}
function depositOreo(address _for, uint256 _amount)
external
override
onlyPermittedTokenFunder(_for, address(oreo))
nonReentrant
{
PoolInfo storage pool = poolInfo[address(oreo)];
UserInfo storage user = userInfo[address(oreo)][_for];
if (user.fundedBy != address(0)) require(user.fundedBy == _msgSender(), "depositOreo: bad sof");
updatePool(address(oreo));
if (user.amount > 0) _harvest(_for, address(oreo));
if (user.fundedBy == address(0)) user.fundedBy = _msgSender();
if (_amount > 0) {
uint256 depositFeeAmount = _amount.mul(pool.depositFee).div(10000);
if (depositFeeAmount > 0) {
_amount = _amount.sub(depositFeeAmount);
IERC20(address(oreo)).safeTransferFrom(address(_msgSender()), devAddr, depositFeeAmount);
}
IERC20(address(oreo)).safeTransferFrom(address(_msgSender()), address(this), _amount);
user.amount = user.amount.add(_amount);
}
user.rewardDebt = user.amount.mul(pool.accOreoPerShare).div(1e12);
emit Deposit(_msgSender(), _for, address(oreo), _amount);
}
function withdrawOreo(address _for, uint256 _amount) external override nonReentrant {
PoolInfo storage pool = poolInfo[address(oreo)];
UserInfo storage user = userInfo[address(oreo)][_for];
require(user.fundedBy == _msgSender(), "withdrawOreo: only funder");
require(user.amount >= _amount, "withdrawOreo: not good");
updatePool(address(oreo));
_harvest(_for, address(oreo));
if (_amount > 0) {
user.amount = user.amount.sub(_amount);
IERC20(address(oreo)).safeTransfer(address(_msgSender()), _amount);
}
user.rewardDebt = user.amount.mul(pool.accOreoPerShare).div(1e12);
if (user.amount == 0) user.fundedBy = address(0);
emit Withdraw(_msgSender(), _for, address(oreo), user.amount);
}
function harvest(address _for, address _stakeToken) external override nonReentrant {
PoolInfo storage pool = poolInfo[_stakeToken];
UserInfo storage user = userInfo[_stakeToken][_for];
updatePool(_stakeToken);
_harvest(_for, _stakeToken);
user.rewardDebt = user.amount.mul(pool.accOreoPerShare).div(1e12);
}
function harvest(address _for, address[] calldata _stakeTokens) external override nonReentrant {
for (uint256 i = 0; i < _stakeTokens.length; i++) {
PoolInfo storage pool = poolInfo[_stakeTokens[i]];
UserInfo storage user = userInfo[_stakeTokens[i]][_for];
updatePool(_stakeTokens[i]);
_harvest(_for, _stakeTokens[i]);
user.rewardDebt = user.amount.mul(pool.accOreoPerShare).div(1e12);
}
}
function _harvest(address _for, address _stakeToken) internal {
PoolInfo memory pool = poolInfo[_stakeToken];
UserInfo memory user = userInfo[_stakeToken][_for];
require(user.fundedBy == _msgSender(), "_harvest: only funder");
require(user.amount > 0, "_harvest: nothing to harvest");
uint256 pending = user.amount.mul(pool.accOreoPerShare).div(1e12).sub(user.rewardDebt);
require(pending <= oreo.balanceOf(address(stake)), "_harvest: wait what.. not enough OREO");
stake.safeOreoTransfer(_for, pending);
if (stakeTokenCallerContracts[_stakeToken].has(_msgSender())) {
_masterChefCallee(_msgSender(), _stakeToken, _for, pending);
}
_referralCallee(_for, pending);
emit Harvest(_msgSender(), _for, _stakeToken, pending);
}
function _referralCallee(address _for, uint256 _pending) internal {
if (!refAddr.isContract()) {
return;
}
stake.safeOreoTransfer(address(refAddr), _pending.mul(refBps).div(10000));
(bool success, ) = refAddr.call(
abi.encodeWithSelector(IReferral.updateReferralReward.selector, _for, _pending.mul(refBps).div(10000))
);
require(success, "_referralCallee: failed to execute updateReferralReward");
}
function _masterChefCallee(
address _caller,
address _stakeToken,
address _for,
uint256 _pending
) internal {
if (!_caller.isContract()) {
return;
}
(bool success, ) = _caller.call(
abi.encodeWithSelector(IMasterChefCallback.masterChefCall.selector, _stakeToken, _for, _pending)
);
require(success, "_masterChefCallee: failed to execute masterChefCall");
}
function emergencyWithdraw(address _for, address _stakeToken) external override nonReentrant {
UserInfo storage user = userInfo[_stakeToken][_for];
require(user.fundedBy == _msgSender(), "emergencyWithdraw: only funder");
IERC20(_stakeToken).safeTransfer(address(_for), user.amount);
emit EmergencyWithdraw(_for, _stakeToken, user.amount);
user.amount = 0;
user.rewardDebt = 0;
user.fundedBy = address(0);
}
function mintExtraReward(
address _stakeToken,
address _to,
uint256 _amount
) external override onlyStakeTokenCallerContract(_stakeToken) {
oreo.mint(_to, _amount);
}
}
文件 11 的 14: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;
}
}
文件 12 的 14:ReentrancyGuard.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 13 的 14: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");
}
}
}
文件 14 的 14: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;
}
}
{
"compilationTarget": {
"contracts/farm/MasterChef.sol": "MasterChef"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IOREO","name":"_oreo","type":"address"},{"internalType":"contract IStake","name":"_stake","type":"address"},{"internalType":"address","name":"_devAddr","type":"address"},{"internalType":"address","name":"_refAddr","type":"address"},{"internalType":"uint256","name":"_oreoPerBlock","type":"uint256"},{"internalType":"uint256","name":"_startBlock","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeToken","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"AddStakeTokenCallerContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"funder","type":"address"},{"indexed":true,"internalType":"address","name":"fundee","type":"address"},{"indexed":true,"internalType":"address","name":"stakeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"stakeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"funder","type":"address"},{"indexed":true,"internalType":"address","name":"fundee","type":"address"},{"indexed":true,"internalType":"address","name":"stakeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Harvest","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeToken","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"RemoveStakeTokenCallerContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"devAddress","type":"address"}],"name":"SetDevAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"devBps","type":"uint256"}],"name":"SetDevBps","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevOreoPerBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentOreoPerBlock","type":"uint256"}],"name":"SetOreoPerBlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"refAddress","type":"address"}],"name":"SetRefAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"refBps","type":"uint256"}],"name":"SetRefBps","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeToken","type":"address"},{"indexed":false,"internalType":"bool","name":"isAllowed","type":"bool"}],"name":"SetStakeTokenCallerAllowancePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bonusMultiplier","type":"uint256"}],"name":"UpdateMultiplier","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"funder","type":"address"},{"indexed":true,"internalType":"address","name":"fundee","type":"address"},{"indexed":true,"internalType":"address","name":"stakeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"uint256","name":"_depositFee","type":"uint256"}],"name":"addPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"},{"internalType":"address","name":"_caller","type":"address"}],"name":"addStakeTokenCallerContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bonusMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_for","type":"address"},{"internalType":"address","name":"_stakeToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_for","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositOreo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"devBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_for","type":"address"},{"internalType":"address","name":"_stakeToken","type":"address"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_for","type":"address"},{"internalType":"address[]","name":"_stakeTokens","type":"address[]"}],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_for","type":"address"},{"internalType":"address","name":"_stakeToken","type":"address"}],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintExtraReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oreo","outputs":[{"internalType":"contract IOREO","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oreoPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingOreo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolInfo","outputs":[{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"accOreoPerShare","type":"uint256"},{"internalType":"uint256","name":"depositFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pools","outputs":[{"internalType":"uint256","name":"llSize","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"}],"name":"removePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"},{"internalType":"address","name":"_caller","type":"address"}],"name":"removeStakeTokenCallerContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_devAddr","type":"address"}],"name":"setDevAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_devBps","type":"uint256"}],"name":"setDevBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oreoPerBlock","type":"uint256"}],"name":"setOreoPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"uint256","name":"_depositFee","type":"uint256"}],"name":"setPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_refAddr","type":"address"}],"name":"setRefAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_refBps","type":"uint256"}],"name":"setRefBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"},{"internalType":"bool","name":"_isAllowed","type":"bool"}],"name":"setStakeTokenCallerAllowancePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stake","outputs":[{"internalType":"contract IStake","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakeTokenCallerAllowancePool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakeTokenCallerContracts","outputs":[{"internalType":"uint256","name":"llSize","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocPoint","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":[{"internalType":"uint256","name":"_bonusMultiplier","type":"uint256"}],"name":"updateMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"address","name":"fundedBy","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_for","type":"address"},{"internalType":"address","name":"_stakeToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_for","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawOreo","outputs":[],"stateMutability":"nonpayable","type":"function"}]