编译器
0.8.27+commit.40a35a09
文件 1 的 14:Address.sol
pragma solidity ^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.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this;
return msg.data;
}
}
文件 3 的 14:ERC20.sol
pragma solidity ^0.8.0;
import './IERC20.sol';
import './IERC20Metadata.sol';
import './Context.sol';
contract ERC20 is Context,IERC20,IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 4 的 14:IDeployMiningPoolParams.sol
pragma solidity ^0.8.0;
interface IDeployMiningPoolParams {
struct DeployMiningPoolParams {
address factory;
address creator;
address pair;
address stableToken;
address mintToken;
uint epochReleaseRate;
uint epochBlocks;
uint startBlock;
uint sellUserRate;
uint sellBuybackRate;
uint32 rateForLPH;
uint32 rateForTH;
uint32 rateForTS;
uint32 rateForDev;
}
}
文件 5 的 14:IERC20.sol
pragma solidity ^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);
}
文件 6 的 14:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 7 的 14:IPoolFactory.sol
pragma solidity ^0.8.0;
import './IDeployMiningPoolParams.sol';
interface IPoolFactory is IDeployMiningPoolParams {
function deployParams() external view returns(DeployMiningPoolParams memory paras);
function factoryOwner() external view returns(address);
function swapRouter() external view returns(address);
function miningPoolsLength() external view returns(uint256);
function miningPools(uint256 index) external view returns(address);
function pair2miningPool(address pair) external view returns(address);
}
文件 8 的 14:ISwapRouter.sol
pragma solidity ^0.8.0;
interface ISwapRouter {
function createPair(
address mintToken,
uint256 mintTokenAmount,
address stableToken,
uint256 stableTokenAmount,
uint256 sellBurnRate,
uint256 sellStopBurnSupply
) external;
function setPoolFactory(address _poolFactory) external;
function pairFor(address tokenA, address tokenB) external view returns (address pair);
function factory() external view returns(address);
function WETH() external view returns(address);
function baseTokenOf(address pair) external view returns(address);
function sellBurnRateOf(address pair) external view returns(uint);
function sellStopBurnSupplyOf(address pair) external view returns(uint);
function isWhiteList(address pair,address account) external view returns(bool);
function setWhiteList(address pair,address account,bool status) external;
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external;
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external;
function getAmountsOut(uint256 amountIn, address[] memory path) external view returns (uint256[] memory);
}
文件 9 的 14:IWETH.sol
pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint value) external returns (bool);
function withdraw(uint) external;
}
文件 10 的 14:MerkleProof.sol
pragma solidity ^0.8.0;
library MerkleProof {
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}
文件 11 的 14:MiningPool.sol
pragma solidity ^0.8.4;
import './libs/Utils.sol';
import './libs/IWETH.sol';
import './libs/ISwapRouter.sol';
import './libs/IPoolFactory.sol';
import './libs/IDeployMiningPoolParams.sol';
import './libs/SafeERC20.sol';
import './libs/SafeMath.sol';
import './libs/ERC20.sol';
contract MiningPool is IDeployMiningPoolParams {
using SafeMath for uint256;
using SafeERC20 for IERC20;
uint public constant RATE_PERCISION = 10000;
uint public constant UNIT_PERCISION = 1e12;
bool public migrateDiscard;
address public dev;
uint256 public devClaimedMintToken;
uint256 public devClaimedStableToken;
address public migrator;
address public creator;
address public rooter;
uint256 public epochReleaseRate;
uint256 public epoch;
address public immutable factory;
address public immutable pair;
address public immutable stableToken;
address public immutable mintToken;
uint256 public immutable epochBlocks;
uint256 public immutable startBlock;
uint256 public totalLPH;
uint256 public totalInvested;
uint256 public usersBalance;
uint256 public usersUnitAcc;
uint256 public sellUserRate;
uint256 public sellBuybackRate;
struct User {
address leader;
uint256 level;
uint256 lph;
uint256 investedAcc;
uint256 rewardAcc;
uint256 referencesRewardAcc;
uint256 rewardDebt;
}
mapping(address => address[]) public references;
mapping(address => uint256[2]) public claimedRewards;
mapping(uint256 => bytes32) public merkleRoots;
mapping(address => User) public users;
uint256[4] public assignRewardsAcc;
uint256[4] public assignRewardsRate;
address[] public accounts;
event ClaimTHTSRewards(address account, address token, uint thRewards, uint tsRewards, uint blockTime);
event ReleaseRewards(uint removedLpAmount, uint remainLpAmount, uint rewardAmount, uint blockTime, uint epoch);
event Buy(address account, uint amountIn, uint lph, uint blockTime);
event Harvested(address account, uint amount, uint blockTime);
event NewUser(address account, address leader);
modifier onlyCreator() {
require(msg.sender == creator, "caller must be creator");
_;
}
modifier onlyFactoryOwner() {
require(msg.sender == IPoolFactory(factory).factoryOwner(), "caller must be creator");
_;
}
modifier onlyRooter() {
require(msg.sender == rooter, "Caller is not rooter");
_;
}
constructor() {
DeployMiningPoolParams memory params = IPoolFactory(msg.sender).deployParams();
factory = params.factory;
creator = tx.origin;
rooter = params.creator;
pair = params.pair;
stableToken = params.stableToken;
mintToken = params.mintToken;
epochReleaseRate = params.epochReleaseRate;
epochBlocks = params.epochBlocks;
startBlock = params.startBlock;
sellUserRate = params.sellUserRate;
sellBuybackRate = params.sellBuybackRate;
dev = tx.origin;
assignRewardsRate[0] = params.rateForLPH;
assignRewardsRate[1] = uint256(params.rateForTH);
assignRewardsRate[2] = uint256(params.rateForTS);
assignRewardsRate[3] = uint256(params.rateForDev);
address router = IPoolFactory(msg.sender).swapRouter();
IERC20(params.stableToken).safeApprove(router,type(uint256).max);
IERC20(params.mintToken).safeApprove(router,type(uint256).max);
IERC20(params.pair).safeApprove(router,type(uint256).max);
}
function setRooter(address newRooter) public onlyFactoryOwner {
require(newRooter != address(0), "Invalid newRooter");
rooter = newRooter;
}
function setMerkleRoot(uint256 _epoch, bytes32 merkleRoot) public onlyRooter {
merkleRoots[_epoch] = merkleRoot;
}
function buy(uint amount, address leader) public {
require(amount == 0 || amount >= 20 * 10 ** ERC20(stableToken).decimals(), "Invalid amount #1");
buy2(amount, leader, msg.sender);
}
function buy2(uint amount, address leader, address receiver) public {
require(amount == 0 || amount >= 10 ** ERC20(stableToken).decimals(), "Invalid amount #2");
buy3(amount, leader, receiver);
}
function buy3(uint amount, address leader, address receiver) internal {
User storage user = users[receiver];
if(user.leader == address(0) && accounts.length == 0){
require(amount > 0, "Invalid amount #3");
require(receiver == creator, "The first user must be creator");
accounts.push(receiver);
user.leader = address(1);
user.level = 1;
emit NewUser(receiver, address(1));
}else if(user.leader == address(0)){
require(users[leader].lph > 0, "Invalid leader");
require(amount > 0, "Invalid amount #4");
user.level = users[leader].level.add(1);
user.leader = leader;
accounts.push(receiver);
references[leader].push(receiver);
emit NewUser(receiver, leader);
}
if (user.lph > 0){
uint256 pending = user.lph.mul(usersUnitAcc).div(UNIT_PERCISION) - user.rewardDebt;
if (pending > 0 && usersBalance >= pending) {
usersBalance = usersBalance.sub(pending);
IERC20(mintToken).safeTransfer(receiver, pending);
user.rewardAcc = user.rewardAcc.add(pending);
users[user.leader].referencesRewardAcc = users[user.leader].referencesRewardAcc.add(pending);
emit Harvested(receiver, pending, block.timestamp);
}
}
if (amount > 0) {
uint receivedAmount = _transferFrom(msg.sender, stableToken, amount);
_addLiquidity(receivedAmount);
uint256 lph = getLPH(receivedAmount);
user.lph = user.lph.add(lph);
totalLPH = totalLPH.add(lph);
totalInvested = totalInvested.add(receivedAmount);
user.investedAcc = user.investedAcc.add(receivedAmount);
emit Buy(receiver, receivedAmount, lph, block.timestamp);
}
users[receiver].rewardDebt = usersUnitAcc.mul(users[receiver].lph).div(UNIT_PERCISION);
}
function sell(uint amount) external {
require(amount > 0, "Invalid amount");
uint receivedAmount = _transferFrom(msg.sender, mintToken, amount);
ISwapRouter router = ISwapRouter(IPoolFactory(factory).swapRouter());
address[] memory path = new address[](2);
path[0] = mintToken;
path[1] = stableToken;
uint balanceBefore = IERC20(stableToken).balanceOf(address(this));
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(receivedAmount, 1, path, address(this), type(uint256).max);
uint swapedAmount = IERC20(stableToken).balanceOf(address(this)).sub(balanceBefore);
IERC20(stableToken).safeTransfer(msg.sender, swapedAmount.mul(sellUserRate) / RATE_PERCISION);
buy3(swapedAmount.mul(sellBuybackRate) / RATE_PERCISION, address(0), msg.sender);
}
function claimLPHRewards() external {
buy(0, address(0));
}
function claimTHTSRewards(uint _epoch, uint thRewardAcc, uint tsRewardAcc, bytes32[] calldata merkleProof) external {
require(Utils.verify(msg.sender, thRewardAcc, tsRewardAcc, merkleRoots[_epoch], merkleProof), "Validation failure");
require(merkleRoots[_epoch] != bytes32(0), "Waiting for `merkleRoots[epoch]` to be set.");
require(thRewardAcc >= claimedRewards[msg.sender][0], "Invalid thRewardAcc");
require(tsRewardAcc >= claimedRewards[msg.sender][1], "Invalid tsRewardAcc");
require(users[msg.sender].lph > 0, "account not invested");
uint256 rewards0 = thRewardAcc.sub(claimedRewards[msg.sender][0]);
uint256 rewards1 = tsRewardAcc.sub(claimedRewards[msg.sender][1]);
uint256 totalRewards = rewards0.add(rewards1);
require(IERC20(mintToken).balanceOf(address(this)).sub(usersBalance) >= totalRewards, "Insufficient balance");
claimedRewards[msg.sender][0] = thRewardAcc;
claimedRewards[msg.sender][1] = tsRewardAcc;
IERC20(mintToken).safeTransfer(msg.sender, totalRewards);
emit ClaimTHTSRewards(msg.sender, mintToken, rewards0, rewards1, block.timestamp);
}
function releaseCheck() external view returns (uint256 curEpochIndex, bool canRelease) {
curEpochIndex = epoch;
canRelease = block.number > startBlock && (block.number.sub(startBlock + epochBlocks.mul(epoch))) > epochBlocks;
}
function releaseRewards() external {
uint rateForLPH = assignRewardsRate[0];
uint rateForTH = assignRewardsRate[1];
uint rateForTS = assignRewardsRate[2];
uint rateForDev = assignRewardsRate[3];
require(rateForLPH + rateForTH + rateForTS + rateForDev == 100, "Invalid assignRewardsRate");
require(block.number > startBlock && (block.number.sub(startBlock + epochBlocks.mul(epoch))) > epochBlocks, "Disable release future rewards.");
uint lpAmount = IERC20(pair).balanceOf(address(this)).mul(epochReleaseRate) / RATE_PERCISION;
uint balanceBefore = IERC20(mintToken).balanceOf(address(this));
_removeLiquidityForRewards(lpAmount);
uint rewardAmount = IERC20(mintToken).balanceOf(address(this)).sub(balanceBefore);
require(rewardAmount > 0, "Invalid rewardAmount");
uint rewardForLPH = rewardAmount.mul(rateForLPH).div(100);
usersUnitAcc = usersUnitAcc.add(rewardForLPH.mul(UNIT_PERCISION).div(totalLPH));
usersBalance = usersBalance.add(rewardForLPH);
uint rewardForDev = rewardAmount.mul(rateForDev).div(100);
assignRewardsAcc[0] = assignRewardsAcc[0].add(rewardForLPH);
assignRewardsAcc[1] = assignRewardsAcc[1].add(rewardAmount.mul(rateForTH).div(100));
assignRewardsAcc[2] = assignRewardsAcc[2].add(rewardAmount.mul(rateForTS).div(100));
assignRewardsAcc[3] = assignRewardsAcc[3].add(rewardForDev);
epoch = epoch.add(1);
emit ReleaseRewards(lpAmount, IERC20(pair).balanceOf(address(this)), rewardAmount, block.timestamp, epoch);
}
function setDev(address _dev) public onlyCreator {
dev = _dev;
}
function devClaimRewardsFromRelease(uint256 amount) public {
require(msg.sender == dev, "caller must be dev");
require(amount > 0 && amount <= assignRewardsAcc[3].sub(devClaimedMintToken), "Invalid amount");
devClaimedMintToken = devClaimedMintToken.add(amount);
IERC20(mintToken).safeTransfer(dev, amount);
}
function devClaimRewardsFromSale(uint256 amount) public {
require(msg.sender == dev, "caller must be dev");
require(amount > 0 && amount <= IERC20(stableToken).balanceOf(address(this)), "Invalid amount");
devClaimedStableToken = devClaimedStableToken.add(amount);
IERC20(stableToken).safeTransfer(dev, amount);
}
function _transferFrom(address from,address token,uint amount) internal returns(uint receivedAmount){
uint beforeBalance = IERC20(token).balanceOf(address(this));
IERC20(token).safeTransferFrom(from, address(this), amount);
return IERC20(token).balanceOf(address(this)).sub(beforeBalance);
}
function _addLiquidity(uint _amount) internal {
uint amountHalf = _amount / 2;
ISwapRouter router = ISwapRouter(IPoolFactory(factory).swapRouter());
address[] memory path = new address[](2);
path[0] = stableToken;
path[1] = mintToken;
uint balanceBefore = IERC20(mintToken).balanceOf(address(this));
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(amountHalf,1,path,address(this),type(uint256).max);
uint swapedAmount = IERC20(mintToken).balanceOf(address(this)).sub(balanceBefore);
router.addLiquidity(stableToken, mintToken, amountHalf, swapedAmount, 1, 1, address(this), type(uint256).max);
}
function _removeLiquidityForRewards(uint lpAmount) internal {
if(lpAmount == 0){
return;
}
ISwapRouter router = ISwapRouter(IPoolFactory(factory).swapRouter());
router.removeLiquidity(stableToken, mintToken, lpAmount, 1, 1, address(this), type(uint256).max);
address[] memory path = new address[](2);
path[0] = stableToken;
path[1] = mintToken;
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(IERC20(path[0]).balanceOf(address(this)),1,path,address(this),type(uint256).max);
}
function transferCreator(address newCreator) external onlyCreator {
require(newCreator != address(0),"new creator can not be address 0");
creator = newCreator;
}
function getClaimedRewards(address account) external view returns (uint256[2] memory) {
return claimedRewards[account];
}
function getAssignRewardsAcc() external view returns (uint256[4] memory) {
return assignRewardsAcc;
}
function getReferences(address leader, uint startPos) external view
returns (uint length, address[] memory data) {
address[] memory refs = references[leader];
length = uint(refs.length);
if(startPos >= length) {
return (length, new address[](0));
}
uint256 endPos = startPos + 10;
if(endPos > length){
endPos = length;
}
data = new address[](endPos - startPos);
for(uint i = 0; i < 10 && (i+startPos) < endPos; i++) {
data[i] = refs[i+startPos];
}
}
function accountsCount() external view returns (uint) {
return accounts.length;
}
function referencesCount(address account) external view returns (uint256) {
return references[account].length;
}
function getLPH(uint256 amount) public view returns(uint256) {
uint256 epochs = startBlock > block.number ? 0 : (block.number - startBlock) / epochBlocks;
uint256 rise = Utils.lphRise(epochs);
return amount.mul(rise).div(10 ** ERC20(stableToken).decimals() * 100);
}
function getLPHRewardAcc(address account) external view returns (uint256) {
User storage user = users[account];
if (user.lph == 0){
return 0;
}
return user.lph.mul(usersUnitAcc).div(UNIT_PERCISION).sub(user.rewardDebt).add(user.rewardAcc);
}
}
文件 12 的 14:SafeERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./Address.sol";
library SafeERC20 {
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) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_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");
}
}
}
文件 13 的 14:SafeMath.sol
pragma solidity >=0.5.16;
library SafeMath {
uint256 constant WAD = 10 ** 18;
uint256 constant RAY = 10 ** 27;
function wad() public pure returns (uint256) {
return WAD;
}
function ray() public pure returns (uint256) {
return RAY;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a <= b ? a : b;
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function sqrt(uint256 a) internal pure returns (uint256 b) {
if (a > 3) {
b = a;
uint256 x = a / 2 + 1;
while (x < b) {
b = x;
x = (a / x + x) / 2;
}
} else if (a != 0) {
b = 1;
}
}
function wmul(uint256 a, uint256 b) internal pure returns (uint256) {
return mul(a, b) / WAD;
}
function wmulRound(uint256 a, uint256 b) internal pure returns (uint256) {
return add(mul(a, b), WAD / 2) / WAD;
}
function rmul(uint256 a, uint256 b) internal pure returns (uint256) {
return mul(a, b) / RAY;
}
function rmulRound(uint256 a, uint256 b) internal pure returns (uint256) {
return add(mul(a, b), RAY / 2) / RAY;
}
function wdiv(uint256 a, uint256 b) internal pure returns (uint256) {
return div(mul(a, WAD), b);
}
function wdivRound(uint256 a, uint256 b) internal pure returns (uint256) {
return add(mul(a, WAD), b / 2) / b;
}
function rdiv(uint256 a, uint256 b) internal pure returns (uint256) {
return div(mul(a, RAY), b);
}
function rdivRound(uint256 a, uint256 b) internal pure returns (uint256) {
return add(mul(a, RAY), b / 2) / b;
}
function wpow(uint256 x, uint256 n) internal pure returns (uint256) {
uint256 result = WAD;
while (n > 0) {
if (n % 2 != 0) {
result = wmul(result, x);
}
x = wmul(x, x);
n /= 2;
}
return result;
}
function rpow(uint256 x, uint256 n) internal pure returns (uint256) {
uint256 result = RAY;
while (n > 0) {
if (n % 2 != 0) {
result = rmul(result, x);
}
x = rmul(x, x);
n /= 2;
}
return result;
}
}
文件 14 的 14:Utils.sol
pragma solidity ^0.8.0;
import './MerkleProof.sol';
library Utils {
function lphRise(uint256 _epoch) internal pure returns(uint256) {
if(_epoch == 0){
return 10000;
}
uint256 base = 10100;
uint256 result = 1;
while (_epoch > 0) {
if (_epoch % 2 == 1) {
if(result > 1){
result = result * base / 10000;
}else{
result = result * base;
}
}
base = base * base / 10000;
_epoch = _epoch / 2;
}
return result;
}
function verify(address account, uint256 thRewardAcc, uint256 tsRewardAcc, bytes32 merkleRoot, bytes32[] calldata merkleProof) internal pure returns(bool) {
bytes32 node = keccak256(abi.encodePacked(account, thRewardAcc, tsRewardAcc));
return MerkleProof.verifyCalldata(merkleProof, merkleRoot, node);
}
}
{
"compilationTarget": {
"contracts/MiningPool.sol": "MiningPool"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lph","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockTime","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"thRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tsRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockTime","type":"uint256"}],"name":"ClaimTHTSRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockTime","type":"uint256"}],"name":"Harvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"leader","type":"address"}],"name":"NewUser","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"removedLpAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainLpAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"ReleaseRewards","type":"event"},{"inputs":[],"name":"RATE_PERCISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNIT_PERCISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"accounts","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accountsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"assignRewardsAcc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"assignRewardsRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"leader","type":"address"}],"name":"buy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"leader","type":"address"},{"internalType":"address","name":"receiver","type":"address"}],"name":"buy2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimLPHRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_epoch","type":"uint256"},{"internalType":"uint256","name":"thRewardAcc","type":"uint256"},{"internalType":"uint256","name":"tsRewardAcc","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"claimTHTSRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"creator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dev","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"devClaimRewardsFromRelease","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"devClaimRewardsFromSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devClaimedMintToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"devClaimedStableToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochReleaseRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAssignRewardsAcc","outputs":[{"internalType":"uint256[4]","name":"","type":"uint256[4]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getClaimedRewards","outputs":[{"internalType":"uint256[2]","name":"","type":"uint256[2]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getLPH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getLPHRewardAcc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"leader","type":"address"},{"internalType":"uint256","name":"startPos","type":"uint256"}],"name":"getReferences","outputs":[{"internalType":"uint256","name":"length","type":"uint256"},{"internalType":"address[]","name":"data","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"merkleRoots","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrateDiscard","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"references","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"referencesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"releaseCheck","outputs":[{"internalType":"uint256","name":"curEpochIndex","type":"uint256"},{"internalType":"bool","name":"canRelease","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"releaseRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rooter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sell","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sellBuybackRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellUserRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_dev","type":"address"}],"name":"setDev","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_epoch","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRooter","type":"address"}],"name":"setRooter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stableToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalInvested","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLPH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newCreator","type":"address"}],"name":"transferCreator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"users","outputs":[{"internalType":"address","name":"leader","type":"address"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"uint256","name":"lph","type":"uint256"},{"internalType":"uint256","name":"investedAcc","type":"uint256"},{"internalType":"uint256","name":"rewardAcc","type":"uint256"},{"internalType":"uint256","name":"referencesRewardAcc","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usersBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usersUnitAcc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]