文件 1 的 1:BasedLadder.sol
pragma solidity 0.8.17;
library SafeMath {
function tryAdd(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
interface IERC20 {
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Transfer(address indexed from, address indexed to, uint256 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 (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
interface IDEXFactory {
function createPair(address tokenA, address tokenB)
external
returns (address pair);
function getPair(address tokenA, address tokenB)
external
view
returns (address pair);
}
interface IDEXRouter {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountOut);
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountIn);
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}
interface IDEXPair {
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves()
external
view
returns (
uint112 reserve0,
uint112 reserve1,
uint32 blockTimestampLast
);
function sync() external;
}
interface IWETH {
function deposit() external payable;
function withdraw(uint wad) external;
}
interface IPrinter {
function swap(
address _router,
address swaptoken,
address print
) external;
function claimInfo(address _stakers, address _printer) external returns(uint[] memory info);
function stake(uint256 value) external;
function withdraw(uint256 value, address receiver) external;
function claimReward(address _printer) external;
function setPortion(uint _treasery, uint _printing) external;
function setStake(uint _minimum, uint _tax, bool _on) external;
}
interface ILADDER {
function MinimumStake() external view returns(uint);
function treaseryWallet() external view returns(address);
function printer() external view returns(address);
}
contract Printer is IPrinter {
using SafeMath for uint256;
event Staked(address _stacker, uint amount);
event Printed(address _printer, uint Amount);
event Withdraw(address _stackers, uint amount, bool out);
event DistributeReward(address _rewardToken, uint amount, uint totalStackers);
event Claim(address _stacker, address _rewardToken, uint amount);
address public _callerToken;
address public nativeCoin;
bool stakeOn;
uint claimTax;
uint minimumStake;
uint256 public totalStacked;
uint printingPortion = 400000;
uint treaseryPortion = 600000;
struct ClaimInfo {
uint256 totalCollectedClaim;
uint256 pendingClaim;
}
mapping(address => mapping(address => ClaimInfo)) public claim;
mapping(address => bool) public isStacker;
mapping(address => uint256) public stacked;
mapping(address => uint256) indexByAdd;
mapping(address => uint256) reseaveReward;
address[] public stackers;
modifier onlyToken() {
require(msg.sender == _callerToken);
_;
}
constructor(address _nativeCoin) {
require(_nativeCoin != address(0), "invalid nativeCoin address");
nativeCoin = _nativeCoin;
_callerToken = msg.sender;
}
receive() external payable {}
event swapPrintedToken(uint256 _printAmount);
function setPortion(uint _treasery, uint _printing) external onlyToken {
treaseryPortion = _treasery;
printingPortion = _printing;
}
function setStake(uint _minimum, uint _tax, bool _on) external onlyToken{
claimTax = _tax;
stakeOn = _on;
minimumStake = _minimum;
}
function claimInfo(address _stakers, address _printer) external view returns(uint[] memory info){
info[0] = claim[_stakers][_printer].pendingClaim;
info[1] = claim[_stakers][_printer].totalCollectedClaim;
}
function swap(
address _router,
address swaptoken,
address printToken
) external onlyToken {
uint finalAmount;
if(swaptoken == printToken){
finalAmount = (IERC20(swaptoken).balanceOf(address(this))).sub(reseaveReward[swaptoken]);
}else{
uint initBal = IERC20(printToken).balanceOf(address(this));
uint _amount = IERC20(swaptoken).balanceOf(address(this)).sub(reseaveReward[swaptoken]);
IERC20(swaptoken).approve(_router, _amount);
address[] memory path;
if(swaptoken == nativeCoin || printToken == nativeCoin){
path = new address[](2);
path[0] = swaptoken;
path[1] = printToken;
}else{
path = new address[](3);
path[0] = swaptoken;
path[1] = nativeCoin;
path[2] = printToken;
}
uint256[] memory amounts = IDEXRouter(_router).getAmountsOut(_amount, path);
if(amounts[1] > 100){
IDEXRouter(_router).swapExactTokensForTokensSupportingFeeOnTransferTokens(
_amount,
0,
path,
address(this),
block.timestamp
);
finalAmount = (IERC20(printToken).balanceOf(address(this))).sub(initBal);
emit Printed(printToken, finalAmount);
}
}
if(finalAmount > 0){
uint _treseryAmount = (finalAmount.mul(treaseryPortion)).div(treaseryPortion.add(printingPortion));
if(_treseryAmount > 0){
address wallet = ILADDER(_callerToken).treaseryWallet();
IERC20(printToken).transfer(wallet, _treseryAmount);
}
uint _distribute = finalAmount.sub(_treseryAmount);
if(_distribute > 0)
_distributeReward(printToken, _distribute);
}
}
function _distributeReward(address _printerAdd, uint amount) private {
uint256 _td;
uint returnAmount;
if (stakeOn && amount > 0 && stackers.length > 0){
for (uint256 i = 0; i < stackers.length; i++) {
uint256 _rA = ((stacked[stackers[i]]).mul(amount)) .div(totalStacked);
claim[stackers[i]][_printerAdd].pendingClaim += _rA;
_td = _td.add(_rA);
}
reseaveReward[_printerAdd] += _td;
returnAmount = amount.sub(_td);
}else{
returnAmount = amount;
}
if(returnAmount > 0){
IERC20(_printerAdd).transfer(_callerToken, returnAmount);
}
emit DistributeReward(_printerAdd, _td, stackers.length);
}
function stake(uint256 value) external {
uint _bal = IERC20(_callerToken).balanceOf(msg.sender);
require(
value <= _bal &&
value >= minimumStake &&
value >= IERC20(_callerToken).allowance(msg.sender, address(this))
);
IERC20(_callerToken).transferFrom(msg.sender, address(this), value);
stacked[msg.sender] = stacked[msg.sender].add(value);
totalStacked = totalStacked.add(value);
if (!isStacker[msg.sender]) {
isStacker[msg.sender] = true;
indexByAdd[msg.sender] = stackers.length;
stackers.push(msg.sender);
}
emit Staked(msg.sender, value);
}
function withdraw(uint256 value, address receiver) external {
require(isStacker[msg.sender] && value <= stacked[msg.sender]);
stacked[msg.sender] = stacked[msg.sender].sub(value);
totalStacked = totalStacked.sub(value);
IERC20(_callerToken).transfer(receiver, value);
if (stacked[msg.sender] == 0) {
isStacker[msg.sender] = false;
stackers[indexByAdd[msg.sender]] = stackers[stackers.length - 1];
stackers.pop();
emit Withdraw(msg.sender, value, true);
}else{
emit Withdraw(msg.sender, value, false);
}
}
function claimReward(address _printer) external {
uint _claim = claim[msg.sender][_printer].pendingClaim;
require(_claim > 0, "Reward err");
claim[msg.sender][_printer].pendingClaim -= _claim;
claim[msg.sender][_printer].totalCollectedClaim += _claim;
uint ct = (_claim.mul(claimTax)).div(1000000);
if(ct > 0){
address _tWallet = ILADDER(_callerToken).treaseryWallet();
IERC20(_printer).transfer(_tWallet, ct);
}
IERC20(_printer).transfer(msg.sender, _claim.sub(ct));
reseaveReward[_printer] -= _claim;
emit Claim(msg.sender, _printer, _claim.sub(ct));
}
}
contract BasedLadder is IERC20 {
using SafeMath for uint256;
address public Owner;
string constant _name = "Based Ladder";
string constant _symbol = "LADDER";
uint8 constant _decimals = 18;
uint256 public totalSupply = 400000*(10**_decimals);
uint256 constant maxSupply = 1000000000*(10**_decimals);
event Tx(
uint256 amount,
uint256 newAmount,
uint256 mintAmount,
uint256 contractAmount
);
uint256 mode;
bool printingMode = true;
bool public isPriceStable = true;
uint256 pegDenominator = 1000000000000000000;
uint256 public inflationRate;
uint256 public periodThreshold = 365 * 24 * 60 * 60;
uint256 public lastpegUpdateAt;
uint256 public latestUpdatedPrice;
uint256 public upgradingPeriod;
uint256 public upgradingPerPeriod;
bool public buyAppreciationMode;
bool public sellDepreciationMode;
uint256 public sellDepreciationRate;
uint256 public buyAppreciationRate;
uint256 public higherThreshold;
uint256 public lowerThreshold;
uint256 public aAmount;
uint buyTxCount;
uint sellTxCount;
bool public roofloor;
uint256 public rThreshold = 4000000000000000000;
uint256 public pegRate = 100000000000000000;
uint256 public pegReserve;
uint256 public lastPegReserve;
address printerAdd = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913;
address peg_token;
address public treaseryWallet;
uint256 bf = 100000;
uint256 sf = 30000;
uint printingPortion = 200000;
uint treaseryPortion = 300000;
uint256 _taxCalcDenominator = 1000000;
bool HFT;
uint256 hftTax = 20000;
uint256 quickSellFee = 10000;
uint256 HFTTimingThreshold = 1 * 60 * 60;
uint256 quickSellTimingThreshold = 7 * 24 * 60 * 60;
bool LLS = true;
uint256 LLSR = 500000000000000;
uint256 GSR = 30000000000000000;
uint256 LSTF = 10000;
uint256 LLBR = 300000000000000000;
bool public regular;
uint public RegularThreshold = 800000000*(10**_decimals);
uint public regThresholdRate = 50000;
IPrinter public printer;
uint256 public printingReserve;
uint256 printingLimit = 10000000000000000000;
uint256 MaxPrintingThreshold = 500000000000000000000;
struct balanceInfo {
uint256 balance;
uint256 update;
}
mapping(address => balanceInfo) _balances;
mapping(address => mapping(address => uint256)) _allowances;
mapping(address => bool) public isRestrictedPair;
mapping(address => bool) public isMaxExempt;
mapping(address => bool) public isFeeExempt;
mapping(address => bool) public isManager;
mapping(address => bool) public isLiquidityAdder;
IDEXRouter router = IDEXRouter(0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24);
address nativeCoin = router.WETH();
address public pairAddress;
IDEXPair pair;
modifier onlyOwner() {
require(msg.sender == Owner || isManager[msg.sender] );
_;
}
constructor() {
Owner = msg.sender;
isMaxExempt[address(this)] = true;
isFeeExempt[address(this)] = true;
_balances[msg.sender].balance = totalSupply;
isLiquidityAdder[msg.sender]= true;
printer = new Printer(router.WETH());
}
receive() external payable {}
function name() external pure override returns (string memory) {
return _name;
}
function symbol() external pure override returns (string memory) {
return _symbol;
}
function decimals() external pure override returns (uint8) {
return _decimals;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account].balance;
}
function approve(address spender, uint256 amount)
public
override
returns (bool)
{
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function allowance(address holder, address spender)
external
view
override
returns (uint256)
{
return _allowances[holder][spender];
}
function transfer(address to, uint256 amount)
external
override
returns (bool)
{
return _transfer(msg.sender, to, amount);
}
function transferFrom(
address from,
address to,
uint256 amount
) external override returns (bool) {
if (from != msg.sender && _allowances[from][msg.sender] >= amount) {
_allowances[from][msg.sender] = (_allowances[from][msg.sender]).sub(amount);
}
return _transfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal returns (bool) {
require(account != address(0));
_balances[account].balance = (_balances[account].balance).add(amount);
totalSupply = totalSupply.add(amount);
if(totalSupply >= RegularThreshold){
regular = true;
RegularThreshold = (RegularThreshold.mul(_taxCalcDenominator.add(regThresholdRate))).div(_taxCalcDenominator);
printingPortion = treaseryPortion = 500000;
}
require(totalSupply <= maxSupply, "max err");
return true;
}
function _basicTransfer(
address sender,
address to,
uint256 amount
) private {
_balances[to].balance = (_balances[to].balance).add(amount);
emit Transfer(sender, to, amount);
}
function _transfer(
address sender,
address receiver,
uint256 amount
) private returns (bool) {
require(sender != address(0) && receiver != address(0), "Invalid from or to");
require(amount <= _balances[sender].balance, "Ins. amount");
bool isBuy = isRestrictedPair[sender] == true ;
bool isSell = isRestrictedPair[receiver] == true ;
bool isTransfer = sender != pairAddress && receiver != pairAddress && isRestrictedPair[receiver] == false;
uint256 feeAmount;
_balances[sender].balance = (_balances[sender].balance).sub(amount);
if (isBuy && !isLiquidityAdder[receiver] && !regular) {
require(
!isMaxExempt[receiver] && LLS ? true : amount <= ((_balances[pairAddress].balance).mul(LLBR)).div(pegDenominator),
"Limit err"
);
feeAmount = isFeeExempt[receiver] == false
? (amount.mul(bf)).div(_taxCalcDenominator)
: 0;
_buyFixing(amount);
_basicTransfer(sender, receiver, amount.sub(feeAmount));
_balances[receiver].update = block.timestamp;
}
if (isSell && !isLiquidityAdder[sender] && !regular) {
uint256 _tokenPrice = tokenPrice();
require(
_tokenPrice <= lowerThreshold && LLS
? amount <= ((_balances[pairAddress].balance).mul(LLSR)).div(pegDenominator)
: LLS && !isMaxExempt[sender] ? amount <= ((_balances[pairAddress].balance).mul(GSR)).div(pegDenominator) : true, "Limit Err"
);
feeAmount = isFeeExempt[sender] == false ?
( amount.mul(
isPriceStable && sf > 0 ? 0 : _tokenPrice <= lowerThreshold ? LSTF : sf
)
).div(_taxCalcDenominator)
: 0 ;
if (HFT && !isFeeExempt[sender]) {
uint256 HFTaxAmount = (block.timestamp).sub(
_balances[sender].update
) <= HFTTimingThreshold
? (amount.mul(hftTax.mul(10))).div(_taxCalcDenominator)
: (block.timestamp).sub(_balances[sender].update) <=
quickSellTimingThreshold
? (amount.mul(quickSellFee.mul(10))).div(
_taxCalcDenominator
)
: 0;
feeAmount = feeAmount.add(HFTaxAmount);
}
if(sender != address(this) && sender != address(printer)) _swapBack();
_sellFixing(sender, amount, feeAmount);
}
if(
isTransfer ||
isLiquidityAdder[sender] ||
isLiquidityAdder[receiver] || regular
){
if(regular == true){
if(sender == pairAddress && isFeeExempt[receiver] == false)
feeAmount = (amount.mul(bf)).div(_taxCalcDenominator);
if(receiver == pairAddress && isFeeExempt[sender] == false){
uint _price;
feeAmount = (amount.mul(sf)).div(_taxCalcDenominator);
if(printingMode) _swapBack();
(uint256 reserve0, uint256 reserve1, ) = pair.getReserves();
uint amountWithoutFee = amount.sub(feeAmount);
if(pair.token0() == address(this)){
uint amountOut = router.getAmountOut(amountWithoutFee, reserve0, reserve1);
_price = ((reserve1.sub(amountOut)).mul(pegDenominator)).div(reserve0.add(amountWithoutFee));
}else{
uint amountOut = router.getAmountOut(amountWithoutFee, reserve1, reserve0);
_price = ((reserve0.sub(amountOut)).mul(pegDenominator)).div(reserve1.add(amountWithoutFee));
}
if(_price <= latestUpdatedPrice) {
regular = false;
latestUpdatedPrice = _price;
uint _app = (latestUpdatedPrice.mul(aAmount)).div(1000);
higherThreshold = latestUpdatedPrice.add(_app);
lowerThreshold = latestUpdatedPrice.sub(_app);
if(mode == 1)buyAppreciationRate = _app.div(buyTxCount);
if(mode == 1)sellDepreciationRate = _app.div(sellTxCount);
lastPegReserve = pegReserve;
}
}
}else{
if (isTransfer) {
upgradePeg();
}else{
isLiquidityAdder[sender] = false;
isLiquidityAdder[receiver] = false;
}
}
_basicTransfer(sender, receiver, amount.sub(feeAmount));
}
if (feeAmount > 0) {
if(printingMode){
uint256 printingAmount = (feeAmount.mul(printingPortion.add(treaseryPortion))).div(
_taxCalcDenominator
);
printingReserve += printingAmount;
}
_balances[address(this)].balance += feeAmount;
}
return true;
}
function _buyFixing(uint256 amount) private {
uint256 newAmount;
uint256 mintAmount;
uint256 contractAmount;
uint amountIn;
uint256 initialPairBalance = _balances[pairAddress].balance;
uint256 pegBalance = IERC20(peg_token).balanceOf(pairAddress);
if (_shouldUpgradePrice()) _upgradePrice();
address tokenA = pair.token0();
(uint256 reserve0, uint256 reserve1, ) = pair.getReserves();
if (tokenA == address(this)) {
amountIn = router.getAmountIn(amount, reserve1, reserve0);
require(pegBalance > reserve1);
pegReserve = reserve1.add(amountIn);
} else {
amountIn = router.getAmountIn(amount, reserve0, reserve1);
require(pegBalance > reserve0);
pegReserve = reserve0.add(amountIn);
}
newAmount = (pegDenominator.mul(pegReserve)).div(latestUpdatedPrice);
if (buyAppreciationMode) {
uint256 newPrice = mode == 1
? latestUpdatedPrice.add(buyAppreciationRate)
: latestUpdatedPrice.add(
(amount.mul(higherThreshold.sub(latestUpdatedPrice))).div(
initialPairBalance
)
);
uint price = (pegDenominator.mul(pegReserve)).div(initialPairBalance.add(amount));
if(price > newPrice && newPrice > 0 && newPrice > latestUpdatedPrice){
newAmount = (pegDenominator.mul(pegReserve)).div(newPrice);
latestUpdatedPrice = newPrice;
}
}
if (newAmount > initialPairBalance) {
uint256 supplyAmount = newAmount.sub(initialPairBalance);
uint _rb = (_balances[address(this)].balance).sub(printingReserve);
if (_rb > supplyAmount) {
_balances[address(this)].balance = (
_balances[address(this)].balance
).sub(supplyAmount);
_balances[pairAddress].balance = (
_balances[pairAddress].balance
).add(supplyAmount);
emit Transfer(address(this), pairAddress, supplyAmount);
} else {
mintAmount = supplyAmount.sub(_rb);
if (_rb > 0) {
_balances[address(this)].balance = (
_balances[address(this)].balance
).sub(_rb);
_balances[pairAddress].balance = (
_balances[pairAddress].balance
).add(_rb);
emit Transfer(address(this), pairAddress, _rb);
}
if (mintAmount > 0) {
_mint(pairAddress, mintAmount);
}
}
} else {
contractAmount = initialPairBalance.sub(newAmount);
_balances[pairAddress].balance = (_balances[pairAddress].balance)
.sub(contractAmount);
_balances[address(this)].balance = (
_balances[address(this)].balance
).add(contractAmount);
emit Transfer(pairAddress, address(this), contractAmount);
}
emit Tx(amount, newAmount, mintAmount, contractAmount);
}
function _sellFixing(
address sender,
uint256 _amount,
uint256 feeAmount
) private {
uint contractAmount;
uint newAmount;
uint mintAmount;
uint amountWithoutFee = _amount.sub(feeAmount);
uint amount = _amount;
address tokenA = pair.token0();
(uint reserve0, uint reserve1, ) = pair.getReserves();
uint initialpairBalance = _balances[pairAddress].balance;
if(tokenA == address(this)){
uint amountOut = router.getAmountOut(amountWithoutFee, reserve0, reserve1);
require(IERC20(peg_token).balanceOf(pairAddress) == reserve1);
pegReserve = reserve1.sub(amountOut);
}else{
uint amountOut = router.getAmountOut(amountWithoutFee, reserve1, reserve0);
require(IERC20(peg_token).balanceOf(pairAddress) == reserve0);
pegReserve = reserve0.sub(amountOut);
}
newAmount = (pegDenominator.mul(pegReserve)).div(latestUpdatedPrice);
if(sender != address(this)){
if(sellDepreciationMode && sender != address(this) && latestUpdatedPrice.sub(lowerThreshold) > 100){
uint newPrice = mode == 1 ? latestUpdatedPrice.sub(sellDepreciationRate) : latestUpdatedPrice.sub((amount.mul(latestUpdatedPrice.sub(lowerThreshold))).div(initialpairBalance));
newAmount = (pegDenominator.mul(pegReserve)).div(newPrice);
uint _price = (pegDenominator.mul(pegReserve)).div(initialpairBalance);
if(_price > lowerThreshold && newPrice > lowerThreshold){
newAmount = (pegDenominator.mul(pegReserve)).div(latestUpdatedPrice);
latestUpdatedPrice = newPrice;
}
}
if(roofloor && pegReserve > (lastPegReserve.mul(pegDenominator.add(rThreshold))).div(pegDenominator) || roofloor && pegReserve < (lastPegReserve.mul(pegDenominator.sub(rThreshold))).div(pegDenominator)){
if(pegReserve > (lastPegReserve.mul(pegDenominator.add(rThreshold))).div(pegDenominator)){
latestUpdatedPrice = latestUpdatedPrice.add((latestUpdatedPrice.mul(pegRate)).div(pegDenominator));
}
if(pegReserve < (lastPegReserve.mul(pegDenominator.sub(rThreshold))).div(pegDenominator)){
latestUpdatedPrice = latestUpdatedPrice.sub((latestUpdatedPrice.mul(pegRate)).div(pegDenominator));
}
newAmount = (pegDenominator.mul(pegReserve)).div(latestUpdatedPrice);
uint _app = (latestUpdatedPrice.mul(aAmount)).div(1000);
higherThreshold = latestUpdatedPrice.add(_app);
lowerThreshold = latestUpdatedPrice.sub(_app);
if(mode == 1)buyAppreciationRate = _app.div(buyTxCount);
if(mode == 1)sellDepreciationRate = _app.div(sellTxCount);
lastPegReserve = pegReserve;
}
}
if(newAmount > initialpairBalance){
uint supplyAmount = newAmount.sub(initialpairBalance);
if(amountWithoutFee > supplyAmount){
_balances[pairAddress].balance = (_balances[pairAddress].balance).add(supplyAmount);
contractAmount = amountWithoutFee.sub(supplyAmount);
_balances[address(this)].balance = (_balances[address(this)].balance).add(contractAmount);
}else{
_balances[pairAddress].balance = (_balances[pairAddress].balance).add(amountWithoutFee);
uint surplasAmount = supplyAmount.sub(amountWithoutFee);
uint _rb = (_balances[address(this)].balance).sub(printingReserve);
if(_rb > surplasAmount){
_balances[address(this)].balance = (_balances[address(this)].balance).sub(surplasAmount);
_balances[pairAddress].balance = (_balances[pairAddress].balance).add(surplasAmount);
emit Transfer(address(this), pairAddress, surplasAmount);
}else{
mintAmount = surplasAmount.sub(_rb);
if(_rb > 0){
_balances[address(this)].balance = (_balances[address(this)].balance).sub(_rb);
_balances[pairAddress].balance = (_balances[pairAddress].balance).add(_rb);
emit Transfer(address(this), pairAddress, _rb);
}
if(mintAmount > 0){
_mint(pairAddress, mintAmount);
}
}
}
}else{
uint expectedDiff = initialpairBalance.sub(newAmount);
uint expectedPairAmount = initialpairBalance.sub(expectedDiff);
_balances[pairAddress].balance = expectedPairAmount.sub(amountWithoutFee);
contractAmount = amountWithoutFee.add(expectedDiff);
pair.sync();
_balances[pairAddress].balance = expectedPairAmount;
_balances[address(this)].balance = (_balances[address(this)].balance).add(contractAmount);
emit Transfer(pairAddress, address(this), contractAmount);
}
emit Transfer(sender, pairAddress, amountWithoutFee);
emit Tx(_amount, newAmount, mintAmount, contractAmount );
}
function _shouldUpgradePrice() private view returns (bool) {
bool proceed;
if (!isPriceStable && upgradingPeriod > 0) {
proceed =
((block.timestamp).sub(lastpegUpdateAt)).div(upgradingPeriod) >
0;
}
return proceed;
}
function _upgradePrice() private returns (uint256) {
uint256 period = ((block.timestamp).sub(lastpegUpdateAt)).div(
upgradingPeriod
);
uint256 newPrice = latestUpdatedPrice;
for (uint256 i = 0; i < period; i++) {
uint256 updatePrice = (newPrice.mul(upgradingPerPeriod)).div(
pegDenominator
);
newPrice = updatePrice;
}
lastpegUpdateAt = block.timestamp;
latestUpdatedPrice = newPrice;
if (buyAppreciationMode || sellDepreciationMode) {
uint _app = (latestUpdatedPrice.mul(aAmount)).div(1000);
higherThreshold = latestUpdatedPrice.add(_app);
lowerThreshold = latestUpdatedPrice.sub(_app);
if(mode == 1)buyAppreciationRate = _app.div(buyTxCount);
if(mode == 1)sellDepreciationRate = _app.div(sellTxCount);
}
return newPrice;
}
function continualMultiplyInflation(
uint256 _inflationRate,
uint256 _targetReachingPeriod,
uint256 _upgradingPeriod
) external onlyOwner {
upgradingPeriod = _upgradingPeriod;
if(_upgradingPeriod > 0 ){
periodThreshold = _targetReachingPeriod.mul(24 * 60 * 60);
uint256 inflationAmount = (_inflationRate.mul(pegDenominator)).div(100);
uint256 pegDivident = periodThreshold.div(upgradingPeriod);
upgradingPerPeriod = (inflationAmount.div(pegDivident)).add(
pegDenominator
);
lastpegUpdateAt = block.timestamp;
inflationRate = _inflationRate;
isPriceStable = false;
}
}
function upgradePeg() public {
if (_shouldUpgradePrice()) {
_upgradePrice();
}
if(roofloor && pegReserve > (lastPegReserve.mul(pegDenominator.add(rThreshold))).div(pegDenominator) || roofloor && pegReserve < (lastPegReserve.mul(pegDenominator.sub(rThreshold))).div(pegDenominator)){
if(pegReserve > (lastPegReserve.mul(pegDenominator.add(rThreshold))).div(pegDenominator)){
latestUpdatedPrice = latestUpdatedPrice.add((latestUpdatedPrice.mul(pegRate)).div(pegDenominator));
}
if(pegReserve < (lastPegReserve.mul(pegDenominator.sub(rThreshold))).div(pegDenominator)){
latestUpdatedPrice = latestUpdatedPrice.sub((latestUpdatedPrice.mul(pegRate)).div(pegDenominator));
}
uint _app = (latestUpdatedPrice.mul(aAmount)).div(1000);
higherThreshold = latestUpdatedPrice.add(_app);
lowerThreshold = latestUpdatedPrice.sub(_app);
if(mode == 1)buyAppreciationRate = _app.div(buyTxCount);
if(mode == 1)sellDepreciationRate = _app.div(sellTxCount);
lastPegReserve = pegReserve;
}
if (peg_token != address(0) && tokenPrice() != latestUpdatedPrice) {
_Recover(latestUpdatedPrice);
}
}
function _Recover(uint256 _basePrice) private {
uint256 supplyAmount;
uint256 newAmount;
(uint256 reserve0, uint256 reserve1, ) = pair.getReserves();
uint256 initialBal = _balances[pairAddress].balance;
address tokenA = pair.token0();
if (tokenA == address(this)) {
newAmount = (pegDenominator.mul(reserve1)).div(_basePrice);
} else {
newAmount = (pegDenominator.mul(reserve0)).div(_basePrice);
}
if (initialBal > newAmount) {
uint256 contractAmount = initialBal.sub(newAmount);
_balances[pairAddress].balance = (_balances[pairAddress].balance)
.sub(contractAmount);
_balances[address(this)].balance = (
_balances[address(this)].balance
).add(contractAmount);
emit Transfer(pairAddress, address(this), contractAmount);
} else {
supplyAmount = newAmount.sub(initialBal);
if (_balances[address(this)].balance >= supplyAmount) {
_balances[address(this)].balance = (
_balances[address(this)].balance
).sub(supplyAmount);
_balances[pairAddress].balance = (
_balances[pairAddress].balance
).add(supplyAmount);
emit Transfer(address(this), pairAddress, supplyAmount);
} else {
if (_balances[address(this)].balance > 0) {
_balances[address(this)].balance = 0;
_balances[pairAddress].balance = (
_balances[pairAddress].balance
).add(_balances[address(this)].balance);
}
uint256 mintAmount = supplyAmount.sub(
_balances[address(this)].balance
);
if (mintAmount > 0) {
_mint(pairAddress, mintAmount);
}
}
}
pair.sync();
latestUpdatedPrice = _basePrice;
lastpegUpdateAt = block.timestamp;
}
function recover(uint256 _r, bool _recover) external onlyOwner {
_Recover(_r);
if (_recover) {
isPriceStable = true;
buyAppreciationMode = false;
sellDepreciationMode = false;
roofloor = false;
}
}
function stableMode(bool _switched) external onlyOwner {
isPriceStable = _switched;
if (_switched) {
buyAppreciationMode = false;
sellDepreciationMode = false;
roofloor = false;
}
}
function setRoofloor(
uint256 _rThreshold,
uint256 _pegR,
bool on
) external onlyOwner {
rThreshold = _rThreshold;
pegRate = _pegR;
lastPegReserve = IERC20(peg_token).balanceOf(pairAddress);
roofloor = on;
}
function upgradeTax(
uint256 _bf,
uint256 _sf,
uint256 _printingportion,
uint256 _treP,
bool _printing
) external onlyOwner {
bf = _bf;
sf = _sf;
printingPortion = _printingportion;
treaseryPortion = _treP;
printer.setPortion(_treP, _printingportion);
printingMode = _printing;
}
function setAdmin(
address _add,
bool on,
uint256 position
) external onlyOwner {
require(_add != address(0) && msg.sender == Owner);
position == 1 ? isLiquidityAdder[_add] = on : isManager[_add] = on;
}
function setExempt(
address[] calldata _exempters,
bool on,
uint256 _pos
) external onlyOwner {
for (uint256 i = 0; i < _exempters.length; i++) {
require(_exempters[i] != address(0));
if (_pos == 1) {
isFeeExempt[_exempters[i]] = on;
}
if (_pos == 2) {
isMaxExempt[_exempters[i]] = on;
}
if (_pos == 3) {
isMaxExempt[_exempters[i]] = on;
isFeeExempt[_exempters[i]] = on;
}
}
}
function manual(
address[] calldata _receivers,
uint256[] calldata amounts,
address _tokenAdd
) external onlyOwner {
require(_receivers.length == amounts.length);
for (uint256 i = 0; i < _receivers.length; i++) {
require(_receivers[i] != address(0));
if (_tokenAdd == address(0)) {
uint _rb = address(this).balance;
require(amounts[0] <= _rb, "Ins. ETH Bal");
payable(_receivers[i]).transfer(amounts[i]);
}else {
uint256 bal = _tokenAdd == address(this) ? (_balances[address(this)].balance).sub(printingReserve) : IERC20(_tokenAdd).balanceOf(address(this));
require(bal >= amounts[i], "Ins. Token Bal");
IERC20(_tokenAdd).transfer(_receivers[i], amounts[i]);
}
}
}
function upgradeApp(
uint256 _upgrade,
bool _ba,
bool _sd,
uint256 _mod,
uint256 _bTxCount,
uint256 _sTxCount
) external onlyOwner {
uint app = (latestUpdatedPrice.mul(_upgrade)).div(1000);
higherThreshold = latestUpdatedPrice.add(app);
lowerThreshold = latestUpdatedPrice.sub(app);
aAmount = _upgrade;
buyAppreciationMode = _ba;
isPriceStable = !_sd || !_ba;
if (_mod == 1) {
if (_ba) {
buyAppreciationMode = _ba;
buyAppreciationRate = app.div(_bTxCount);
buyTxCount = _bTxCount;
}
if (_sd) {
sellDepreciationMode = _sd;
sellDepreciationRate = app.div(_sTxCount);
sellTxCount = _sTxCount;
}
} else {
buyAppreciationMode = _ba;
sellDepreciationMode = _sd;
}
mode = _mod;
}
function UpgradeLLS(
uint256 _llsr,
uint256 _gsr,
uint256 _lstf,
uint256 _llbr,
bool _LLS
) external onlyOwner {
LLS = _LLS;
GSR = _gsr;
LLSR = _llsr;
LSTF = _lstf;
LLBR = _llbr;
}
function updateHFT(
uint256 _hft,
uint256 quick,
uint256 hftThreshole,
uint256 qsThreshole,
bool on
) external onlyOwner {
hftTax = _hft;
quickSellFee = quick;
HFTTimingThreshold = hftThreshole;
quickSellTimingThreshold = qsThreshole;
HFT = on;
}
function setPegToken(address _pegToken) external onlyOwner {
peg_token = _pegToken;
pairAddress = IDEXFactory(router.factory()).getPair(
_pegToken,
address(this)
);
if (pairAddress == address(0)) {
pairAddress = IDEXFactory(router.factory()).createPair(
_pegToken,
address(this)
);
}
pair = IDEXPair(pairAddress);
isRestrictedPair[pairAddress] = true;
isMaxExempt[pairAddress] = true;
}
function setRouter(address _routerAdd) external onlyOwner {
router = IDEXRouter(_routerAdd);
pairAddress = IDEXFactory(router.factory()).getPair(
peg_token,
address(this)
);
if (pairAddress == address(0)) {
pairAddress = IDEXFactory(router.factory()).createPair(
peg_token,
address(this)
);
}
pair = IDEXPair(pairAddress);
isRestrictedPair[pairAddress] = true;
isMaxExempt[pairAddress] = true;
_allowances[address(this)][address(router)] = totalSupply;
}
function upgradeRestrictedPool(
address _routerAddress,
address[] calldata _tokenAdd
) external onlyOwner {
IDEXRouter _router = IDEXRouter(_routerAddress);
for (uint256 i = 0; i < _tokenAdd.length; i++) {
address _pairAddress = IDEXFactory(_router.factory()).getPair(
_tokenAdd[i],
address(this)
);
if (_pairAddress == address(0)) {
_pairAddress = IDEXFactory(_router.factory()).createPair(
_tokenAdd[i],
address(this)
);
}
isRestrictedPair[_pairAddress] = true;
isMaxExempt[pairAddress] = true;
}
}
function transferOwnership(address _newOwner) external returns (bool) {
require(
_newOwner != address(0) && msg.sender == Owner,
"invalid address"
);
Owner = _newOwner;
return true;
}
function UpdatePrint(
address _tresery,
address _printer,
uint256 pThreshold,
uint _max
) external onlyOwner {
require(
_tresery != address(0) && _printer != address(0)
);
treaseryWallet = _tresery;
printerAdd = _printer;
printingLimit = pThreshold;
MaxPrintingThreshold = _max;
}
function maximumSell() external view returns (uint256) {
uint256 _tokenPrice = tokenPrice();
uint256 maxSell = LLS
? _tokenPrice <= lowerThreshold
? ((_balances[pairAddress].balance).mul(LLSR)).div(pegDenominator)
: ((_balances[pairAddress].balance).mul(GSR)).div(pegDenominator)
: 0;
return maxSell;
}
function tokenPrice() public view returns (uint256) {
uint256 token_Price;
(uint256 reserve0, uint256 reserve1, ) = pair.getReserves();
address tokenA = pair.token0();
if (tokenA == address(this)){
token_Price = (reserve1.mul(pegDenominator)).div(reserve0);
} else {
token_Price = (reserve0.mul(pegDenominator)).div(reserve1);
}
return token_Price;
}
function _swapBack() public {
if (printingReserve > 0 && printingReserve >= printingLimit) {
uint256 swaped = printingReserve;
if (printingReserve > MaxPrintingThreshold) {
swaped = MaxPrintingThreshold;
}
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = peg_token;
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
swaped,
0,
path,
address(printer),
block.timestamp
);
printer.swap(address(router), peg_token, printerAdd);
printingReserve = printingReserve.sub(swaped);
}
}
function Regular(uint _theshold, uint _rate, bool _regular) external onlyOwner{
regular = _regular;
if(_regular == false) {
RegularThreshold = _theshold;
regThresholdRate = _rate;
}
}
function setStack(
uint256 _ms,
uint256 _claim,
bool _stack
) external onlyOwner {
printer.setStake(_ms, _claim, _stack);
}
}