编译器
0.8.20+commit.a1b79de6
文件 1 的 13:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 13:BoringERC20.sol
pragma solidity ^0.8.7;
import "./IBoringERC20.sol";
library BoringERC20 {
bytes4 private constant SIG_SYMBOL = 0x95d89b41;
bytes4 private constant SIG_NAME = 0x06fdde03;
bytes4 private constant SIG_DECIMALS = 0x313ce567;
bytes4 private constant SIG_TRANSFER = 0xa9059cbb;
bytes4 private constant SIG_TRANSFER_FROM = 0x23b872dd;
function returnDataToString(bytes memory data)
internal
pure
returns (string memory)
{
if (data.length >= 64) {
return abi.decode(data, (string));
} else if (data.length == 32) {
uint8 i = 0;
while (i < 32 && data[i] != 0) {
i++;
}
bytes memory bytesArray = new bytes(i);
for (i = 0; i < 32 && data[i] != 0; i++) {
bytesArray[i] = data[i];
}
return string(bytesArray);
} else {
return "???";
}
}
function safeSymbol(IBoringERC20 token)
internal
view
returns (string memory)
{
(bool success, bytes memory data) = address(token).staticcall(
abi.encodeWithSelector(SIG_SYMBOL)
);
return success ? returnDataToString(data) : "???";
}
function safeName(IBoringERC20 token)
internal
view
returns (string memory)
{
(bool success, bytes memory data) = address(token).staticcall(
abi.encodeWithSelector(SIG_NAME)
);
return success ? returnDataToString(data) : "???";
}
function safeDecimals(IBoringERC20 token) internal view returns (uint8) {
(bool success, bytes memory data) = address(token).staticcall(
abi.encodeWithSelector(SIG_DECIMALS)
);
return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;
}
function safeTransfer(
IBoringERC20 token,
address to,
uint256 amount
) internal {
(bool success, bytes memory data) = address(token).call(
abi.encodeWithSelector(SIG_TRANSFER, to, amount)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"BoringERC20: Transfer failed"
);
}
function safeTransferFrom(
IBoringERC20 token,
address from,
address to,
uint256 amount
) internal {
(bool success, bytes memory data) = address(token).call(
abi.encodeWithSelector(SIG_TRANSFER_FROM, from, to, amount)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"BoringERC20: TransferFrom failed"
);
}
}
文件 3 的 13:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 4 的 13:EsProxyMaster.sol
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./interfaces/IComplexRewarder.sol";
import './interfaces/IEsTokenUsage.sol';
import './interfaces/esMaster/IEsToken.sol';
import './interfaces/esMaster/IBasedDistributorV2.sol';
import "../farm/v2/libraries/BoringERC20.sol";
import "../farm/v2/IUniswapV2Pair.sol";
contract EsProxyMaster is Ownable, ReentrancyGuard, IEsTokenUsage {
using BoringERC20 for IBoringERC20;
struct UserInfo {
uint256 amount;
uint256 rewardDebt;
uint256 rewardLockedUp;
uint256 nextHarvestUntil;
}
struct PoolInfo {
IEsToken esToken;
uint256 allocPoint;
uint256 lastRewardTimestamp;
uint256 accTokenPerShare;
uint256 harvestInterval;
uint256 totalLp;
IComplexRewarder[] rewarders;
}
IBoringERC20 public rewardToken;
IBasedDistributorV2 public emissionMaster;
uint public emissionPid;
uint lastHarvestTimestamp;
uint256 public tokenPerSec;
uint256 public constant MAXIMUM_HARVEST_INTERVAL = 14 days;
PoolInfo[] public poolInfo;
mapping(uint256 => mapping(address => UserInfo)) public userInfo;
mapping(address => uint256) public esTokens;
uint256 public totalAllocPoint = 0;
uint256 public startTimestamp;
uint256 public totalLockedUpRewards;
uint256 public totalTokenInPools = 0;
uint256 private immutable ACC_TOKEN_PRECISION = 1e12;
modifier validatePoolByPid(uint256 _pid) {
require(_pid < poolInfo.length, "Pool does not exist");
_;
}
event Add(
uint256 indexed pid,
uint256 allocPoint,
IEsToken indexed esToken,
uint256 harvestInterval,
IComplexRewarder[] indexed rewarders
);
event Set(
uint256 indexed pid,
uint256 allocPoint,
uint256 harvestInterval,
IComplexRewarder[] indexed rewarders
);
event UpdatePool(
uint256 indexed pid,
uint256 lastRewardTimestamp,
uint256 lpSupply,
uint256 accTokenPerShare
);
event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
event EmissionRateUpdated(
address indexed caller,
uint256 previousValue,
uint256 newValue
);
event RewardLockedUp(
address indexed user,
uint256 indexed pid,
uint256 amountLockedUp
);
event AllocPointsUpdated(
address indexed caller,
uint256 previousAmount,
uint256 newAmount
);
constructor(
IBoringERC20 _rewardToken
) {
startTimestamp = block.timestamp + (60 * 60 * 24 * 365);
rewardToken = _rewardToken;
poolInfo.push(
PoolInfo({
esToken: IEsToken(address(0)),
allocPoint: 0,
lastRewardTimestamp: 0,
accTokenPerShare: 0,
harvestInterval: 0,
totalLp: 0,
rewarders: new IComplexRewarder[](0)
})
);
}
function startFarming(IBoringERC20 _dummyToken, IBasedDistributorV2 _emissionMaster, uint _emissionPid) public onlyOwner {
require(
block.timestamp < startTimestamp,
"start farming: farm started already"
);
uint dummySupply = _dummyToken.totalSupply();
require(_dummyToken.balanceOf(address(this)) == dummySupply, "Invalid token initialization");
require(address(_emissionMaster) != address(0), "Invalid emission master");
emissionMaster = _emissionMaster;
emissionPid = _emissionPid;
_dummyToken.approve(address(emissionMaster), dummySupply);
emissionMaster.deposit(emissionPid, dummySupply);
uint256 length = poolInfo.length;
for (uint256 pid = 1; pid < length; ++pid) {
PoolInfo storage pool = poolInfo[pid];
pool.lastRewardTimestamp = block.timestamp;
}
startTimestamp = block.timestamp;
lastHarvestTimestamp = block.timestamp;
_updateEmissionRate();
}
function poolLength() external view returns (uint256) {
return poolInfo.length;
}
function add(
uint256 _allocPoint,
IEsToken _esToken,
uint256 _harvestInterval,
IComplexRewarder[] calldata _rewarders
) public onlyOwner {
require(_rewarders.length <= 10, "add: too many rewarders");
require(
_harvestInterval <= MAXIMUM_HARVEST_INTERVAL,
"add: invalid harvest interval"
);
require(
Address.isContract(address(_esToken)),
"add: LP token must be a valid contract"
);
require(esTokens[address(_esToken)] == 0, "Pool already exists");
for (
uint256 rewarderId = 0;
rewarderId < _rewarders.length;
++rewarderId
) {
require(
Address.isContract(address(_rewarders[rewarderId])),
"add: rewarder must be contract"
);
}
_massUpdatePools();
uint256 lastRewardTimestamp = block.timestamp > startTimestamp
? block.timestamp
: startTimestamp;
totalAllocPoint += _allocPoint;
uint pid = poolInfo.length;
esTokens[address(_esToken)] = pid;
poolInfo.push(
PoolInfo({
esToken: _esToken,
allocPoint: _allocPoint,
lastRewardTimestamp: lastRewardTimestamp,
accTokenPerShare: 0,
harvestInterval: _harvestInterval,
totalLp: 0,
rewarders: _rewarders
})
);
emit Add(
poolInfo.length - 1,
_allocPoint,
_esToken,
_harvestInterval,
_rewarders
);
}
function set(
uint256 _pid,
uint256 _allocPoint,
uint256 _harvestInterval,
IComplexRewarder[] calldata _rewarders
) public onlyOwner validatePoolByPid(_pid) {
require(_rewarders.length <= 10, "set: too many rewarders");
require(_pid != 0, "Not authorized");
require(
_harvestInterval <= MAXIMUM_HARVEST_INTERVAL,
"set: invalid harvest interval"
);
for (
uint256 rewarderId = 0;
rewarderId < _rewarders.length;
++rewarderId
) {
require(
Address.isContract(address(_rewarders[rewarderId])),
"set: rewarder must be contract"
);
}
_massUpdatePools();
totalAllocPoint =
totalAllocPoint -
poolInfo[_pid].allocPoint +
_allocPoint;
poolInfo[_pid].allocPoint = _allocPoint;
poolInfo[_pid].harvestInterval = _harvestInterval;
poolInfo[_pid].rewarders = _rewarders;
emit Set(
_pid,
_allocPoint,
_harvestInterval,
_rewarders
);
}
function pendingTokens(uint256 _pid, address _user)
external
view
validatePoolByPid(_pid)
returns (
address[] memory addresses,
string[] memory symbols,
uint256[] memory decimals,
uint256[] memory amounts
)
{
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint256 accTokenPerShare = pool.accTokenPerShare;
uint256 lpSupply = pool.totalLp;
if (block.timestamp > pool.lastRewardTimestamp && lpSupply != 0) {
uint256 multiplier = block.timestamp - pool.lastRewardTimestamp;
uint256 tokenReward = (multiplier *
tokenPerSec *
pool.allocPoint) /
totalAllocPoint;
accTokenPerShare += (
((tokenReward * ACC_TOKEN_PRECISION) / lpSupply)
);
}
uint256 pendingToken = (((user.amount * accTokenPerShare) /
ACC_TOKEN_PRECISION) - user.rewardDebt) + user.rewardLockedUp;
addresses = new address[](pool.rewarders.length + 1);
symbols = new string[](pool.rewarders.length + 1);
amounts = new uint256[](pool.rewarders.length + 1);
decimals = new uint256[](pool.rewarders.length + 1);
addresses[0] = address(rewardToken);
symbols[0] = IBoringERC20(rewardToken).safeSymbol();
decimals[0] = IBoringERC20(rewardToken).safeDecimals();
amounts[0] = pendingToken;
for (
uint256 rewarderId = 0;
rewarderId < pool.rewarders.length;
++rewarderId
) {
addresses[rewarderId + 1] = address(
pool.rewarders[rewarderId].rewardToken()
);
symbols[rewarderId + 1] = IBoringERC20(
pool.rewarders[rewarderId].rewardToken()
).safeSymbol();
decimals[rewarderId + 1] = IBoringERC20(
pool.rewarders[rewarderId].rewardToken()
).safeDecimals();
amounts[rewarderId + 1] = pool.rewarders[rewarderId].pendingTokens(
_pid,
_user
);
}
}
function poolRewardsPerSec(uint256 _pid)
external
view
validatePoolByPid(_pid)
returns (
address[] memory addresses,
string[] memory symbols,
uint256[] memory decimals,
uint256[] memory rewardsPerSec
)
{
PoolInfo storage pool = poolInfo[_pid];
addresses = new address[](pool.rewarders.length + 1);
symbols = new string[](pool.rewarders.length + 1);
decimals = new uint256[](pool.rewarders.length + 1);
rewardsPerSec = new uint256[](pool.rewarders.length + 1);
addresses[0] = address(rewardToken);
symbols[0] = IBoringERC20(rewardToken).safeSymbol();
decimals[0] = IBoringERC20(rewardToken).safeDecimals();
rewardsPerSec[0] =
(pool.allocPoint * tokenPerSec) /
totalAllocPoint;
for (
uint256 rewarderId = 0;
rewarderId < pool.rewarders.length;
++rewarderId
) {
addresses[rewarderId + 1] = address(
pool.rewarders[rewarderId].rewardToken()
);
symbols[rewarderId + 1] = IBoringERC20(
pool.rewarders[rewarderId].rewardToken()
).safeSymbol();
decimals[rewarderId + 1] = IBoringERC20(
pool.rewarders[rewarderId].rewardToken()
).safeDecimals();
rewardsPerSec[rewarderId + 1] = pool
.rewarders[rewarderId]
.poolRewardsPerSec(_pid);
}
}
function poolRewarders(uint256 _pid)
external
view
validatePoolByPid(_pid)
returns (address[] memory rewarders)
{
PoolInfo storage pool = poolInfo[_pid];
rewarders = new address[](pool.rewarders.length);
for (
uint256 rewarderId = 0;
rewarderId < pool.rewarders.length;
++rewarderId
) {
rewarders[rewarderId] = address(pool.rewarders[rewarderId]);
}
}
function canHarvest(uint256 _pid, address _user)
public
view
validatePoolByPid(_pid)
returns (bool)
{
UserInfo storage user = userInfo[_pid][_user];
return
block.timestamp >= startTimestamp &&
block.timestamp >= user.nextHarvestUntil;
}
function massUpdatePools() external nonReentrant {
_massUpdatePools();
}
function _massUpdatePools() internal {
for (uint256 pid = 1; pid < poolInfo.length; ++pid) {
_updatePool(pid);
}
}
function updatePool(uint256 _pid) external nonReentrant {
require(_pid != 0, "Not authorized");
_updatePool(_pid);
}
function _updatePool(uint256 _pid) internal validatePoolByPid(_pid) {
PoolInfo storage pool = poolInfo[_pid];
_harvestAndValidateEmissions();
if (block.timestamp <= pool.lastRewardTimestamp) {
return;
}
uint256 lpSupply = pool.totalLp;
if (lpSupply == 0 || pool.allocPoint == 0) {
pool.lastRewardTimestamp = block.timestamp;
return;
}
uint256 multiplier = block.timestamp - pool.lastRewardTimestamp;
uint256 tokenReward = ((multiplier * tokenPerSec) * pool.allocPoint) /
totalAllocPoint;
pool.accTokenPerShare +=
(tokenReward * ACC_TOKEN_PRECISION) /
pool.totalLp;
pool.lastRewardTimestamp = block.timestamp;
emit UpdatePool(
_pid,
pool.lastRewardTimestamp,
lpSupply,
pool.accTokenPerShare
);
}
function allocate(address user, uint256 amount, bytes calldata data) external override nonReentrant {
uint _pid = esTokens[msg.sender];
require(_pid != 0, "Not authorized");
_deposit(user, _pid, amount);
}
function harvest(uint256 _pid) external nonReentrant validatePoolByPid(_pid) {
require(_pid != 0, "Not authorized");
_deposit(msg.sender, _pid, 0);
}
function _deposit(address userAddress, uint256 _pid, uint256 _amount)
internal
{
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][userAddress];
_updatePool(_pid);
payOrLockupPendingToken(_pid, userAddress);
if (_amount > 0) {
user.amount += _amount;
if (address(pool.esToken) == address(rewardToken)) {
totalTokenInPools += _amount;
}
}
user.rewardDebt =
(user.amount * pool.accTokenPerShare) /
ACC_TOKEN_PRECISION;
for (
uint256 rewarderId = 0;
rewarderId < pool.rewarders.length;
++rewarderId
) {
pool.rewarders[rewarderId].onReward(
_pid,
userAddress,
user.amount
);
}
if (_amount > 0) {
pool.totalLp += _amount;
}
emit Deposit(userAddress, _pid, _amount);
}
function deallocate(address userAddress, uint256 _amount, bytes calldata data) external override nonReentrant {
uint _pid = esTokens[msg.sender];
require(_pid != 0, "Not authorized");
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][userAddress];
require(user.amount >= _amount, "withdraw: user amount not enough");
require(pool.totalLp >= _amount, "withdraw: pool total not enough");
_updatePool(_pid);
payOrLockupPendingToken(_pid, userAddress);
if (_amount > 0) {
user.amount -= _amount;
if (address(pool.esToken) == address(rewardToken)) {
totalTokenInPools -= _amount;
}
}
user.rewardDebt =
(user.amount * pool.accTokenPerShare) /
ACC_TOKEN_PRECISION;
for (
uint256 rewarderId = 0;
rewarderId < pool.rewarders.length;
++rewarderId
) {
try pool.rewarders[rewarderId].onReward(
_pid,
userAddress,
user.amount
) {} catch {}
}
if (_amount > 0) {
pool.totalLp -= _amount;
}
emit Withdraw(userAddress, _pid, _amount);
}
function payOrLockupPendingToken(uint256 _pid, address userAddress) internal {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][userAddress];
if (user.nextHarvestUntil == 0 && block.timestamp >= startTimestamp) {
user.nextHarvestUntil = block.timestamp + pool.harvestInterval;
}
uint256 pending = ((user.amount * pool.accTokenPerShare) /
ACC_TOKEN_PRECISION) - user.rewardDebt;
if (canHarvest(_pid, userAddress)) {
if (pending > 0 || user.rewardLockedUp > 0) {
uint256 pendingRewards = pending + user.rewardLockedUp;
totalLockedUpRewards -= user.rewardLockedUp;
user.rewardLockedUp = 0;
user.nextHarvestUntil = block.timestamp + pool.harvestInterval;
safeTokenTransfer(userAddress, pendingRewards);
}
} else if (pending > 0) {
totalLockedUpRewards += pending;
user.rewardLockedUp += pending;
emit RewardLockedUp(userAddress, _pid, pending);
}
}
function safeTokenTransfer(address _to, uint256 _amount) internal {
if (rewardToken.balanceOf(address(this)) > totalTokenInPools) {
uint256 tokenBal = rewardToken.balanceOf(address(this)) -
totalTokenInPools;
if (_amount >= tokenBal) {
rewardToken.safeTransfer(_to, tokenBal);
} else if (_amount > 0) {
rewardToken.safeTransfer(_to, _amount);
}
}
}
function _harvestAndValidateEmissions() internal {
(,,,,,uint harvestInterval,) = emissionMaster.poolInfo(emissionPid);
if(block.timestamp <= lastHarvestTimestamp + harvestInterval) {
return;
}
uint preBalance = rewardToken.balanceOf(address(this));
emissionMaster.deposit(emissionPid, 0);
uint derivedTokenPerSec = (rewardToken.balanceOf(address(this)) - preBalance) / (block.timestamp - lastHarvestTimestamp);
lastHarvestTimestamp = block.timestamp;
if(derivedTokenPerSec != tokenPerSec) {
_updateEmissionRate();
}
}
function updateEmissionRate() public onlyOwner {
_updateEmissionRate();
}
function _updateEmissionRate() internal {
uint newTokenPerSec;
{
(,uint parentAllocPoint,,,,,) = emissionMaster.poolInfo(emissionPid);
uint parentTotalAllocPoint = emissionMaster.totalAllocPoint();
uint parentTokenPerSec = emissionMaster.albPerSec();
uint teamPercent = emissionMaster.teamPercent();
uint investorPercent = emissionMaster.investorPercent();
uint treasuryPercent = emissionMaster.treasuryPercent();
uint lpPercent = 1000 - teamPercent - investorPercent - treasuryPercent;
newTokenPerSec = (parentTokenPerSec * parentAllocPoint / parentTotalAllocPoint) * lpPercent / 1000;
}
if(newTokenPerSec != tokenPerSec) {
_massUpdatePools();
emit EmissionRateUpdated(msg.sender, tokenPerSec, newTokenPerSec);
tokenPerSec = newTokenPerSec;
}
}
function updateAllocPoint(uint256 _pid, uint256 _allocPoint)
public
onlyOwner
{
require(_pid != 0, "Not authorized");
_massUpdatePools();
emit AllocPointsUpdated(
msg.sender,
poolInfo[_pid].allocPoint,
_allocPoint
);
totalAllocPoint =
totalAllocPoint -
poolInfo[_pid].allocPoint +
_allocPoint;
poolInfo[_pid].allocPoint = _allocPoint;
}
function poolTotalLp(uint256 pid) external view returns (uint256) {
return poolInfo[pid].totalLp;
}
function harvestMany(uint256[] calldata _pids) public nonReentrant {
require(_pids.length <= 30, "harvest many: too many pool ids");
for (uint256 index = 0; index < _pids.length; ++index) {
require(_pids[index] != 0, "Not authorized");
_deposit(msg.sender, _pids[index], 0);
}
}
function recoverRewardToken(uint amount) external onlyOwner {
rewardToken.safeTransfer(owner(), amount);
}
}
文件 5 的 13:IBasedDistributorV2.sol
pragma solidity ^0.8.2;
interface IBasedDistributorV2 {
function totalAllocPoint() external view returns (uint256);
function deposit(uint256 _pid, uint256 _amount) external;
function poolLength() external view returns (uint256);
function albPerSec() external view returns (uint256);
function poolTotalLp(uint256 pid) external view returns (uint256);
function poolInfo(uint256 pid) external view returns (address, uint256, uint256, uint256, uint16, uint256, uint256);
function teamPercent() external view returns (uint256);
function investorPercent() external view returns (uint256);
function treasuryPercent() external view returns (uint256);
}
文件 6 的 13:IBoringERC20.sol
pragma solidity ^0.8.7;
interface IBoringERC20 {
function mint(address to, uint256 amount) external;
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, 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
);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
文件 7 的 13:IComplexRewarder.sol
pragma solidity ^0.8.7;
import "../../farm/v2/libraries/IBoringERC20.sol";
interface IComplexRewarder {
function onReward(
uint256 pid,
address user,
uint256 newLpAmount
) external;
function pendingTokens(uint256 pid, address user)
external
view
returns (uint256 pending);
function rewardToken() external view returns (IBoringERC20);
function poolRewardsPerSec(uint256 pid) external view returns (uint256);
}
文件 8 的 13:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, 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 from, address to, uint256 amount) external returns (bool);
}
文件 9 的 13:IEsToken.sol
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IEsToken is IERC20 {
function usageAllocations(address userAddress, address usageAddress) external view returns (uint256 allocation);
function allocateFromUsage(address userAddress, uint256 amount) external;
function convertTo(uint256 amount, address to) external;
function deallocateFromUsage(address userAddress, uint256 amount) external;
function isTransferWhitelisted(address account) external view returns (bool);
}
文件 10 的 13:IEsTokenUsage.sol
pragma solidity >=0.7.6;
interface IEsTokenUsage {
function allocate(address userAddress, uint256 amount, bytes calldata data) external;
function deallocate(address userAddress, uint256 amount, bytes calldata data) external;
}
文件 11 的 13:IUniswapV2Pair.sol
pragma solidity ^0.8.7;
interface IUniswapV2Pair {
function initialize(address, address) external;
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
文件 12 的 13:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 13 的 13:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
{
"compilationTarget": {
"contracts/escrow/EsProxyMaster.sol": "EsProxyMaster"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 999999
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IBoringERC20","name":"_rewardToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocPoint","type":"uint256"},{"indexed":true,"internalType":"contract IEsToken","name":"esToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"harvestInterval","type":"uint256"},{"indexed":true,"internalType":"contract IComplexRewarder[]","name":"rewarders","type":"address[]"}],"name":"Add","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newAmount","type":"uint256"}],"name":"AllocPointsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"EmissionRateUpdated","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":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountLockedUp","type":"uint256"}],"name":"RewardLockedUp","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocPoint","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"harvestInterval","type":"uint256"},{"indexed":true,"internalType":"contract IComplexRewarder[]","name":"rewarders","type":"address[]"}],"name":"Set","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastRewardTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accTokenPerShare","type":"uint256"}],"name":"UpdatePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"MAXIMUM_HARVEST_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"contract IEsToken","name":"_esToken","type":"address"},{"internalType":"uint256","name":"_harvestInterval","type":"uint256"},{"internalType":"contract IComplexRewarder[]","name":"_rewarders","type":"address[]"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"allocate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"canHarvest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"deallocate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emissionMaster","outputs":[{"internalType":"contract IBasedDistributorV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emissionPid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"esTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_pids","type":"uint256[]"}],"name":"harvestMany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingTokens","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"uint256[]","name":"decimals","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"contract IEsToken","name":"esToken","type":"address"},{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardTimestamp","type":"uint256"},{"internalType":"uint256","name":"accTokenPerShare","type":"uint256"},{"internalType":"uint256","name":"harvestInterval","type":"uint256"},{"internalType":"uint256","name":"totalLp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"poolRewarders","outputs":[{"internalType":"address[]","name":"rewarders","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"poolRewardsPerSec","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"uint256[]","name":"decimals","type":"uint256[]"},{"internalType":"uint256[]","name":"rewardsPerSec","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"poolTotalLp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IBoringERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"uint256","name":"_harvestInterval","type":"uint256"},{"internalType":"contract IComplexRewarder[]","name":"_rewarders","type":"address[]"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IBoringERC20","name":"_dummyToken","type":"address"},{"internalType":"contract IBasedDistributorV2","name":"_emissionMaster","type":"address"},{"internalType":"uint256","name":"_emissionPid","type":"uint256"}],"name":"startFarming","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenPerSec","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLockedUpRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokenInPools","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":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"}],"name":"updateAllocPoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateEmissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint256","name":"rewardLockedUp","type":"uint256"},{"internalType":"uint256","name":"nextHarvestUntil","type":"uint256"}],"stateMutability":"view","type":"function"}]