文件 2 的 2:hardrouter.sol
pragma solidity =0.6.6;
import './interfaces/IEtherVistaRouter.sol';
interface IEtherVistaPair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function setMetadata(string calldata website, string calldata image, string calldata description, string calldata chat, string calldata social) external;
function websiteUrl() external view returns (string memory);
function imageUrl() external view returns (string memory);
function tokenDescription() external view returns (string memory);
function chatUrl() external view returns (string memory);
function socialUrl() external view returns (string memory);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function updateProvider(address user) external;
function euler(uint) external view returns (uint256);
function viewShare() external view returns (uint256 share);
function claimShare() external;
function poolBalance() external view returns (uint);
function totalCollected() external view returns (uint);
function setProtocol(address) external;
function protocol() external view returns (address);
function payableProtocol() external view returns (address payable origin);
function creator() external view returns (address);
function renounce() external;
function setFees() external;
function updateFees(uint8, uint8, uint8, uint8) external;
function buyLpFee() external view returns (uint8);
function sellLpFee() external view returns (uint8);
function buyProtocolFee() external view returns (uint8);
function sellProtocolFee() external view returns (uint8);
function buyTotalFee() external view returns (uint8);
function sellTotalFee() external view returns (uint8);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function first_mint(address to, uint8 buyLp, uint8 sellLp, uint8 buyProtocol, uint8 sellProtocol, address protocolAddress) external returns (uint liquidity);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address _token0, address _token1) external;
}
library SafeMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
}
library UniswapV2Library {
using SafeMath for uint;
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES');
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS');
}
function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
pair = address(uint(keccak256(abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encodePacked(token0, token1)),
hex'e260b72768e8ec6814aa811c576f346d208ba00840f835949d65c6424ac80a8d'
))));
}
function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
(address token0,) = sortTokens(tokenA, tokenB);
(uint reserve0, uint reserve1,) = IEtherVistaPair(pairFor(factory, tokenA, tokenB)).getReserves();
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
}
function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT');
require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
amountB = amountA.mul(reserveB) / reserveA;
}
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
uint amountInWithFee = amountIn.mul(1000);
uint numerator = amountInWithFee.mul(reserveOut);
uint denominator = reserveIn.mul(1000).add(amountInWithFee);
amountOut = numerator / denominator;
}
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
uint numerator = reserveIn.mul(amountOut).mul(1000);
uint denominator = reserveOut.sub(amountOut).mul(1000);
amountIn = (numerator / denominator).add(1);
}
function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) {
require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
amounts = new uint[](path.length);
amounts[0] = amountIn;
for (uint i; i < path.length - 1; i++) {
(uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]);
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
}
}
function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) {
require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
amounts = new uint[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint i = path.length - 1; i > 0; i--) {
(uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]);
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
}
}
}
interface IEtherVistaFactory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function routerSetter() external view returns (address);
function router() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
function setRouterSetter(address) external;
function setRouter(address) external;
}
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::safeApprove: 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::safeTransfer: 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::transferFrom: transferFrom failed'
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
}
}
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}
interface IWETH {
function deposit() external payable;
function transfer(address to, uint value) external returns (bool);
function withdraw(uint) external;
}
interface AggregatorV3Interface {
function decimals()
external
view
returns (
uint8
);
function description()
external
view
returns (
string memory
);
function version()
external
view
returns (
uint256
);
function getRoundData(
uint80 _roundId
)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
interface IStakingContract {
function stake(uint256, address, address) external;
}
contract EtherVistaRouter is IEtherVistaRouter {
using SafeMath for uint;
address public immutable override factory;
address public immutable override WETH;
address payable public treasury;
AggregatorV3Interface internal priceFeed;
modifier ensure(uint deadline) {
require(deadline >= block.timestamp, 'EtherVista: EXPIRED');
_;
}
constructor(address _factory, address _WETH, address _oracleAddress ) public {
factory = _factory;
WETH = _WETH;
priceFeed = AggregatorV3Interface(_oracleAddress);
treasury = msg.sender;
}
receive() external payable {
assert(msg.sender == WETH);
}
function getEthUsdcPrice() internal view returns (uint256) {
(, int256 price, , , ) = priceFeed.latestRoundData();
require(price > 0, "Invalid price");
return uint256(price/100);
}
function usdcToEth(uint256 usdcAmount) public view returns (uint256) {
uint256 ethUsdcPrice = getEthUsdcPrice();
return (usdcAmount * 1e6*1e18 / ethUsdcPrice);
}
function updateSelf(address _token) public override {
IEtherVistaPair pair = IEtherVistaPair(_token);
require(IEtherVistaFactory(factory).getPair(pair.token0(), pair.token1()) == _token);
pair.updateProvider(msg.sender);
}
function safeTransferLp(address _token, address to, uint256 _amount) public override {
require(_amount > 0, "Amount must be greater than 0");
IEtherVistaPair pair = IEtherVistaPair(_token);
require(IEtherVistaFactory(factory).getPair(pair.token0(), pair.token1()) == _token);
TransferHelper.safeTransferFrom(_token, msg.sender, to, _amount);
pair.updateProvider(msg.sender);
}
function hardstake(address _contract, address _token, uint256 _amount) public override {
require(_amount > 0, "Amount must be greater than 0");
TransferHelper.safeTransferFrom(_token, msg.sender, _contract, _amount);
try IEtherVistaPair(_token).token0() returns (address token0) {
address token1 = IEtherVistaPair(_token).token1();
if (IEtherVistaFactory(factory).getPair(token0, token1) == _token) {
IEtherVistaPair(_token).updateProvider(msg.sender);
}
} catch {}
IStakingContract(_contract).stake(_amount, msg.sender, _token);
}
function _addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin
) internal virtual returns (uint amountA, uint amountB) {
if (IEtherVistaFactory(factory).getPair(tokenA, tokenB) == address(0)) {
IEtherVistaFactory(factory).createPair(tokenA, tokenB);
}
(uint reserveA, uint reserveB) = UniswapV2Library.getReserves(factory, tokenA, tokenB);
if (reserveA == 0 && reserveB == 0) {
(amountA, amountB) = (amountADesired, amountBDesired);
} else {
uint amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB);
if (amountBOptimal <= amountBDesired) {
require(amountBOptimal >= amountBMin, 'EtherVistaRouter: INSUFFICIENT_B_AMOUNT');
(amountA, amountB) = (amountADesired, amountBOptimal);
} else {
uint amountAOptimal = UniswapV2Library.quote(amountBDesired, reserveB, reserveA);
assert(amountAOptimal <= amountADesired);
require(amountAOptimal >= amountAMin, 'EtherVistaRouter: INSUFFICIENT_A_AMOUNT');
(amountA, amountB) = (amountAOptimal, amountBDesired);
}
}
}
function launch(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
uint8 buyLpFee,
uint8 sellLpFee,
uint8 buyProtocolFee,
uint8 sellProtocolFee,
address protocolAddress
) external virtual override payable returns (uint amountToken, uint amountETH, uint liquidity) {
(amountToken, amountETH) = _addLiquidity(
token,
WETH,
amountTokenDesired,
msg.value,
amountTokenMin,
amountETHMin
);
address pair = UniswapV2Library.pairFor(factory, token, WETH);
TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
IWETH(WETH).deposit{value: amountETH}();
assert(IWETH(WETH).transfer(pair, amountETH));
liquidity = IEtherVistaPair(pair).first_mint(msg.sender, buyLpFee, sellLpFee, buyProtocolFee, sellProtocolFee, protocolAddress);
IEtherVistaPair(UniswapV2Library.pairFor(factory, token, WETH)).updateProvider(msg.sender);
if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
}
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
uint deadline
) external virtual override payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
(amountToken, amountETH) = _addLiquidity(
token,
WETH,
amountTokenDesired,
msg.value,
amountTokenMin,
amountETHMin
);
address pair = UniswapV2Library.pairFor(factory, token, WETH);
TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
IWETH(WETH).deposit{value: amountETH}();
assert(IWETH(WETH).transfer(pair, amountETH));
liquidity = IEtherVistaPair(pair).mint(msg.sender);
IEtherVistaPair(UniswapV2Library.pairFor(factory, token, WETH)).updateProvider(msg.sender);
if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
}
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) internal ensure(deadline) returns (uint amountA, uint amountB) {
address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);
IEtherVistaPair(pair).transferFrom(msg.sender, pair, liquidity);
(uint amount0, uint amount1) = IEtherVistaPair(pair).burn(to);
(address token0,) = UniswapV2Library.sortTokens(tokenA, tokenB);
(amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0);
require(amountA >= amountAMin, 'EtherVistaRouter: INSUFFICIENT_A_AMOUNT');
require(amountB >= amountBMin, 'EtherVistaRouter: INSUFFICIENT_B_AMOUNT');
}
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
uint deadline
) public virtual override ensure(deadline) returns (uint amountETH) {
(, amountETH) = removeLiquidity(
token,
WETH,
liquidity,
amountTokenMin,
amountETHMin,
address(this),
deadline
);
IEtherVistaPair(UniswapV2Library.pairFor(factory, token, WETH)).updateProvider(msg.sender);
TransferHelper.safeTransfer(token, msg.sender, IERC20(token).balanceOf(address(this)));
IWETH(WETH).withdraw(amountETH);
TransferHelper.safeTransferETH(msg.sender, amountETH);
}
function _swapSupportingFeeOnTransferTokens(address[] memory path, address _to) internal virtual {
for (uint i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0,) = UniswapV2Library.sortTokens(input, output);
IEtherVistaPair pair = IEtherVistaPair(UniswapV2Library.pairFor(factory, input, output));
uint amountInput;
uint amountOutput;
{
(uint reserve0, uint reserve1,) = pair.getReserves();
(uint reserveInput, uint reserveOutput) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
amountInput = IERC20(input).balanceOf(address(pair)).sub(reserveInput);
amountOutput = UniswapV2Library.getAmountOut(amountInput, reserveInput, reserveOutput);
}
(uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOutput) : (amountOutput, uint(0));
address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2]) : _to;
pair.swap(amount0Out, amount1Out, to, new bytes(0));
}
}
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
)
external
virtual
override
payable
ensure(deadline)
{
require(path.length == 2, 'EtherVistaRouter: INVALID_PATH_LENGTH');
IEtherVistaPair Pair = IEtherVistaPair(UniswapV2Library.pairFor(factory, path[0], path[1]));
require(path[0] == WETH, 'EtherVistaRouter: INVALID_PATH');
require(msg.value > usdcToEth(Pair.buyTotalFee()), 'EtherVistaRouter: INSUFFICIENT_ETH_FEE');
uint amountIn = msg.value-usdcToEth(Pair.buyTotalFee());
IWETH(WETH).deposit{value: amountIn}();
assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn));
uint balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
_swapSupportingFeeOnTransferTokens(path, to);
require(
IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
'EtherVistaRouter: INSUFFICIENT_OUTPUT_AMOUNT'
);
treasury.transfer(usdcToEth(1));
(bool sent1, ) = IEtherVistaPair(UniswapV2Library.pairFor(factory, path[0], path[1])).payableProtocol().call{value: usdcToEth(Pair.buyProtocolFee())}("");
(bool sent2,) = UniswapV2Library.pairFor(factory, path[0], path[1]).call{value: usdcToEth(Pair.buyLpFee())}("");
require(sent1 && sent2, "Failed to send Ether");
}
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
)
external
payable
virtual
override
ensure(deadline)
{
require(path.length == 2, 'EtherVistaRouter: INVALID_PATH_LENGTH');
IEtherVistaPair Pair = IEtherVistaPair(UniswapV2Library.pairFor(factory, path[0], path[1]));
require(path[path.length - 1] == WETH, 'EtherVistaRouter: INVALID_PATH');
require(msg.value >= usdcToEth(Pair.sellTotalFee()), 'EtherVistaRouter: INSUFFICIENT_ETH_FEE');
TransferHelper.safeTransferFrom(
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn
);
_swapSupportingFeeOnTransferTokens(path, address(this));
uint amountOut = IERC20(WETH).balanceOf(address(this));
require(amountOut >= amountOutMin, 'EtherVistaRouter: INSUFFICIENT_OUTPUT_AMOUNT');
treasury.transfer(usdcToEth(1));
(bool sent1, ) = IEtherVistaPair(UniswapV2Library.pairFor(factory, path[0], path[1])).payableProtocol().call{value: usdcToEth(Pair.sellProtocolFee())}("");
(bool sent2,) = UniswapV2Library.pairFor(factory, path[0], path[1]).call{value: usdcToEth(Pair.sellLpFee())}("");
require(sent1 && sent2, "Failed to send Ether");
IWETH(WETH).withdraw(amountOut);
TransferHelper.safeTransferETH(to, amountOut);
}
function quote(uint amountA, uint reserveA, uint reserveB) public pure virtual override returns (uint amountB) {
return UniswapV2Library.quote(amountA, reserveA, reserveB);
}
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut)
public
pure
virtual
override
returns (uint amountOut)
{
return UniswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut);
}
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut)
public
pure
virtual
override
returns (uint amountIn)
{
return UniswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut);
}
function getAmountsOut(uint amountIn, address[] memory path)
public
view
virtual
override
returns (uint[] memory amounts)
{
return UniswapV2Library.getAmountsOut(factory, amountIn, path);
}
function getAmountsIn(uint amountOut, address[] memory path)
public
view
virtual
override
returns (uint[] memory amounts)
{
return UniswapV2Library.getAmountsIn(factory, amountOut, path);
}
}