Contract Source Code:
File 1 of 1 : YFStable
// SPDX-License-Identifier: MIT
/*
YYYYYYY YYYYYYYFFFFFFFFFFFFFFFFFFFFFF SSSSSSSSSSSSSSS TTTTTTTTTTTTTTTTTTTTTTT AAA BBBBBBBBBBBBBBBBB LLLLLLLLLLL EEEEEEEEEEEEEEEEEEEEEE
Y:::::Y Y:::::YF::::::::::::::::::::F SS:::::::::::::::ST:::::::::::::::::::::T A:::A B::::::::::::::::B L:::::::::L E::::::::::::::::::::E
Y:::::Y Y:::::YF::::::::::::::::::::FS:::::SSSSSS::::::ST:::::::::::::::::::::T A:::::A B::::::BBBBBB:::::B L:::::::::L E::::::::::::::::::::E
Y::::::Y Y::::::YFF::::::FFFFFFFFF::::FS:::::S SSSSSSST:::::TT:::::::TT:::::T A:::::::A BB:::::B B:::::BLL:::::::LL EE::::::EEEEEEEEE::::E
YYY:::::Y Y:::::YYY F:::::F FFFFFFS:::::S TTTTTT T:::::T TTTTTT A:::::::::A B::::B B:::::B L:::::L E:::::E EEEEEE
Y:::::Y Y:::::Y F:::::F S:::::S T:::::T A:::::A:::::A B::::B B:::::B L:::::L E:::::E
Y:::::Y:::::Y F::::::FFFFFFFFFF S::::SSSS T:::::T A:::::A A:::::A B::::BBBBBB:::::B L:::::L E::::::EEEEEEEEEE
Y:::::::::Y F:::::::::::::::F SS::::::SSSSS T:::::T A:::::A A:::::A B:::::::::::::BB L:::::L E:::::::::::::::E
Y:::::::Y F:::::::::::::::F SSS::::::::SS T:::::T A:::::A A:::::A B::::BBBBBB:::::B L:::::L E:::::::::::::::E
Y:::::Y F::::::FFFFFFFFFF SSSSSS::::S T:::::T A:::::AAAAAAAAA:::::A B::::B B:::::B L:::::L E::::::EEEEEEEEEE
Y:::::Y F:::::F S:::::S T:::::T A:::::::::::::::::::::A B::::B B:::::B L:::::L E:::::E
Y:::::Y F:::::F S:::::S T:::::T A:::::AAAAAAAAAAAAA:::::A B::::B B:::::B L:::::L LLLLLL E:::::E EEEEEE
Y:::::Y FF:::::::FF SSSSSSS S:::::S TT:::::::TT A:::::A A:::::A BB:::::BBBBBB::::::BLL:::::::LLLLLLLLL:::::LEE::::::EEEEEEEE:::::E
YYYY:::::YYYY F::::::::FF S::::::SSSSSS:::::S T:::::::::T A:::::A A:::::A B:::::::::::::::::B L::::::::::::::::::::::LE::::::::::::::::::::E
Y:::::::::::Y F::::::::FF S:::::::::::::::SS T:::::::::T A:::::A A:::::A B::::::::::::::::B L::::::::::::::::::::::LE::::::::::::::::::::E
YYYYYYYYYYYYY FFFFFFFFFFF SSSSSSSSSSSSSSS TTTTTTTTTTTAAAAAAA AAAAAAABBBBBBBBBBBBBBBBB LLLLLLLLLLLLLLLLLLLLLLLLEEEEEEEEEEEEEEEEEEEEEE
*/
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() 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;
}
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);
}
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;
}
library SafeMath {
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;
}
}
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");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(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 _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);
}
}
}
}
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
library Constants {
uint256 private constant MAX = ~uint256(0);
uint256 private constant _launchSupply = 60450 * 10**9;
uint256 private constant _largeTotal = (MAX - (MAX % _launchSupply));
uint256 private constant _baseExpansionFactor = 100;
uint256 private constant _baseContractionFactor = 100;
uint256 private constant _baseUtilityFee = 50;
uint256 private constant _baseContractionCap = 1000;
uint256 private constant _stabilizerFee = 250;
uint256 private constant _stabilizationLowerBound = 50;
uint256 private constant _stabilizationLowerReset = 75;
uint256 private constant _stabilizationUpperBound = 150;
uint256 private constant _stabilizationUpperReset = 125;
uint256 private constant _stabilizePercent = 10;
uint256 private constant _treasuryFee = 250;
uint256 private constant _presaleMinIndividualCap = 1 ether;
uint256 private constant _presaleMaxIndividualCap = 4 ether;
uint256 private constant _presaleCap = 37200 * 10**9;
uint256 private constant _maxPresaleGas = 200000000000;
uint256 private constant _epochLength = 4 hours;
uint256 private constant _liquidityReward = 2 * 10**9;
uint256 private constant _minForLiquidity = 10 * 10**9;
uint256 private constant _minForCallerLiquidity = 10 * 10**9;
address private constant _routerAddress = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address private constant _factoryAddress = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
address payable private constant _deployerAddress = 0xB4a43aEd87902A24cD66afBD3349Af812325Ca01;
address private constant _treasuryAddress = 0xB4a43aEd87902A24cD66afBD3349Af812325Ca01;
uint256 private constant _presaleRate = 31000;
uint256 private constant _listingRate = 29063;
string private constant _name = "YFStable";
string private constant _symbol = "YFST";
uint8 private constant _decimals = 9;
/****** Getters *******/
function getPresaleRate() internal pure returns (uint256) {
return _presaleRate;
}
function getListingRate() internal pure returns (uint256) {
return _listingRate;
}
function getLaunchSupply() internal pure returns (uint256) {
return _launchSupply;
}
function getLargeTotal() internal pure returns (uint256) {
return _largeTotal;
}
function getPresaleCap() internal pure returns (uint256) {
return _presaleCap;
}
function getPresaleMinIndividualCap() internal pure returns (uint256) {
return _presaleMinIndividualCap;
}
function getPresaleMaxIndividualCap() internal pure returns (uint256) {
return _presaleMaxIndividualCap;
}
function getMaxPresaleGas() internal pure returns (uint256) {
return _maxPresaleGas;
}
function getBaseExpansionFactor() internal pure returns (uint256) {
return _baseExpansionFactor;
}
function getBaseContractionFactor() internal pure returns (uint256) {
return _baseContractionFactor;
}
function getBaseContractionCap() internal pure returns (uint256) {
return _baseContractionCap;
}
function getBaseUtilityFee() internal pure returns (uint256) {
return _baseUtilityFee;
}
function getStabilizerFee() internal pure returns (uint256) {
return _stabilizerFee;
}
function getStabilizationLowerBound() internal pure returns (uint256) {
return _stabilizationLowerBound;
}
function getStabilizationLowerReset() internal pure returns (uint256) {
return _stabilizationLowerReset;
}
function getStabilizationUpperBound() internal pure returns (uint256) {
return _stabilizationUpperBound;
}
function getStabilizationUpperReset() internal pure returns (uint256) {
return _stabilizationUpperReset;
}
function getStabilizePercent() internal pure returns (uint256) {
return _stabilizePercent;
}
function getTreasuryFee() internal pure returns (uint256) {
return _treasuryFee;
}
function getEpochLength() internal pure returns (uint256) {
return _epochLength;
}
function getLiquidityReward() internal pure returns (uint256) {
return _liquidityReward;
}
function getMinForLiquidity() internal pure returns (uint256) {
return _minForLiquidity;
}
function getMinForCallerLiquidity() internal pure returns (uint256) {
return _minForCallerLiquidity;
}
function getRouterAdd() internal pure returns (address) {
return _routerAddress;
}
function getFactoryAdd() internal pure returns (address) {
return _factoryAddress;
}
function getDeployerAdd() internal pure returns (address payable) {
return _deployerAddress;
}
function getTreasuryAdd() internal pure returns (address) {
return _treasuryAddress;
}
function getName() internal pure returns (string memory) {
return _name;
}
function getSymbol() internal pure returns (string memory) {
return _symbol;
}
function getDecimals() internal pure returns (uint8) {
return _decimals;
}
}
contract State {
mapping (address => uint256) _largeBalances;
mapping (address => mapping (address => uint256)) _allowances;
// Supported pools and data for measuring mint & burn factors
struct PoolCounter {
address pairToken;
uint256 tokenBalance;
uint256 pairTokenBalance;
uint256 lpBalance;
uint256 startTokenBalance;
uint256 startPairTokenBalance;
}
address[] _supportedPools;
mapping (address => PoolCounter) _poolCounters;
mapping (address => bool) _isSupportedPool;
address _mainPool;
uint256 _currentEpoch;
//Creating locked balances
struct LockBox {
address beneficiary;
uint256 lockedBalance;
uint256 unlockTime;
bool locked;
}
LockBox[] _lockBoxes;
mapping(address => uint256) _lockedBalance;
mapping(address => bool) _hasLockedBalance;
uint256 _totalLockedBalance;
uint256 _largeTotal;
uint256 _totalSupply;
address _liquidityReserve;
address _stabilizer;
bool _presaleDone;
address _presaleCon;
bool _paused;
bool _taxLess;
mapping(address=>bool) _isTaxlessSetter;
}
contract Getters is State {
using SafeMath for uint256;
using Address for address;
function getLargeBalances(address account) public view returns (uint256) {
return _largeBalances[account];
}
function getAllowances(address account, address spender) public view returns (uint256) {
return _allowances[account][spender];
}
function getSupportedPools(uint256 index) public view returns (address) {
return _supportedPools[index];
}
function getPoolCounters(address pool) public view returns (address, uint256, uint256, uint256, uint256, uint256) {
PoolCounter memory pc = _poolCounters[pool];
return (pc.pairToken, pc.tokenBalance, pc.pairTokenBalance, pc.lpBalance, pc.startTokenBalance, pc.startPairTokenBalance);
}
function isSupportedPool(address pool) public view returns (bool) {
return _isSupportedPool[pool];
}
function mainPool() public view returns (address) {
return _mainPool;
}
function getCurrentEpoch() public view returns (uint256) {
return _currentEpoch;
}
function getLockBoxes(uint256 box) public view returns (address, uint256, uint256, bool) {
LockBox memory lb = _lockBoxes[box];
return (lb.beneficiary, lb.lockedBalance, lb.unlockTime, lb.locked);
}
function getLockedBalance(address account) public view returns (uint256) {
return _lockedBalance[account];
}
function hasLockedBalance(address account) public view returns (bool) {
return _hasLockedBalance[account];
}
function getTotalLockedBalance() public view returns (uint256) {
return _totalLockedBalance;
}
function getLargeTotal() public view returns (uint256) {
return _largeTotal;
}
function getTotalSupply() public view returns (uint256) {
return _totalSupply;
}
function getLiquidityReserve() public view returns (address) {
return _liquidityReserve;
}
function getStabilizer() public view returns (address) {
return _stabilizer;
}
function isPresaleDone() public view returns (bool) {
return _presaleDone;
}
function getPresaleAddress() public view returns (address) {
return _presaleCon;
}
function isPaused() public view returns (bool) {
return _paused;
}
function isTaxLess() public view returns (bool) {
return _taxLess;
}
function isTaxlessSetter(address account) public view returns (bool) {
return _isTaxlessSetter[account];
}
function getUniswapRouter() public view returns (IUniswapV2Router02) {
return IUniswapV2Router02(Constants.getRouterAdd());
}
function getUniswapFactory() public view returns (IUniswapV2Factory) {
return IUniswapV2Factory(Constants.getFactoryAdd());
}
function getFactor() public view returns(uint256) {
if (_presaleDone) {
return _largeTotal.div(_totalSupply);
} else {
return _largeTotal.div(Constants.getLaunchSupply());
}
}
function getUpdatedPoolCounters(address pool, address pairToken) public view returns (uint256, uint256, uint256) {
uint256 lpBalance = IERC20(pool).totalSupply();
uint256 tokenBalance = IERC20(address(this)).balanceOf(pool);
uint256 pairTokenBalance = IERC20(address(pairToken)).balanceOf(pool);
return (tokenBalance, pairTokenBalance, lpBalance);
}
function getMintValue(address sender, uint256 amount) internal view returns(uint256, uint256, uint256) {
uint256 expansionR = (_poolCounters[sender].pairTokenBalance).mul(_poolCounters[sender].startTokenBalance).mul(100).div(_poolCounters[sender].startPairTokenBalance).div(_poolCounters[sender].tokenBalance);
uint256 mintAmount;
if (expansionR > (Constants.getBaseExpansionFactor()).add(10000).div(100)) {
uint256 mintFactor = expansionR.mul(expansionR);
mintAmount = amount.mul(mintFactor.sub(10000)).div(10000);
} else {
mintAmount = amount.mul(Constants.getBaseExpansionFactor()).div(10000);
}
return (mintAmount.mul(Constants.getStabilizerFee()).div(10000),mintAmount.mul(Constants.getTreasuryFee()).div(10000),mintAmount);
}
function getBurnValues(address recipient, uint256 amount) internal view returns(uint256, uint256) {
uint256 currentFactor = getFactor();
uint256 contractionR;
if (isSupportedPool(recipient)) {
contractionR = (_poolCounters[recipient].tokenBalance).mul(_poolCounters[recipient].startPairTokenBalance).mul(100).div(_poolCounters[recipient].pairTokenBalance).div(_poolCounters[recipient].startTokenBalance);
} else {
contractionR = (_poolCounters[_mainPool].tokenBalance).mul(_poolCounters[_mainPool].startPairTokenBalance).mul(100).div(_poolCounters[_mainPool].pairTokenBalance).div(_poolCounters[_mainPool].startTokenBalance);
}
uint256 burnAmount;
if (contractionR > (Constants.getBaseContractionFactor().add(10000)).div(100)) {
uint256 burnFactor = contractionR.mul(contractionR);
burnAmount = amount.mul(burnFactor.sub(10000)).div(10000);
if (burnAmount > amount.mul(Constants.getBaseContractionCap()).div(10000)) burnAmount = amount.mul(Constants.getBaseContractionCap()).div(10000);
} else {
burnAmount = amount.mul(Constants.getBaseContractionFactor()).div(10000);
}
return (burnAmount, burnAmount.mul(currentFactor));
}
function getUtilityFee(uint256 amount) internal view returns(uint256, uint256) {
uint256 currentFactor = getFactor();
uint256 utilityFee = amount.mul(Constants.getBaseUtilityFee()).div(10000);
return (utilityFee, utilityFee.mul(currentFactor));
}
function getMintRate(address pool) external view returns (uint256) {
uint256 expansionR = (_poolCounters[pool].pairTokenBalance).mul(_poolCounters[pool].startTokenBalance).mul(100).div(_poolCounters[pool].startPairTokenBalance).div(_poolCounters[pool].tokenBalance);
if (expansionR > (Constants.getBaseExpansionFactor()).add(10000).div(100)) {
uint256 mintFactor = expansionR.mul(expansionR);
return mintFactor.sub(10000);
} else {
return Constants.getBaseExpansionFactor();
}
}
function getBurnRate(address pool) external view returns (uint256) {
uint256 contractionR = (_poolCounters[pool].tokenBalance).mul(_poolCounters[pool].startPairTokenBalance).mul(100).div(_poolCounters[pool].pairTokenBalance).div(_poolCounters[pool].startTokenBalance);
uint256 burnRate;
if (contractionR > (Constants.getBaseContractionFactor().add(10000)).div(100)) {
uint256 burnFactor = contractionR.mul(contractionR);
burnRate = burnFactor.sub(10000);
if (burnRate > Constants.getBaseContractionCap()) {
return Constants.getBaseContractionCap();
}
return burnRate;
} else {
return Constants.getBaseContractionFactor();
}
}
}
contract Setters is State, Getters {
function updatePresaleAddress(address presaleAddress) internal {
_presaleCon = presaleAddress;
}
function setAllowances(address owner, address spender, uint256 amount) internal {
_allowances[owner][spender] = amount;
}
function addToAccount(address account, uint256 amount) internal {
uint256 currentFactor = getFactor();
uint256 largeAmount = amount.mul(currentFactor);
_largeBalances[account] = _largeBalances[account].add(largeAmount);
_totalSupply = _totalSupply.add(amount);
}
function addToAll(uint256 amount) internal {
_totalSupply = _totalSupply.add(amount);
}
function initializeEpoch() internal {
_currentEpoch = now;
}
function updateEpoch() internal {
initializeEpoch();
for (uint256 i=0; i<_supportedPools.length; i++) {
_poolCounters[_supportedPools[i]].startTokenBalance = _poolCounters[_supportedPools[i]].tokenBalance;
_poolCounters[_supportedPools[i]].startPairTokenBalance = _poolCounters[_supportedPools[i]].pairTokenBalance;
}
}
function initializeLargeTotal() internal {
_largeTotal = Constants.getLargeTotal();
}
function syncPair(address pool) internal returns(bool) {
(uint256 tokenBalance, uint256 pairTokenBalance, uint256 lpBalance) = getUpdatedPoolCounters(pool, _poolCounters[pool].pairToken);
bool lpBurn = lpBalance < _poolCounters[pool].lpBalance;
_poolCounters[pool].lpBalance = lpBalance;
_poolCounters[pool].tokenBalance = tokenBalance;
_poolCounters[pool].pairTokenBalance = pairTokenBalance;
return (lpBurn);
}
function silentSyncPair(address pool) public {
(uint256 tokenBalance, uint256 pairTokenBalance, uint256 lpBalance) = getUpdatedPoolCounters(pool, _poolCounters[pool].pairToken);
_poolCounters[pool].lpBalance = lpBalance;
_poolCounters[pool].tokenBalance = tokenBalance;
_poolCounters[pool].pairTokenBalance = pairTokenBalance;
}
function addSupportedPool(address pool, address pairToken) internal {
require(!isSupportedPool(pool),"This pool is already supported");
_isSupportedPool[pool] = true;
_supportedPools.push(pool);
(uint256 tokenBalance, uint256 pairTokenBalance, uint256 lpBalance) = getUpdatedPoolCounters(pool, pairToken);
_poolCounters[pool] = PoolCounter(pairToken, tokenBalance, pairTokenBalance, lpBalance, tokenBalance, pairTokenBalance);
}
function removeSupportedPool(address pool) internal {
require(isSupportedPool(pool), "This pool is currently not supported");
for (uint256 i = 0; i < _supportedPools.length; i++) {
if (_supportedPools[i] == pool) {
_supportedPools[i] = _supportedPools[_supportedPools.length - 1];
_isSupportedPool[pool] = false;
delete _poolCounters[pool];
_supportedPools.pop();
break;
}
}
}
}
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);
}
contract Stabilizer {
constructor() public {
}
}
contract YFStable is Setters, Context, IERC20, Ownable {
using SafeMath for uint256;
using Address for address;
modifier onlyTaxless {
require(isTaxlessSetter(_msgSender()),"not taxless");
_;
}
modifier onlyPresale {
require(_msgSender()==getPresaleAddress(),"not presale");
require(!isPresaleDone(), "Presale over");
_;
}
modifier pausable {
require(!isPaused(), "Paused");
_;
}
modifier taxlessTx {
_taxLess = true;
_;
_taxLess = false;
}
constructor() public {
updateEpoch();
initializeLargeTotal();
setStabilizer(address(new Stabilizer()));
}
function name() public view returns (string memory) {
return Constants.getName();
}
function symbol() public view returns (string memory) {
return Constants.getSymbol();
}
function decimals() public view returns (uint8) {
return Constants.getDecimals();
}
function totalSupply() public view override returns (uint256) {
return getTotalSupply();
}
function circulatingSupply() public view returns (uint256) {
uint256 currentFactor = getFactor();
return getTotalSupply().sub(getTotalLockedBalance().div(currentFactor)).sub(balanceOf(address(this))).sub(balanceOf(getStabilizer()));
}
function balanceOf(address account) public view override returns (uint256) {
uint256 currentFactor = getFactor();
if (hasLockedBalance(account)) return (getLargeBalances(account).add(getLockedBalance(account)).div(currentFactor));
return getLargeBalances(account).div(currentFactor);
}
function unlockedBalanceOf(address account) public view returns (uint256) {
uint256 currentFactor = getFactor();
return getLargeBalances(account).div(currentFactor);
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return getAllowances(owner,spender);
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), getAllowances(sender,_msgSender()).sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, getAllowances(_msgSender(),spender).add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, getAllowances(_msgSender(),spender).sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function mint(address to, uint256 amount) public onlyPresale {
addToAccount(to,amount);
emit Transfer(address(0),to,amount);
}
function _approve(address owner, address spender, uint256 amount) private {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
setAllowances(owner, spender, amount);
emit Approval(owner, spender, amount);
}
function _transfer(address sender, address recipient, uint256 amount) private pausable {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Amount must be greater than zero");
require(amount <= balanceOf(sender),"Amount exceeds balance");
require(amount <= unlockedBalanceOf(sender),"Amount exceeds unlocked balance");
require(isPresaleDone(),"Presale yet to close");
if (now > getCurrentEpoch().add(Constants.getEpochLength())) updateEpoch();
uint256 currentFactor = getFactor();
uint256 largeAmount = amount.mul(currentFactor);
uint256 txType;
if (isTaxLess()) {
txType = 3;
} else {
bool lpBurn;
if (isSupportedPool(sender)) {
lpBurn = syncPair(sender);
} else if (isSupportedPool(recipient)){
silentSyncPair(recipient);
} else {
silentSyncPair(_mainPool);
}
txType = _getTxType(sender, recipient, lpBurn);
}
// Buy Transaction from supported pools - requires mint, no utility fee
if (txType == 1) {
(uint256 stabilizerMint, uint256 treasuryMint, uint256 totalMint) = getMintValue(sender, amount);
// uint256 mintSize = amount.div(100);
_largeBalances[sender] = _largeBalances[sender].sub(largeAmount);
_largeBalances[recipient] = _largeBalances[recipient].add(largeAmount);
_largeBalances[getStabilizer()] = _largeBalances[getStabilizer()].add(stabilizerMint.mul(currentFactor));
_largeBalances[Constants.getTreasuryAdd()] = _largeBalances[Constants.getTreasuryAdd()].add(treasuryMint.mul(currentFactor));
_totalSupply = _totalSupply.add(totalMint);
emit Transfer(sender, recipient, amount);
emit Transfer(address(0),getStabilizer(),stabilizerMint);
emit Transfer(address(0),Constants.getTreasuryAdd(),treasuryMint);
}
// Sells to supported pools or unsupported transfer - requires exit burn and utility fee
else if (txType == 2) {
(uint256 burnSize, uint256 largeBurnSize) = getBurnValues(recipient, amount);
(uint256 utilityFee, uint256 largeUtilityFee) = getUtilityFee(amount);
uint256 actualTransferAmount = amount.sub(burnSize).sub(utilityFee);
uint256 largeTransferAmount = actualTransferAmount.mul(currentFactor);
_largeBalances[sender] = _largeBalances[sender].sub(largeAmount);
_largeBalances[recipient] = _largeBalances[recipient].add(largeTransferAmount);
_largeBalances[_liquidityReserve] = _largeBalances[_liquidityReserve].add(largeUtilityFee);
_totalSupply = _totalSupply.sub(burnSize);
_largeTotal = _largeTotal.sub(largeBurnSize);
emit Transfer(sender, recipient, actualTransferAmount);
emit Transfer(sender, address(0), burnSize);
emit Transfer(sender, _liquidityReserve, utilityFee);
}
// Add Liquidity via interface or Remove Liquidity Transaction to supported pools - no fee of any sort
else if (txType == 3) {
_largeBalances[sender] = _largeBalances[sender].sub(largeAmount);
_largeBalances[recipient] = _largeBalances[recipient].add(largeAmount);
emit Transfer(sender, recipient, amount);
}
}
function _getTxType(address sender, address recipient, bool lpBurn) private returns(uint256) {
uint256 txType = 2;
if (isSupportedPool(sender)) {
if (lpBurn) {
txType = 3;
} else {
txType = 1;
}
} else if (sender == Constants.getRouterAdd()) {
txType = 3;
}
return txType;
}
function setPresale(address presaleAdd) external onlyOwner() {
require(!isPresaleDone(), "Presale is already completed");
updatePresaleAddress(presaleAdd);
}
function setPresaleDone() public payable onlyPresale {
require(totalSupply() <= Constants.getLaunchSupply(), "Total supply is already minted");
_mintRemaining();
_presaleDone = true;
_createEthPool();
}
function _mintRemaining() private {
require(!isPresaleDone(), "Cannot mint post presale");
Constants.getDeployerAdd().transfer(address(this).balance.div(3));
uint256 toMint = Constants.getLaunchSupply().sub(totalSupply());
uint256 tokensToAdd = address(this).balance.div(10**11).mul(Constants.getListingRate());
if(toMint > tokensToAdd) {
addToAccount(address(0),toMint.sub(tokensToAdd));
emit Transfer(address(0),address(0),toMint.sub(tokensToAdd));
}
addToAccount(address(this), tokensToAdd);
emit Transfer(address(0),address(this),tokensToAdd);
}
function mintLockedTranche(address account, uint256 unlockTime, uint256 amount) external onlyOwner() {
require(!isPresaleDone(), "Cannot mint post presale");
uint256 currentFactor = getFactor();
uint256 largeAmount = amount.mul(currentFactor);
_lockBoxes.push(LockBox(account, largeAmount, unlockTime, true));
_lockedBalance[account] = _lockedBalance[account].add(largeAmount);
_hasLockedBalance[account] = true;
_totalLockedBalance = _totalLockedBalance.add(largeAmount);
_totalSupply = _totalSupply.add(amount);
emit Transfer(address(0),account,amount);
}
function mintUnlockedTranche(address account, uint256 amount) external onlyOwner() {
require(!isPresaleDone(), "Cannot mint post presale");
addToAccount(account, amount);
emit Transfer(address(0),account,amount);
}
function unlockTranche(uint256 tranche) external {
require(hasLockedBalance(_msgSender()),"Caller has no locked balance");
(address beneficiary, uint256 balance, uint256 unlockTime, bool locked) = getLockBoxes(tranche);
require(unlockTime <= now,"This tranche cannot be unlocked yet");
require(beneficiary == _msgSender(),"You are not the owner of this tranche");
require(locked == true, "This tranche has already been unlocked");
_totalLockedBalance = _totalLockedBalance.sub(balance);
_largeBalances[_msgSender()] = _largeBalances[_msgSender()].add(balance);
_lockedBalance[_msgSender()] = _lockedBalance[_msgSender()].sub(balance);
if (_lockedBalance[_msgSender()] <= 0) _hasLockedBalance[_msgSender()] = false;
_lockBoxes[tranche].lockedBalance = 0;
_lockBoxes[tranche].locked = false;
}
function reassignTranche(uint256 tranche, address beneficiary) external onlyOwner() {
(address oldBeneficiary, uint256 balance, uint256 unlockTime, bool locked) = getLockBoxes(tranche);
require(locked == true, "This tranche has already been unlocked");
require(unlockTime > now,"This tranche has already been vested");
_lockedBalance[oldBeneficiary] = _lockedBalance[oldBeneficiary].sub(balance);
_lockedBalance[beneficiary] = _lockedBalance[beneficiary].add(balance);
if (_lockedBalance[oldBeneficiary] == 0) _hasLockedBalance[oldBeneficiary] = false;
_hasLockedBalance[beneficiary] = true;
_lockBoxes[tranche].beneficiary = beneficiary;
uint256 currentFactor = getFactor();
emit Transfer(oldBeneficiary,beneficiary,balance.div(currentFactor));
}
function _createEthPool() private taxlessTx {
IUniswapV2Router02 uniswapRouterV2 = getUniswapRouter();
IUniswapV2Factory uniswapFactory = getUniswapFactory();
address tokenUniswapPair;
if (uniswapFactory.getPair(address(uniswapRouterV2.WETH()), address(this)) == address(0)) {
tokenUniswapPair = uniswapFactory.createPair(
address(uniswapRouterV2.WETH()), address(this));
} else {
tokenUniswapPair = uniswapFactory.getPair(address(this),uniswapRouterV2.WETH());
}
uint256 tokensToAdd = balanceOf(address(this));
_approve(address(this), 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, tokensToAdd);
uniswapRouterV2.addLiquidityETH{value: address(this).balance}(address(this),
tokensToAdd, 0, 0, Constants.getDeployerAdd(), block.timestamp);
addSupportedPool(tokenUniswapPair, address(uniswapRouterV2.WETH()));
_mainPool = tokenUniswapPair;
}
function createTokenPool(address pairToken, uint256 amount) external onlyOwner() taxlessTx {
IUniswapV2Router02 uniswapRouterV2 = getUniswapRouter();
IUniswapV2Factory uniswapFactory = getUniswapFactory();
address tokenUniswapPair;
if (uniswapFactory.getPair(pairToken, address(this)) == address(0)) {
tokenUniswapPair = uniswapFactory.createPair(
pairToken, address(this));
} else {
tokenUniswapPair = uniswapFactory.getPair(pairToken,address(this));
}
require(uniswapFactory.getPair(pairToken,address(uniswapRouterV2.WETH())) != address(0), "Eth pairing does not exist");
require(balanceOf(address(this)) >= amount, "Amount exceeds the token balance");
uint256 toConvert = amount.div(2);
uint256 toAdd = amount.sub(toConvert);
uint256 initialBalance = IERC20(pairToken).balanceOf(address(this));
address[] memory path = new address[](3);
path[0] = address(this);
path[1] = uniswapRouterV2.WETH();
path[2] = pairToken;
_approve(address(this), address(uniswapRouterV2), toConvert);
uniswapRouterV2.swapExactTokensForTokensSupportingFeeOnTransferTokens(
toConvert, 0, path, address(this), block.timestamp);
uint256 newBalance = IERC20(pairToken).balanceOf(address(this)).sub(initialBalance);
_approve(address(this), address(uniswapRouterV2), toAdd);
IERC20(pairToken).approve(address(uniswapRouterV2), newBalance);
uniswapRouterV2.addLiquidity(address(this),pairToken,toAdd,newBalance,0,0,address(this),block.timestamp);
addSupportedPool(tokenUniswapPair, pairToken);
}
function addNewSupportedPool(address pool, address pairToken) external onlyOwner() {
addSupportedPool(pool, pairToken);
}
function removeOldSupportedPool(address pool) external onlyOwner() {
removeSupportedPool(pool);
}
function setTaxlessSetter(address cont) external onlyOwner() {
require(!isTaxlessSetter(cont),"already setter");
_isTaxlessSetter[cont] = true;
}
function setTaxless(bool flag) public onlyTaxless {
_taxLess = flag;
}
function removeTaxlessSetter(address cont) external onlyOwner() {
require(isTaxlessSetter(cont),"not setter");
_isTaxlessSetter[cont] = false;
}
function setLiquidityReserve(address reserve) external onlyOwner() {
require(Address.isContract(reserve),"Need a contract");
_isTaxlessSetter[_liquidityReserve] = false;
uint256 oldBalance = balanceOf(_liquidityReserve);
if (oldBalance > 0) {
_transfer(_liquidityReserve, reserve, oldBalance);
emit Transfer(_liquidityReserve, reserve, oldBalance);
}
_liquidityReserve = reserve;
_isTaxlessSetter[reserve] = true;
}
function setStabilizer(address reserve) public onlyOwner() taxlessTx {
require(Address.isContract(reserve),"Need a contract");
_isTaxlessSetter[_stabilizer] = false;
uint256 oldBalance = balanceOf(_stabilizer);
if (oldBalance > 0) {
_transfer(_stabilizer, reserve, oldBalance);
emit Transfer(_stabilizer, reserve, oldBalance);
}
_stabilizer = reserve;
_isTaxlessSetter[reserve] = true;
}
function pauseContract(bool flag) external onlyOwner() {
_paused = flag;
}
}