文件 1 的 15: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 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
) internal 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 的 15: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;
}
}
文件 3 的 15:FunPool.sol
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "../../periphery/interfaces/IWETH.sol";
import '../../lib/utils/TransferHelper.sol';
import "../interface/IFunPool.sol";
import "../interface/IFunFactory.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "../interface/IFunToken.sol";
contract FunPool is IFunPool, Pausable, Ownable {
using SafeERC20 for IERC20;
using SafeMath for uint256;
address public override WETH;
mapping(address => uint) private locked;
address public operatorAddress;
mapping(address => address) public token1Addresses;
mapping(address => uint256) private _liquidity0;
mapping(address => uint256) private _liquidity1;
mapping(address => uint256) private _liquidity1Virtual;
mapping(address => uint256) public swapLimits;
mapping(address => uint256) public fees;
mapping(address => uint8) public status;
uint256 constant private X = 1E6;
uint256 public feeRate = 1E4;
address public funFactory;
address public uniSwapV2Router02;
constructor(address _WETH, address _funFactory, address _uniSwapV2Router02){
WETH = _WETH;
funFactory = _funFactory;
operatorAddress = msg.sender;
uniSwapV2Router02 = _uniSwapV2Router02;
}
receive() external payable {
assert(msg.sender == WETH);
}
modifier lock(address token0) {
require(locked[token0] == 0, 'LOCKED');
locked[token0] = 1;
_;
locked[token0] = 0;
}
modifier statusCheck(address token0){
require(status[token0] == 1, 'Error: status != 1');
_;
}
modifier onlyOperator(){
require(msg.sender == operatorAddress, 'caller is not the operator');
_;
}
function setOperatorAddress(address newAddress) onlyOwner public {
require(newAddress != address(0), 'Error newAddress');
operatorAddress = newAddress;
}
function emergencyWithdrawEther() public onlyOwner {
payable(msg.sender).transfer(address(this).balance);
}
function emergencyWithdrawErc20(address _tokenAddress) public onlyOwner {
IERC20 token = IERC20(_tokenAddress);
token.safeTransfer(msg.sender, token.balanceOf(address(this)));
}
function setFeeRate(uint256 _feeRate) onlyOwner public {
require(_feeRate < X, 'Error: _feeRate >= X');
feeRate = _feeRate;
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function addLiquidity(address token0,
address token1,
uint256 liquidity0,
uint256 liquidity1,
uint256 swapLimit,
uint256 fee) override virtual public {
require(status[token0] == 0,'Error: status != 0');
require(msg.sender == funFactory, 'No authority');
require(token0 != address(0), 'token0 zero');
require(token1Addresses[token0] == address(0), 'Added');
require(liquidity0 >= 20 && liquidity1 >= 20, 'liquidity low');
require(_liquidity0[token0] == 0 && _liquidity1[token0] == 0, 'liquidity added');
_liquidity0[token0] = liquidity0;
_liquidity1[token0] = _liquidity1Virtual[token0] = liquidity1;
if (token1 == address(0)) token1 = WETH;
token1Addresses[token0] = token1;
swapLimits[token0] = swapLimit;
fees[token0] = fee;
status[token0] = 1;
emit LiquidityAdded(token0, token1, liquidity0, liquidity1);
emit Status(token0, token1, 1);
}
function getLiquidity(address token0) override virtual public view returns (uint256 liquidity0, uint256 liquidity1){
liquidity0 = _liquidity0[token0];
liquidity1 = _liquidity1[token0];
}
function tokenPrice(address token0) override virtual public view returns (uint256){
require(_liquidity0[token0] > 0 && _liquidity1[token0] > 0, 'Liquidity 0');
return _liquidity1[token0] * 1E18 / _liquidity0[token0];
}
function buyGain(address token0, uint256 cost) override virtual public view returns (uint256){
(uint256 amount,,,) = _buyGain(token0, cost);
return amount;
}
function _buyGain(address token0, uint256 cost) internal virtual view returns (uint256 amount, uint256 price, uint256 fee, uint256 k){
(uint256 liquidity0, uint256 liquidity1) = getLiquidity(token0);
require(liquidity0 > 0, 'Insufficient liquidity');
require(cost > 0, 'Overflow');
k = liquidity0 * liquidity1;
fee = cost * feeRate / X;
amount = liquidity0 - k / (liquidity1 + (cost - fee));
price = (cost - fee) * 1E18 / amount;
require(amount > 0 && amount < liquidity0, 'Insufficient liquidity');
}
function buyExactGain(address token0, uint256 gain) override virtual public view returns (uint256){
(uint256 cost,,,) = _buyExactGain(token0, gain);
return cost;
}
function _buyExactGain(address token0, uint256 gain) internal virtual view returns (uint256 cost, uint256 price, uint256 fee, uint256 k){
(uint256 liquidity0, uint256 liquidity1) = getLiquidity(token0);
require(liquidity0 > 0, 'Insufficient liquidity');
require(gain > 0, 'Overflow');
k = liquidity0 * liquidity1;
cost = k / (liquidity0 - gain) - liquidity1 + 1;
cost = cost * X / (X - feeRate);
fee = cost * feeRate / X;
price = (cost - fee) * 1E18 / gain;
require(cost > 0 && cost < liquidity1, 'Insufficient liquidity');
}
function buy(address token0, address to, uint256 cost, uint256 amountOutMin) whenNotPaused() override virtual external payable {
address token1 = token1Addresses[token0];
require(token1 != address(0), 'Not found!');
if (token1 == WETH) {
if (msg.value > 0) cost = msg.value;
else if (cost > 0) {
IERC20(WETH).transferFrom(msg.sender, address(this), cost);
IWETH(WETH).withdraw(cost);
}
}
_buy(token0, token1, to, amountOutMin, cost);
endCheck(token0, token1);
}
function _buy(address token0, address token1, address to, uint256 amountOutMin, uint256 cost) statusCheck(token0) lock(token0) internal virtual returns (uint256) {
(uint256 amount,,uint256 fee,) = _buyGain(token0, cost);
require(amount >= amountOutMin, 'LT amountOutMin');
IERC20(token0).safeTransfer(to, amount);
_liquidity0[token0] -= amount;
_liquidity1[token0] += (cost - fee);
if (token1 == WETH) {
IWETH(WETH).deposit{value: (cost - fee)}();
if (fee > 0) TransferHelper.safeTransferETH(IFunFactory(funFactory).feeTo(), fee);
} else {
IERC20(token1).safeTransferFrom(msg.sender, address(this), cost);
if (fee > 0) IERC20(token1).safeTransfer(IFunFactory(funFactory).feeTo(), fee);
}
uint256 newPrice = _liquidity1[token0] * 1E18 / _liquidity0[token0];
emit Buy(to, token0, token1, newPrice, cost, amount, fee, block.timestamp);
return amount;
}
function buyCostForExactGain(address token0, address to, uint256 gain, uint256 amountInMax) whenNotPaused() override virtual external payable {
address token1 = token1Addresses[token0];
require(token1 != address(0), 'Not found!');
if (token1 == WETH) {
if (msg.value > 0) amountInMax = msg.value;
else if (amountInMax > 0) {
IERC20(WETH).transferFrom(msg.sender, address(this), amountInMax);
IWETH(WETH).withdraw(amountInMax);
}
}
_buyCostForExactGain(token0, token1, to, gain, amountInMax);
endCheck(token0, token1);
}
function _buyCostForExactGain(address token0, address token1, address to, uint256 gain, uint256 amountInMax) statusCheck(token0) lock(token0) internal virtual returns (uint256) {
(uint256 cost,,uint256 fee,) = _buyExactGain(token0, gain);
require(cost <= amountInMax, 'GT amountInMax');
IERC20(token0).safeTransfer(to, gain);
_liquidity0[token0] -= gain;
_liquidity1[token0] += (cost - fee);
if (token1 == WETH) {
IWETH(WETH).deposit{value: (cost - fee)}();
if (fee > 0) TransferHelper.safeTransferETH(IFunFactory(funFactory).feeTo(), fee);
if (amountInMax > cost) TransferHelper.safeTransferETH(msg.sender, amountInMax - cost);
} else {
IERC20(token1).safeTransferFrom(msg.sender, address(this), amountInMax);
if (fee > 0) IERC20(token1).safeTransfer(IFunFactory(funFactory).feeTo(), fee);
if (amountInMax > cost) IERC20(token1).safeTransfer(msg.sender, amountInMax - cost);
}
uint256 newPrice = _liquidity1[token0] * 1E18 / _liquidity0[token0];
emit Buy(to, token0, token1, newPrice, cost, gain, fee, block.timestamp);
return cost;
}
function sellGain(address token0, uint256 amount) override virtual public view returns (uint256){
(uint256 gain,,,) = _sellGain(token0, amount);
return gain;
}
function _sellGain(address token0, uint256 amount) internal virtual view returns (uint256 gain, uint256 price, uint256 fee, uint256 k){
(uint256 liquidity0, uint256 liquidity1) = getLiquidity(token0);
require(liquidity0 > 0, 'Insufficient liquidity');
require(amount > 0, 'Overflow');
k = liquidity0 * liquidity1;
gain = liquidity1 - k / (liquidity0 + amount);
fee = gain * feeRate / X;
gain = gain * (X - feeRate) / X;
price = gain * 1E18 / amount;
require(gain > 0 && gain < liquidity1, 'Insufficient liquidity');
}
function sellExactGain(address token0, uint256 gain) override virtual public view returns (uint256){
(uint256 amount,,,) = _sellExactGain(token0, gain);
return amount;
}
function _sellExactGain(address token0, uint256 gain) internal virtual view returns (uint256 amount, uint256 price, uint256 fee, uint256 k){
(uint256 liquidity0, uint256 liquidity1) = getLiquidity(token0);
require(liquidity0 > 0, 'Insufficient liquidity');
require(gain > 0, 'Overflow');
k = liquidity0 * liquidity1;
uint256 _gain = gain * X / (X - feeRate);
amount = k / (liquidity1 - _gain) - liquidity0 + 1;
fee = _gain * feeRate / X;
price = gain * 1E18 / amount;
require(amount > 0 && amount < liquidity0, 'Insufficient liquidity');
}
function sell(address token0, address to, uint256 amount, uint256 amountOutMin) whenNotPaused() override virtual external {
address token1 = token1Addresses[token0];
require(token1 != address(0), 'Not found!');
_sell(token0, token1, to, amount, amountOutMin);
}
function _sell(address token0, address token1, address to, uint256 amount, uint256 amountOutMin) statusCheck(token0) lock(token0) internal virtual returns (uint256){
(uint256 gain,,uint256 fee,) = _sellGain(token0, amount);
require(gain >= amountOutMin, 'LT amountOutMin');
IERC20(token0).safeTransferFrom(msg.sender, address(this), amount);
_liquidity0[token0] += amount;
_liquidity1[token0] -= (gain + fee);
require(gain + fee <= IERC20(token1).balanceOf(address(this)), 'Insufficient token1');
if (token1 == WETH) {
IWETH(WETH).withdraw(gain + fee);
TransferHelper.safeTransferETH(to, gain);
if (fee > 0) TransferHelper.safeTransferETH(IFunFactory(funFactory).feeTo(), fee);
} else {
IERC20(token1).safeTransfer(to, gain);
if (fee > 0) IERC20(token1).safeTransfer(IFunFactory(funFactory).feeTo(), fee);
}
uint256 newPrice = _liquidity1[token0] * 1E18 / _liquidity0[token0];
emit Sell(to, token0, token1, newPrice, gain, amount, fee, block.timestamp);
return gain;
}
function sellCostForExactGain(address token0, address to, uint256 gain, uint256 amountInMax) whenNotPaused() override virtual external {
address token1 = token1Addresses[token0];
require(token1 != address(0), 'Not found!');
_sellCostForExactGain(token0, token1, to, gain, amountInMax);
}
function _sellCostForExactGain(address token0, address token1, address to, uint256 gain, uint256 amountInMax) statusCheck(token0) lock(token0) internal virtual returns (uint256){
(uint256 amount,,uint256 fee,) = _sellExactGain(token0, gain);
require(amount <= amountInMax, 'GT amountInMax');
IERC20(token0).safeTransferFrom(msg.sender, address(this), amountInMax);
if (amountInMax > amount) IERC20(token0).safeTransfer(msg.sender, amountInMax - amount);
_liquidity0[token0] += amount;
_liquidity1[token0] -= (gain + fee);
require(gain + fee <= IERC20(token1).balanceOf(address(this)), 'Insufficient token1');
if (token1 == WETH) {
IWETH(WETH).withdraw(gain + fee);
TransferHelper.safeTransferETH(to, gain);
if (fee > 0) TransferHelper.safeTransferETH(IFunFactory(funFactory).feeTo(), fee);
} else {
IERC20(token1).safeTransfer(to, gain);
if (fee > 0) IERC20(token1).safeTransfer(IFunFactory(funFactory).feeTo(), fee);
}
uint256 newPrice = _liquidity1[token0] * 1E18 / _liquidity0[token0];
emit Sell(to, token0, token1, newPrice, gain, amount, fee, block.timestamp);
return amount;
}
function endCheck(address token0, address token1) internal virtual {
if (_liquidity1[token0] - _liquidity1Virtual[token0] >= swapLimits[token0]) {
status[token0] = 2;
emit Status(token0, token1, 2);
}
}
function addSwapLiquidity(address token0) onlyOperator virtual external {
require(status[token0] == 2, 'Error: status != 2');
address token1 = token1Addresses[token0];
require(token1 != address(0), 'Not found!');
uint256 token0Balance = IERC20(token0).balanceOf(address(this));
uint256 token1Balance = _liquidity1[token0] - _liquidity1Virtual[token0];
if (!IFunToken(token0).status()) IFunToken(token0).setStatus(true);
uint256 fee = fees[token0];
uint256 token1Amount = token1Balance - fee;
IERC20(token0).approve(uniSwapV2Router02, token0Balance);
if (token1 == WETH) {
IWETH(WETH).withdraw(token1Balance);
TransferHelper.safeTransferETH(msg.sender, fee);
IUniswapV2Router02(uniSwapV2Router02).addLiquidityETH{value: token1Amount}(token0, token0Balance, token0Balance, token1Amount, msg.sender, block.timestamp);
} else {
IERC20(token1).safeTransfer(msg.sender, fee);
IERC20(token1).approve(uniSwapV2Router02, token1Amount);
IUniswapV2Router02(uniSwapV2Router02).addLiquidity(token0, token1, token0Balance, token1Amount, token0Balance, token1Amount, msg.sender, block.timestamp);
}
_liquidity0[token0] = 0;
_liquidity1[token0] = 0;
_liquidity1Virtual[token0] = 0;
status[token0] = 3;
emit Status(token0, token1, 3);
}
}
文件 4 的 15: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 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);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 5 的 15:IFunFactory.sol
pragma solidity >=0.8.0;
interface IFunFactory {
event TokenCreated(address indexed token, address indexed creator, string id);
event SetSupportToken(
address indexed token1,
bool isSupport,
uint256 liquidity0,
uint256 liquidity1,
uint256 swapLimit,
uint256 fee
);
event SetFunPool(address indexed poolAddress);
function feeTo() external view returns (address);
function allTokens(uint256) external view returns (address token);
function allTokenLength() external view returns (uint256);
function setFeeTo(address) external;
}
文件 6 的 15:IFunPool.sol
pragma solidity >=0.8.0;
interface IFunPool {
event LiquidityAdded(
address indexed token0,
address token1,
uint256 liquidity0,
uint256 liquidity1
);
event Buy(
address indexed to,
address indexed token0,
address token1,
uint256 newPrice,
uint256 costIn,
uint256 amount,
uint256 fee,
uint256 timestamp
);
event Sell(
address indexed to,
address indexed token0,
address token1,
uint256 newPrice,
uint256 gainOut,
uint256 amount,
uint256 fee,
uint256 timestamp
);
event Status(
address indexed token0,
address token1,
uint8 status
);
function WETH() external view returns (address);
function addLiquidity(address token0, address token1, uint256 liquidity0, uint256 liquidity1, uint256 swapLimit, uint256 fee) external;
function getLiquidity(address token0) external view returns (uint256 liquidity0, uint256 liquidity1);
function tokenPrice(address token0) external view returns (uint256);
function buyGain(address token0, uint256 cost) external view returns (uint256);
function buyExactGain(address token0, uint256 gain) external view returns (uint256);
function buy(address token0, address to, uint256 cost, uint256 amountOutMin) external payable;
function buyCostForExactGain(address token0, address to, uint256 gain, uint256 amountInMax) external payable;
function sellGain(address token0, uint256 amount0) external view returns (uint256);
function sellExactGain(address token0, uint256 gain) external view returns (uint256);
function sell(address token0, address to, uint256 amount, uint256 amountOutMin) external;
function sellCostForExactGain(address token0, address to, uint256 gain, uint256 amountInMax) external;
}
文件 7 的 15:IFunToken.sol
pragma solidity >=0.8.0;
interface IFunToken {
function status() view external returns (bool);
function setStatus(bool status) external;
}
文件 8 的 15:IUniswapV2Router01.sol
pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
文件 9 的 15:IUniswapV2Router02.sol
pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
文件 10 的 15:IWETH.sol
pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint256 value) external returns (bool);
function withdraw(uint256) external;
}
文件 11 的 15: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());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_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);
}
}
文件 12 的 15:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_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());
}
}
文件 13 的 15:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/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");
}
}
}
文件 14 的 15:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
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) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
文件 15 的 15:TransferHelper.sol
pragma solidity >=0.6.0;
library TransferHelper {
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}
{
"compilationTarget": {
"contracts/BakeFun/core/FunPool.sol": "FunPool"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 999999
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"_funFactory","type":"address"},{"internalType":"address","name":"_uniSwapV2Router02","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":false,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"costIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":false,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidity0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidity1","type":"uint256"}],"name":"LiquidityAdded","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":false,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gainOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Sell","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":false,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"uint8","name":"status","type":"uint8"}],"name":"Status","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint256","name":"liquidity0","type":"uint256"},{"internalType":"uint256","name":"liquidity1","type":"uint256"},{"internalType":"uint256","name":"swapLimit","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"}],"name":"addSwapLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gain","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"}],"name":"buyCostForExactGain","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"uint256","name":"gain","type":"uint256"}],"name":"buyExactGain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"uint256","name":"cost","type":"uint256"}],"name":"buyGain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"emergencyWithdrawErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyWithdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"fees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"funFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"}],"name":"getLiquidity","outputs":[{"internalType":"uint256","name":"liquidity0","type":"uint256"},{"internalType":"uint256","name":"liquidity1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"}],"name":"sell","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gain","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"}],"name":"sellCostForExactGain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"uint256","name":"gain","type":"uint256"}],"name":"sellExactGain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sellGain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feeRate","type":"uint256"}],"name":"setFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"setOperatorAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"status","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"swapLimits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"token1Addresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"}],"name":"tokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniSwapV2Router02","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]