文件 1 的 12: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 的 12: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 的 12:IEIP2612.sol
pragma solidity >=0.6.0 <0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IEIP2612 is IERC20 {
function DOMAIN_SEPARATOR() external view returns (bytes32);
function nonces(address owner) external view returns (uint256);
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
}
文件 4 的 12: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 的 12:IEmergency.sol
pragma solidity >=0.6.0 <0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IEmergency {
function emergencyWithdraw(IERC20 token) external ;
}
文件 6 的 12:ILon.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IEmergency.sol";
import "./IEIP2612.sol";
interface ILon is IEmergency, IEIP2612 {
function cap() external view returns(uint256);
function mint(address to, uint256 amount) external;
function burn(uint256 amount) external;
}
文件 7 的 12:IUniswapRouterV2.sol
pragma solidity >=0.5.0 <0.8.0;
interface IUniswapRouterV2 {
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
}
文件 8 的 12:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Ownable {
address public owner;
address public nominatedOwner;
constructor(address _owner) {
owner = _owner;
}
function acceptOwnership() external {
require(msg.sender == nominatedOwner, "not nominated");
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
function renounceOwnership() external onlyOwner {
emit OwnerChanged(owner, address(0));
owner = address(0);
}
function nominateNewOwner(address newOwner) external onlyOwner {
nominatedOwner = newOwner;
emit OwnerNominated(newOwner);
}
modifier onlyOwner {
require(msg.sender == owner, "not owner");
_;
}
event OwnerNominated(address indexed newOwner);
event OwnerChanged(address indexed oldOwner, address indexed newOwner);
}
文件 9 的 12:Pausable.sol
pragma solidity >=0.6.0 <0.8.0;
import "./Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor () internal {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 10 的 12:RewardDistributor.sol
pragma solidity >=0.6.0 <0.8.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "../../interfaces/IUniswapRouterV2.sol";
import "../../interfaces/ILon.sol";
import "../Ownable.sol";
contract RewardDistributor is Ownable, Pausable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
uint256 private constant MAX_UINT = 2**256 - 1;
address public immutable LON_TOKEN_ADDR;
uint32 public buybackInterval;
uint8 public miningFactor;
uint8 public numStrategyAddr;
uint8 public numExchangeAddr;
mapping(address => bool) public isOperator;
address public treasury;
address public lonStaking;
address public miningTreasury;
address public feeTokenRecipient;
mapping(uint256 => address) public strategyAddrs;
mapping(uint256 => address) public exchangeAddrs;
mapping(address => FeeToken) public feeTokens;
struct FeeToken {
uint8 exchangeIndex;
uint8 LFactor;
uint8 RFactor;
uint32 lastTimeBuyback;
bool enable;
uint256 minBuy;
uint256 maxBuy;
address[] path;
}
event SetOperator(address operator, bool enable);
event SetMiningFactor(uint8 miningFactor);
event SetTreasury(address treasury);
event SetLonStaking(address lonStaking);
event SetMiningTreasury(address miningTreasury);
event SetFeeTokenRecipient(address feeTokenRecipient);
event SetBuybackInterval(uint256 interval);
event SetStrategy(uint256 index, address strategy);
event SetExchange(uint256 index, address exchange);
event EnableFeeToken(address feeToken, bool enable);
event SetFeeToken(
address feeToken,
uint256 exchangeIndex,
address[] path,
uint256 LFactor,
uint256 RFactor,
uint256 minBuy,
uint256 maxBuy
);
event SetFeeTokenFailure(address feeToken, string reason, bytes lowLevelData);
event BuyBack(
address feeToken,
uint256 feeTokenAmount,
uint256 swappedLonAmount,
uint256 LFactor,
uint256 RFactor,
uint256 minBuy,
uint256 maxBuy
);
event BuyBackFailure(address feeToken, uint256 feeTokenAmount, string reason, bytes lowLevelData);
event DistributeLon(uint256 treasuryAmount, uint256 lonStakingAmount);
event MintLon(uint256 mintedAmount);
event Recovered(address token, uint256 amount);
modifier only_Operator_or_Owner {
require(_isAuthorized(msg.sender), "only operator or owner can call");
_;
}
modifier only_Owner_or_Operator_or_Self {
if (msg.sender != address(this)) {
require(_isAuthorized(msg.sender), "only operator or owner can call");
}
_;
}
modifier only_EOA {
require((msg.sender == tx.origin), "only EOA can call");
_;
}
modifier only_EOA_or_Self {
if (msg.sender != address(this)) {
require((msg.sender == tx.origin), "only EOA can call");
}
_;
}
constructor(
address _LON_TOKEN_ADDR,
address _owner,
address _operator,
uint32 _buyBackInterval,
uint8 _miningFactor,
address _treasury,
address _lonStaking,
address _miningTreasury,
address _feeTokenRecipient
) Ownable(_owner) {
LON_TOKEN_ADDR = _LON_TOKEN_ADDR;
isOperator[_operator] = true;
buybackInterval = _buyBackInterval;
require(_miningFactor <= 100, "incorrect mining factor");
miningFactor = _miningFactor;
require(Address.isContract(_lonStaking), "Lon staking is not a contract");
treasury = _treasury;
lonStaking = _lonStaking;
miningTreasury = _miningTreasury;
feeTokenRecipient = _feeTokenRecipient;
}
function getFeeTokenPath(address _feeTokenAddr) public view returns (address[] memory path) {
return feeTokens[_feeTokenAddr].path;
}
function pause() external onlyOwner whenNotPaused {
_pause();
}
function unpause() external onlyOwner whenPaused {
_unpause();
}
function setOperator(address _operator, bool _enable) external onlyOwner {
isOperator[_operator] = _enable;
emit SetOperator(_operator, _enable);
}
function setMiningFactor(uint8 _miningFactor) external onlyOwner {
require(_miningFactor <= 100, "incorrect mining factor");
miningFactor = _miningFactor;
emit SetMiningFactor(_miningFactor);
}
function setTreasury(address _treasury) external onlyOwner {
treasury = _treasury;
emit SetTreasury(_treasury);
}
function setLonStaking(address _lonStaking) external onlyOwner {
require(Address.isContract(_lonStaking), "Lon staking is not a contract");
lonStaking = _lonStaking;
emit SetLonStaking(_lonStaking);
}
function setMiningTreasury(address _miningTreasury) external onlyOwner {
miningTreasury = _miningTreasury;
emit SetMiningTreasury(_miningTreasury);
}
function setFeeTokenRecipient(address _feeTokenRecipient) external onlyOwner {
feeTokenRecipient = _feeTokenRecipient;
emit SetFeeTokenRecipient(_feeTokenRecipient);
}
function recoverERC20(address _tokenAddress, uint256 _tokenAmount) external only_Operator_or_Owner {
IERC20(_tokenAddress).safeTransfer(owner, _tokenAmount);
emit Recovered(_tokenAddress, _tokenAmount);
}
function setBuybackInterval(uint32 _buyBackInterval) external only_Operator_or_Owner {
require(_buyBackInterval >= 3600, "invalid buyback interval");
buybackInterval = _buyBackInterval;
emit SetBuybackInterval(_buyBackInterval);
}
function setStrategyAddrs(uint256[] calldata _indexes, address[] calldata _strategyAddrs) external only_Operator_or_Owner {
require(_indexes.length == _strategyAddrs.length, "input not the same length");
for (uint256 i = 0; i < _indexes.length; i++) {
require(Address.isContract(_strategyAddrs[i]), "strategy is not a contract");
require(_indexes[i] <= numStrategyAddr, "index out of bound");
strategyAddrs[_indexes[i]] = _strategyAddrs[i];
if (_indexes[i] == numStrategyAddr) numStrategyAddr++;
emit SetStrategy(_indexes[i], _strategyAddrs[i]);
}
}
function setExchangeAddrs(uint256[] calldata _indexes, address[] calldata _exchangeAddrs) external only_Operator_or_Owner {
require(_indexes.length == _exchangeAddrs.length, "input not the same length");
for (uint256 i = 0; i < _indexes.length; i++) {
require(Address.isContract(_exchangeAddrs[i]), "exchange is not a contract");
require(_indexes[i] <= numExchangeAddr, "index out of bound");
exchangeAddrs[_indexes[i]] = _exchangeAddrs[i];
if (_indexes[i] == numExchangeAddr) numExchangeAddr++;
emit SetExchange(_indexes[i], _exchangeAddrs[i]);
}
}
function setFeeToken(
address _feeTokenAddr,
uint8 _exchangeIndex,
address[] calldata _path,
uint8 _LFactor,
uint8 _RFactor,
bool _enable,
uint256 _minBuy,
uint256 _maxBuy
) external only_Owner_or_Operator_or_Self {
require(Address.isContract(_feeTokenAddr), "fee token is not a contract");
require(Address.isContract(exchangeAddrs[_exchangeIndex]), "exchange is not a contract");
require(_path.length >= 2, "invalid swap path");
require(_path[_path.length - 1] == LON_TOKEN_ADDR, "output token must be LON");
require(_LFactor <= 100, "incorrect LFactor");
require(_RFactor <= 100, "incorrect RFactor");
require(_minBuy <= _maxBuy, "incorrect minBuy and maxBuy");
FeeToken storage feeToken = feeTokens[_feeTokenAddr];
feeToken.exchangeIndex = _exchangeIndex;
feeToken.path = _path;
feeToken.LFactor = _LFactor;
feeToken.RFactor = _RFactor;
if (feeToken.enable != _enable) {
feeToken.enable = _enable;
emit EnableFeeToken(_feeTokenAddr, _enable);
}
feeToken.minBuy = _minBuy;
feeToken.maxBuy = _maxBuy;
emit SetFeeToken(_feeTokenAddr, _exchangeIndex, _path, _LFactor, _RFactor, _minBuy, _maxBuy);
}
function setFeeTokens(
address[] memory _feeTokenAddr,
uint8[] memory _exchangeIndex,
address[][] memory _path,
uint8[] memory _LFactor,
uint8[] memory _RFactor,
bool[] memory _enable,
uint256[] memory _minBuy,
uint256[] memory _maxBuy
) external only_Operator_or_Owner {
uint256 inputLength = _feeTokenAddr.length;
require(
(_exchangeIndex.length == inputLength) &&
(_path.length == inputLength) &&
(_LFactor.length == inputLength) &&
(_RFactor.length == inputLength) &&
(_enable.length == inputLength) &&
(_minBuy.length == inputLength) &&
(_maxBuy.length == inputLength),
"input not the same length"
);
for (uint256 i = 0; i < inputLength; i++) {
try
this.setFeeToken(
_feeTokenAddr[i],
_exchangeIndex[i],
_path[i],
_LFactor[i],
_RFactor[i],
_enable[i],
_minBuy[i],
_maxBuy[i]
)
{
continue;
} catch Error(string memory reason) {
emit SetFeeTokenFailure(_feeTokenAddr[i], reason, bytes(""));
} catch (bytes memory lowLevelData) {
emit SetFeeTokenFailure(_feeTokenAddr[i], "", lowLevelData);
}
}
}
function enableFeeToken(address _feeTokenAddr, bool _enable) external only_Operator_or_Owner {
FeeToken storage feeToken = feeTokens[_feeTokenAddr];
if (feeToken.enable != _enable) {
feeToken.enable = _enable;
emit EnableFeeToken(_feeTokenAddr, _enable);
}
}
function enableFeeTokens(address[] calldata _feeTokenAddr, bool[] calldata _enable) external only_Operator_or_Owner {
require(_feeTokenAddr.length == _enable.length, "input not the same length");
for (uint256 i = 0; i < _feeTokenAddr.length; i++) {
FeeToken storage feeToken = feeTokens[_feeTokenAddr[i]];
if (feeToken.enable != _enable[i]) {
feeToken.enable = _enable[i];
emit EnableFeeToken(_feeTokenAddr[i], _enable[i]);
}
}
}
function _isAuthorized(address _account) internal view returns (bool) {
if ((isOperator[_account]) || (_account == owner)) return true;
else return false;
}
function _validate(
FeeToken memory _feeToken,
uint256 _amount
) internal view returns (uint256 amountFeeTokenToSwap, uint256 amountFeeTokenToTransfer) {
require(_amount > 0, "zero fee token amount");
if (!_isAuthorized(msg.sender)) {
require(_feeToken.enable, "fee token is not enabled");
}
amountFeeTokenToTransfer = _amount.mul(_feeToken.LFactor).div(100);
amountFeeTokenToSwap = _amount.sub(amountFeeTokenToTransfer);
if (amountFeeTokenToSwap > 0) {
require(amountFeeTokenToSwap >= _feeToken.minBuy, "amount less than min buy");
require(amountFeeTokenToSwap <= _feeToken.maxBuy, "amount greater than max buy");
require(block.timestamp > uint256(_feeToken.lastTimeBuyback).add(uint256(buybackInterval)), "already a buyback recently");
}
}
function _transferFeeToken(
address _feeTokenAddr,
address _transferTo,
uint256 _totalFeeTokenAmount
) internal {
address strategyAddr;
uint256 balanceInStrategy;
uint256 amountToTransferFrom;
uint256 cumulatedAmount;
for (uint256 i = 0; i < numStrategyAddr; i++) {
strategyAddr = strategyAddrs[i];
balanceInStrategy = IERC20(_feeTokenAddr).balanceOf(strategyAddr);
if (cumulatedAmount.add(balanceInStrategy) > _totalFeeTokenAmount) {
amountToTransferFrom = _totalFeeTokenAmount.sub(cumulatedAmount);
} else {
amountToTransferFrom = balanceInStrategy;
}
if (amountToTransferFrom == 0) continue;
IERC20(_feeTokenAddr).safeTransferFrom(strategyAddr, _transferTo, amountToTransferFrom);
cumulatedAmount = cumulatedAmount.add(amountToTransferFrom);
if (cumulatedAmount == _totalFeeTokenAmount) break;
}
require(cumulatedAmount == _totalFeeTokenAmount, "insufficient amount of fee tokens");
}
function _swap(
address _feeTokenAddr,
address _exchangeAddr,
address[] memory _path,
uint256 _amountFeeTokenToSwap,
uint256 _minLonAmount
) internal returns (uint256 swappedLonAmount) {
IERC20(_feeTokenAddr).safeApprove(_exchangeAddr, MAX_UINT);
IUniswapRouterV2 router = IUniswapRouterV2(_exchangeAddr);
uint256[] memory amounts = router.swapExactTokensForTokens(
_amountFeeTokenToSwap,
_minLonAmount,
_path,
address(this),
block.timestamp + 60
);
swappedLonAmount = amounts[_path.length - 1];
IERC20(_feeTokenAddr).safeApprove(_exchangeAddr, 0);
}
function _distributeLon(
FeeToken memory _feeToken,
uint256 swappedLonAmount
) internal {
uint256 treasuryAmount = swappedLonAmount.mul(_feeToken.RFactor).div(100);
if (treasuryAmount > 0) {
IERC20(LON_TOKEN_ADDR).safeTransfer(treasury, treasuryAmount);
}
uint256 lonStakingAmount = swappedLonAmount.sub(treasuryAmount);
if (lonStakingAmount > 0) {
IERC20(LON_TOKEN_ADDR).safeTransfer(lonStaking, lonStakingAmount);
}
emit DistributeLon(treasuryAmount, lonStakingAmount);
}
function _mintLon(uint256 swappedLonAmount) internal {
uint256 mintedAmount = swappedLonAmount.mul(uint256(miningFactor)).div(100);
if (mintedAmount > 0) {
ILon(LON_TOKEN_ADDR).mint(miningTreasury, mintedAmount);
emit MintLon(mintedAmount);
}
}
function _buyback(
address _feeTokenAddr,
FeeToken storage _feeToken,
address _exchangeAddr,
uint256 _amountFeeTokenToSwap,
uint256 _minLonAmount
) internal {
if (_amountFeeTokenToSwap > 0) {
uint256 swappedLonAmount =
_swap(_feeTokenAddr, _exchangeAddr, _feeToken.path, _amountFeeTokenToSwap, _minLonAmount);
_feeToken.lastTimeBuyback = uint32(block.timestamp);
emit BuyBack(
_feeTokenAddr,
_amountFeeTokenToSwap,
swappedLonAmount,
_feeToken.LFactor,
_feeToken.RFactor,
_feeToken.minBuy,
_feeToken.maxBuy
);
_distributeLon(_feeToken, swappedLonAmount);
_mintLon(swappedLonAmount);
}
}
function buyback(address _feeTokenAddr, uint256 _amount, uint256 _minLonAmount) external whenNotPaused only_EOA_or_Self {
FeeToken storage feeToken = feeTokens[_feeTokenAddr];
if (_feeTokenAddr == LON_TOKEN_ADDR) {
require(feeToken.enable, "fee token is not enabled");
require(_amount >= feeToken.minBuy, "amount less than min buy");
uint256 _lonToTreasury = _amount.mul(feeToken.RFactor).div(100);
uint256 _lonToStaking = _amount.sub(_lonToTreasury);
_transferFeeToken(LON_TOKEN_ADDR, treasury, _lonToTreasury);
_transferFeeToken(LON_TOKEN_ADDR, lonStaking, _lonToStaking);
emit DistributeLon(_lonToTreasury, _lonToStaking);
_mintLon(_amount);
feeToken.lastTimeBuyback = uint32(block.timestamp);
return;
}
(uint256 amountFeeTokenToSwap, uint256 amountFeeTokenToTransfer) = _validate(feeToken, _amount);
if (amountFeeTokenToSwap == 0) {
_transferFeeToken(_feeTokenAddr, feeTokenRecipient, amountFeeTokenToTransfer);
} else {
_transferFeeToken(_feeTokenAddr, address(this), _amount);
_buyback(_feeTokenAddr, feeToken, exchangeAddrs[feeToken.exchangeIndex], amountFeeTokenToSwap, _minLonAmount);
if (amountFeeTokenToTransfer > 0) {
IERC20(_feeTokenAddr).safeTransfer(feeTokenRecipient, amountFeeTokenToTransfer);
}
}
}
function batchBuyback(
address[] calldata _feeTokenAddr,
uint256[] calldata _amount,
uint256[] calldata _minLonAmount
) external whenNotPaused only_EOA {
uint256 inputLength = _feeTokenAddr.length;
require(
(_amount.length == inputLength) &&
(_minLonAmount.length == inputLength),
"input not the same length"
);
for (uint256 i = 0; i < inputLength; i++) {
try this.buyback(_feeTokenAddr[i], _amount[i], _minLonAmount[i]) {
continue;
} catch Error(string memory reason) {
emit BuyBackFailure(_feeTokenAddr[i], _amount[i], reason, bytes(""));
} catch (bytes memory lowLevelData) {
emit BuyBackFailure(_feeTokenAddr[i], _amount[i], "", lowLevelData);
}
}
}
}
文件 11 的 12: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 的 12: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/implements/stage2/RewardDistributor.sol": "RewardDistributor"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_LON_TOKEN_ADDR","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"},{"internalType":"uint32","name":"_buyBackInterval","type":"uint32"},{"internalType":"uint8","name":"_miningFactor","type":"uint8"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_lonStaking","type":"address"},{"internalType":"address","name":"_miningTreasury","type":"address"},{"internalType":"address","name":"_feeTokenRecipient","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swappedLonAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"LFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"RFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minBuy","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxBuy","type":"uint256"}],"name":"BuyBack","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeTokenAmount","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"},{"indexed":false,"internalType":"bytes","name":"lowLevelData","type":"bytes"}],"name":"BuyBackFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"treasuryAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lonStakingAmount","type":"uint256"}],"name":"DistributeLon","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeToken","type":"address"},{"indexed":false,"internalType":"bool","name":"enable","type":"bool"}],"name":"EnableFeeToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"mintedAmount","type":"uint256"}],"name":"MintLon","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"interval","type":"uint256"}],"name":"SetBuybackInterval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"exchange","type":"address"}],"name":"SetExchange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"exchangeIndex","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"path","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"LFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"RFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minBuy","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxBuy","type":"uint256"}],"name":"SetFeeToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeToken","type":"address"},{"indexed":false,"internalType":"string","name":"reason","type":"string"},{"indexed":false,"internalType":"bytes","name":"lowLevelData","type":"bytes"}],"name":"SetFeeTokenFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeTokenRecipient","type":"address"}],"name":"SetFeeTokenRecipient","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lonStaking","type":"address"}],"name":"SetLonStaking","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"miningFactor","type":"uint8"}],"name":"SetMiningFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"miningTreasury","type":"address"}],"name":"SetMiningTreasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"enable","type":"bool"}],"name":"SetOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"strategy","type":"address"}],"name":"SetStrategy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"treasury","type":"address"}],"name":"SetTreasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"LON_TOKEN_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_feeTokenAddr","type":"address[]"},{"internalType":"uint256[]","name":"_amount","type":"uint256[]"},{"internalType":"uint256[]","name":"_minLonAmount","type":"uint256[]"}],"name":"batchBuyback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTokenAddr","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minLonAmount","type":"uint256"}],"name":"buyback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buybackInterval","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTokenAddr","type":"address"},{"internalType":"bool","name":"_enable","type":"bool"}],"name":"enableFeeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_feeTokenAddr","type":"address[]"},{"internalType":"bool[]","name":"_enable","type":"bool[]"}],"name":"enableFeeTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"exchangeAddrs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTokenRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"feeTokens","outputs":[{"internalType":"uint8","name":"exchangeIndex","type":"uint8"},{"internalType":"uint8","name":"LFactor","type":"uint8"},{"internalType":"uint8","name":"RFactor","type":"uint8"},{"internalType":"uint32","name":"lastTimeBuyback","type":"uint32"},{"internalType":"bool","name":"enable","type":"bool"},{"internalType":"uint256","name":"minBuy","type":"uint256"},{"internalType":"uint256","name":"maxBuy","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTokenAddr","type":"address"}],"name":"getFeeTokenPath","outputs":[{"internalType":"address[]","name":"path","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lonStaking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miningFactor","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miningTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numExchangeAddr","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numStrategyAddr","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_buyBackInterval","type":"uint32"}],"name":"setBuybackInterval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"},{"internalType":"address[]","name":"_exchangeAddrs","type":"address[]"}],"name":"setExchangeAddrs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTokenAddr","type":"address"},{"internalType":"uint8","name":"_exchangeIndex","type":"uint8"},{"internalType":"address[]","name":"_path","type":"address[]"},{"internalType":"uint8","name":"_LFactor","type":"uint8"},{"internalType":"uint8","name":"_RFactor","type":"uint8"},{"internalType":"bool","name":"_enable","type":"bool"},{"internalType":"uint256","name":"_minBuy","type":"uint256"},{"internalType":"uint256","name":"_maxBuy","type":"uint256"}],"name":"setFeeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTokenRecipient","type":"address"}],"name":"setFeeTokenRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_feeTokenAddr","type":"address[]"},{"internalType":"uint8[]","name":"_exchangeIndex","type":"uint8[]"},{"internalType":"address[][]","name":"_path","type":"address[][]"},{"internalType":"uint8[]","name":"_LFactor","type":"uint8[]"},{"internalType":"uint8[]","name":"_RFactor","type":"uint8[]"},{"internalType":"bool[]","name":"_enable","type":"bool[]"},{"internalType":"uint256[]","name":"_minBuy","type":"uint256[]"},{"internalType":"uint256[]","name":"_maxBuy","type":"uint256[]"}],"name":"setFeeTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lonStaking","type":"address"}],"name":"setLonStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_miningFactor","type":"uint8"}],"name":"setMiningFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_miningTreasury","type":"address"}],"name":"setMiningTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_enable","type":"bool"}],"name":"setOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"},{"internalType":"address[]","name":"_strategyAddrs","type":"address[]"}],"name":"setStrategyAddrs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"strategyAddrs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]