Transaction Hash:
Block:
12547358 at Jun-01-2021 08:01:55 AM +UTC
Transaction Fee:
0.0018001368 ETH
$3.83
Gas Used:
96,264 Gas / 18.7 Gwei
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
|
0x06B8C588...834c8706E
Miner
| (Mining Express) | 173.20188503650317446 Eth | 173.20368517330317446 Eth | 0.0018001368 | |
| 0x4437C517...4Ec585930 |
0.011629092128483216 Eth
Nonce: 21
|
0.009828955328483216 Eth
Nonce: 22
| 0.0018001368 |
Execution Trace
FEGwETH.BUY( tokenIn=0xf786c34106762Ab4Eeb45a51B42a62470E9D5332, tokenAmountIn=153800000000000000, tokenOut=0x389999216860AB8E0175387A0c90E5c52522C945, minAmountOut=1000, maxPrice=100000000000000000000000000 ) => ( tokenAmountOut=35408467139433450592217433187231851964531694900788300625387963629091585785856, spotPriceAfter=17 )
-
TRYfinance.transferFrom( sender=0x4437C517F1ddaEb22Bff670eD31f02E4Ec585930, recipient=0x7cBFA36d57e5fb9723d715787049D2101C323347, amount=153800000000000000 )
BUY[FEGwETH (ln:962)]
bmul[FEGwETH (ln:983)]calcSpotPrice[FEGwETH (ln:985)]calcOutGivenIn[FEGwETH (ln:995)]calcReservesFromFee[FEGwETH (ln:1005)]calcSpotPrice[FEGwETH (ln:1007)]bdiv[FEGwETH (ln:1016)]LOG_SWAP[FEGwETH (ln:1018)]badd[FEGwETH (ln:1020)]LOG_ADD_RESERVES[FEGwETH (ln:1021)]_pullUnderlying[FEGwETH (ln:1023)]transferFrom[FEGwETH (ln:1340)]
_pushUnderlying[FEGwETH (ln:1024)]transfer[FEGwETH (ln:1347)]
balanceOf[FEGwETH (ln:1025)]balanceOf[FEGwETH (ln:1026)]
File 1 of 2: FEGwETH
File 2 of 2: TRYfinance
pragma solidity 0.7.6;
// SPDX-License-Identifier: UNLICENSED
/*
* Must wrap your ETH for fETH to use FEGex DEX
Built for fETH - FEG Wapped ETH - Built in 1% frictionless rewards of ETH! Stake ETH with fETHand earn rewards!
*/
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
contract FSilver {
function getColor()
external pure
returns (bytes32) {
return bytes32("BRONZE");
}
}
contract FConst is FSilver, ReentrancyGuard {
uint public constant BASE = 10**18;
uint public constant MIN_BOUND_TOKENS = 2;
uint public constant MAX_BOUND_TOKENS = 8;
uint public constant MIN_FEE = 2000000000000000;
uint public constant MAX_FEE = 2000000000000000; // FREE BUYS
uint public constant EXIT_FEE = BASE / 200;
uint public constant DEFAULT_RESERVES_RATIO = 0;
uint public constant MIN_WEIGHT = BASE;
uint public constant MAX_WEIGHT = BASE * 50;
uint public constant MAX_TOTAL_WEIGHT = BASE * 50;
uint public constant MIN_BALANCE = BASE / 10**12;
uint public constant INIT_POOL_SUPPLY = BASE * 100;
uint public SM = 10;
uint public M1 = 10;
address public FEGstake = 0x4c9BC793716e8dC05d1F48D8cA8f84318Ec3043C;
uint public constant MIN_BPOW_BASE = 1 wei;
uint public constant MAX_BPOW_BASE = (2 * BASE) - 1 wei;
uint public constant BPOW_PRECISION = BASE / 10**10;
uint public constant MAX_IN_RATIO = BASE / 2;
uint public constant MAX_OUT_RATIO = (BASE / 3) + 1 wei;
uint public MAX_SELL_RATIO = BASE / SM;
uint public MAX_1_RATIO = BASE / M1;
}
contract FNum is ReentrancyGuard, FConst {
function btoi(uint a)
internal pure
returns (uint)
{
return a / BASE;
}
function bfloor(uint a)
internal pure
returns (uint)
{
return btoi(a) * BASE;
}
function badd(uint a, uint b)
internal pure
returns (uint)
{
uint c = a + b;
require(c >= a, "ERR_ADD_OVERFLOW");
return c;
}
function bsub(uint a, uint b)
internal pure
returns (uint)
{
(uint c, bool flag) = bsubSign(a, b);
require(!flag, "ERR_SUB_UNDERFLOW");
return c;
}
function bsubSign(uint a, uint b)
internal pure
returns (uint, bool)
{
if (a >= b) {
return (a - b, false);
} else {
return (b - a, true);
}
}
function bmul(uint a, uint b)
internal pure
returns (uint)
{
uint c0 = a * b;
require(a == 0 || c0 / a == b, "ERR_MUL_OVERFLOW");
uint c1 = c0 + (BASE / 2);
require(c1 >= c0, "ERR_MUL_OVERFLOW");
uint c2 = c1 / BASE;
return c2;
}
function bdiv(uint a, uint b)
internal pure
returns (uint)
{
require(b != 0, "ERR_DIV_ZERO");
uint c0 = a * BASE;
require(a == 0 || c0 / a == BASE, "ERR_DIV_INTERNAL"); // bmul overflow
uint c1 = c0 + (b / 2);
require(c1 >= c0, "ERR_DIV_INTERNAL"); // badd require
uint c2 = c1 / b;
return c2;
}
// DSMath.wpow
function bpowi(uint a, uint n)
internal pure
returns (uint)
{
uint z = n % 2 != 0 ? a : BASE;
for (n /= 2; n != 0; n /= 2) {
a = bmul(a, a);
if (n % 2 != 0) {
z = bmul(z, a);
}
}
return z;
}
function bpow(uint base, uint exp)
internal pure
returns (uint)
{
require(base >= MIN_BPOW_BASE, "ERR_BPOW_BASE_TOO_LOW");
require(base <= MAX_BPOW_BASE, "ERR_BPOW_BASE_TOO_HIGH");
uint whole = bfloor(exp);
uint remain = bsub(exp, whole);
uint wholePow = bpowi(base, btoi(whole));
if (remain == 0) {
return wholePow;
}
uint partialResult = bpowApprox(base, remain, BPOW_PRECISION);
return bmul(wholePow, partialResult);
}
function bpowApprox(uint base, uint exp, uint precision)
internal pure
returns (uint)
{
// term 0:
uint a = exp;
(uint x, bool xneg) = bsubSign(base, BASE);
uint term = BASE;
uint sum = term;
bool negative = false;
for (uint i = 1; term >= precision; i++) {
uint bigK = i * BASE;
(uint c, bool cneg) = bsubSign(a, bsub(bigK, BASE));
term = bmul(term, bmul(c, x));
term = bdiv(term, bigK);
if (term == 0) break;
if (xneg) negative = !negative;
if (cneg) negative = !negative;
if (negative) {
sum = bsub(sum, term);
} else {
sum = badd(sum, term);
}
}
return sum;
}
}
contract FMath is FSilver, FConst, FNum {
function calcSpotPrice(
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenWeightOut,
uint swapFee
)
public pure
returns (uint spotPrice)
{
uint numer = bdiv(tokenBalanceIn, tokenWeightIn);
uint denom = bdiv(tokenBalanceOut, tokenWeightOut);
uint ratio = bdiv(numer, denom);
uint scale = bdiv(BASE, bsub(BASE, swapFee));
return (spotPrice = bmul(ratio, scale));
}
function calcOutGivenIn(
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenAmountIn,
uint swapFee
)
public pure
returns (uint tokenAmountOut, uint tokenInFee)
{
uint weightRatio = bdiv(tokenWeightIn, tokenWeightOut);
uint adjustedIn = bsub(BASE, swapFee);
adjustedIn = bmul(tokenAmountIn, adjustedIn);
uint y = bdiv(tokenBalanceIn, badd(tokenBalanceIn, adjustedIn));
uint foo = bpow(y, weightRatio);
uint bar = bsub(BASE, foo);
tokenAmountOut = bmul(tokenBalanceOut, bar);
tokenInFee = bsub(tokenAmountIn, adjustedIn);
return (tokenAmountOut, tokenInFee);
}
function calcInGivenOut(
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenAmountOut,
uint swapFee
)
public pure
returns (uint tokenAmountIn, uint tokenInFee)
{
uint weightRatio = bdiv(tokenWeightOut, tokenWeightIn);
uint diff = bsub(tokenBalanceOut, tokenAmountOut);
uint y = bdiv(tokenBalanceOut, diff);
uint foo = bpow(y, weightRatio);
foo = bsub(foo, BASE);
foo = bmul(tokenBalanceIn, foo);
tokenAmountIn = bsub(BASE, swapFee);
tokenAmountIn = bdiv(foo, tokenAmountIn);
tokenInFee = bdiv(foo, BASE);
tokenInFee = bsub(tokenAmountIn, tokenInFee);
return (tokenAmountIn, tokenInFee);
}
function calcPoolOutGivenSingleIn(
uint tokenBalanceIn,
uint tokenWeightIn,
uint poolSupply,
uint totalWeight,
uint tokenAmountIn,
uint swapFee,
uint reservesRatio
)
public pure
returns (uint poolAmountOut, uint reserves)
{
uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
uint zaz = bmul(bsub(BASE, normalizedWeight), swapFee);
uint tokenAmountInAfterFee = bmul(tokenAmountIn, bsub(BASE, zaz));
reserves = calcReserves(tokenAmountIn, tokenAmountInAfterFee, reservesRatio);
uint newTokenBalanceIn = badd(tokenBalanceIn, tokenAmountInAfterFee);
uint tokenInRatio = bdiv(newTokenBalanceIn, tokenBalanceIn);
uint poolRatio = bpow(tokenInRatio, normalizedWeight);
uint newPoolSupply = bmul(poolRatio, poolSupply);
poolAmountOut = bsub(newPoolSupply, poolSupply);
return (poolAmountOut, reserves);
}
function calcSingleOutGivenPoolIn(
uint tokenBalanceOut,
uint tokenWeightOut,
uint poolSupply,
uint totalWeight,
uint poolAmountIn,
uint swapFee
)
public pure
returns (uint tokenAmountOut)
{
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
uint poolAmountInAfterExitFee = bmul(poolAmountIn, bsub(BASE, EXIT_FEE));
uint newPoolSupply = bsub(poolSupply, poolAmountInAfterExitFee);
uint poolRatio = bdiv(newPoolSupply, poolSupply);
uint tokenOutRatio = bpow(poolRatio, bdiv(BASE, normalizedWeight));
uint newTokenBalanceOut = bmul(tokenOutRatio, tokenBalanceOut);
uint tokenAmountOutBeforeSwapFee = bsub(tokenBalanceOut, newTokenBalanceOut);
uint zaz = bmul(bsub(BASE, normalizedWeight), swapFee);
tokenAmountOut = bmul(tokenAmountOutBeforeSwapFee, bsub(BASE, zaz));
return tokenAmountOut;
}
function calcPoolInGivenSingleOut(
uint tokenBalanceOut,
uint tokenWeightOut,
uint poolSupply,
uint totalWeight,
uint tokenAmountOut,
uint swapFee,
uint reservesRatio
)
public pure
returns (uint poolAmountIn, uint reserves)
{
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
uint zar = bmul(bsub(BASE, normalizedWeight), swapFee);
uint tokenAmountOutBeforeSwapFee = bdiv(tokenAmountOut, bsub(BASE, zar));
reserves = calcReserves(tokenAmountOutBeforeSwapFee, tokenAmountOut, reservesRatio);
uint newTokenBalanceOut = bsub(tokenBalanceOut, tokenAmountOutBeforeSwapFee);
uint tokenOutRatio = bdiv(newTokenBalanceOut, tokenBalanceOut);
uint poolRatio = bpow(tokenOutRatio, normalizedWeight);
uint newPoolSupply = bmul(poolRatio, poolSupply);
uint poolAmountInAfterExitFee = bsub(poolSupply, newPoolSupply);
poolAmountIn = bdiv(poolAmountInAfterExitFee, bsub(BASE, EXIT_FEE));
return (poolAmountIn, reserves);
}
function calcReserves(uint amountWithFee, uint amountWithoutFee, uint reservesRatio)
internal pure
returns (uint reserves)
{
require(amountWithFee >= amountWithoutFee, "ERR_MATH_APPROX");
require(reservesRatio <= BASE, "ERR_INVALID_RESERVE");
uint swapFeeAndReserves = bsub(amountWithFee, amountWithoutFee);
reserves = bmul(swapFeeAndReserves, reservesRatio);
require(swapFeeAndReserves >= reserves, "ERR_MATH_APPROX");
}
function calcReservesFromFee(uint fee, uint reservesRatio)
internal pure
returns (uint reserves)
{
require(reservesRatio <= BASE, "ERR_INVALID_RESERVE");
reserves = bmul(fee, reservesRatio);
}
}
// Highly opinionated token implementation
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address whom) external view returns (uint);
function allowance(address src, address dst) external view returns (uint);
function approve(address dst, uint amt) external returns (bool);
function transfer(address dst, uint amt) external returns (bool);
function transferFrom(
address src, address dst, uint amt
) external returns (bool);
}
contract FTokenBase is ReentrancyGuard, FNum {
mapping(address => uint) internal _balance;
mapping(address => mapping(address=>uint)) internal _allowance;
uint internal _totalSupply;
event Approval(address indexed src, address indexed dst, uint amt);
event Transfer(address indexed src, address indexed dst, uint amt);
function _mint(uint amt) internal {
_balance[address(this)] = badd(_balance[address(this)], amt);
_totalSupply = badd(_totalSupply, amt);
emit Transfer(address(0), address(this), amt);
}
function _burn(uint amt) internal {
require(_balance[address(this)] >= amt);
_balance[address(this)] = bsub(_balance[address(this)], amt);
_totalSupply = bsub(_totalSupply, amt);
emit Transfer(address(this), address(0), amt);
}
function _move(address src, address dst, uint amt) internal {
require(_balance[src] >= amt);
_balance[src] = bsub(_balance[src], amt);
_balance[dst] = badd(_balance[dst], amt);
emit Transfer(src, dst, amt);
}
function _push(address to, uint amt) internal {
_move(address(this), to, amt);
}
function _pull(address from, uint amt) internal {
_move(from, address(this), amt);
}
}
contract FToken is ReentrancyGuard, FTokenBase {
string private _name = "FEGwETHpair";
string private _symbol = "FEGwETHLP";
uint8 private _decimals = 18;
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns(uint8) {
return _decimals;
}
function allowance(address src, address dst) external view returns (uint) {
return _allowance[src][dst];
}
function balanceOf(address whom) external view returns (uint) {
return _balance[whom];
}
function totalSupply() public view returns (uint) {
return _totalSupply;
}
function approve(address dst, uint amt) external returns (bool) {
_allowance[msg.sender][dst] = amt;
emit Approval(msg.sender, dst, amt);
return true;
}
function increaseApproval(address dst, uint amt) external returns (bool) {
_allowance[msg.sender][dst] = badd(_allowance[msg.sender][dst], amt);
emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
return true;
}
function decreaseApproval(address dst, uint amt) external returns (bool) {
uint oldValue = _allowance[msg.sender][dst];
if (amt > oldValue) {
_allowance[msg.sender][dst] = 0;
} else {
_allowance[msg.sender][dst] = bsub(oldValue, amt);
}
emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
return true;
}
function transfer(address dst, uint amt) external returns (bool) {
FEGwETH ulock;
bool getlock = ulock.getUserLock(msg.sender);
require(getlock == true, 'Liquidity is locked, you cannot removed liquidity until after lock time.');
_move(msg.sender, dst, amt);
return true;
}
function transferFrom(address src, address dst, uint amt) external returns (bool) {
require(msg.sender == src || amt <= _allowance[src][msg.sender]);
FEGwETH ulock;
bool getlock = ulock.getUserLock(msg.sender);
require(getlock == true, 'Transfer is Locked ');
_move(src, dst, amt);
if (msg.sender != src && _allowance[src][msg.sender] != uint256(-1)) {
_allowance[src][msg.sender] = bsub(_allowance[src][msg.sender], amt);
emit Approval(msg.sender, dst, _allowance[src][msg.sender]);
}
return true;
}
}
contract FEGwETH is FSilver, ReentrancyGuard, FToken, FMath {
struct Record {
bool bound; // is token bound to pool
uint index; // private
uint denorm; // denormalized weight
uint balance;
}
struct userLock {
bool setLock; // true = locked, false=unlocked
uint unlockTime;
}
function getUserLock(address usr) public view returns(bool lock){
return _userlock[usr].setLock;
}
event LOG_SWAP(
address indexed caller,
address indexed tokenIn,
address indexed tokenOut,
uint256 tokenAmountIn,
uint256 tokenAmountOut,
uint256 reservesAmount
);
event LOG_JOIN(
address indexed caller,
address indexed tokenIn,
uint256 tokenAmountIn,
uint256 reservesAmount
);
event LOG_EXIT(
address indexed caller,
address indexed tokenOut,
uint256 tokenAmountOut,
uint256 reservesAmount
);
event LOG_CLAIM_RESERVES(
address indexed caller,
address indexed tokenOut,
uint256 tokenAmountOut
);
event LOG_ADD_RESERVES(
address indexed token,
uint256 reservesAmount
);
event LOG_CALL(
bytes4 indexed sig,
address indexed caller,
bytes data
) anonymous;
modifier _logs_() {
emit LOG_CALL(msg.sig, msg.sender, msg.data);
_;
}
modifier _lock_() {
require(!_mutex);
_mutex = true;
_;
_mutex = false;
}
modifier _viewlock_() {
require(!_mutex);
_;
}
bool private _mutex;
address private _factory = 0x4c9BC793716e8dC05d1F48D8cA8f84318Ec3043C; // BFactory address to push token exitFee to
address private _controller = 0x4c9BC793716e8dC05d1F48D8cA8f84318Ec3043C; // has CONTROL role
address private _poolOwner;
address public fETH = 0xf786c34106762Ab4Eeb45a51B42a62470E9D5332;
address public FEG = 0x389999216860AB8E0175387A0c90E5c52522C945;
address public pairRewardPool = 0x4c9BC793716e8dC05d1F48D8cA8f84318Ec3043C;
bool private _publicSwap; // true if PUBLIC can call SWAP functions
// `setSwapFee` and `Launch' require CONTROL
// `Launch` sets `PUBLIC can SWAP`, `PUBLIC can JOIN`
uint private _swapFee;
uint private _reservesRatio;
bool private _launched;
address[] private _tokens;
mapping(address=>Record) private _records;
mapping(address=>userLock) public _userlock;
mapping(address=>uint) public totalReserves;
mapping(address=>bool) public whiteListContract;
uint private _totalWeight;
constructor() {
_poolOwner = msg.sender;
_swapFee = MIN_FEE;
_reservesRatio = DEFAULT_RESERVES_RATIO;
_publicSwap = false;
_launched = false;
}
function isContract(address account) internal view returns (bool) {
if(IsWhiteListContract(account)) { return false; }
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != 0x0 && codehash != accountHash);
}
function addWhiteListContract(address _addy, bool boolean) public {
require(msg.sender == _controller);
require(_addy != address(0), "setting 0 address;;");
whiteListContract[_addy] = boolean;
}
function IsWhiteListContract(address _addy) public view returns(bool){
require(_addy != address(0), "setting 0 address;;");
return whiteListContract[_addy];
}
modifier noContract() {
require(isContract(msg.sender) == false, 'Unapproved contracts are not allowed to interact with the swap');
_;
}
function setMaxSellRatio(uint256 _amount) public {
require(msg.sender == _poolOwner, "You do not have permission");
require (_amount > 0, "cannot turn off");
require (_amount <= 100, "cannot set under 1%");
SM = _amount;
}
function setMax1SideLiquidityRatio(uint256 _amount) public {
require(msg.sender == _poolOwner, "You do not have permission");
require (_amount > 10, "cannot set over 10%");
require (_amount <= 200, "cannot set under 0.5%");
M1 = _amount;
}
function setStakePool(address _addy) public {
require(msg.sender == _controller);
FEGstake = _addy;
}
function setPairRewardPool(address _addy) public {
require(msg.sender == _controller);
pairRewardPool = _addy;
}
function isPublicSwap()
external view
returns (bool)
{
return _publicSwap;
}
function isBound(address t)
external view
returns (bool)
{
return _records[t].bound;
}
function getFinalTokens()
external view
_viewlock_
returns (address[] memory tokens)
{
require(_launched);
return _tokens;
}
function getDenormalizedWeight(address token)
external view
_viewlock_
returns (uint)
{
require(_records[token].bound);
return _records[token].denorm;
}
function getTotalDenormalizedWeight()
external view
_viewlock_
returns (uint)
{
return _totalWeight;
}
function getNormalizedWeight(address token)
external view
_viewlock_
returns (uint)
{
require(_records[token].bound);
uint denorm = _records[token].denorm;
return bdiv(denorm, _totalWeight);
}
function getBalance(address token)
external view
_viewlock_
returns (uint)
{
require(_records[token].bound);
return _records[token].balance;
}
function getSwapFee()
external view
_viewlock_
returns (uint)
{
return _swapFee;
}
function getController()
external view
_viewlock_
returns (address)
{
return _controller;
}
function setController(address manager)
external
_logs_
_lock_
{
require(msg.sender == _controller);
_controller = manager;
}
function Launch()
external
_logs_
_lock_
{
require(msg.sender == _poolOwner);
require(!_launched);
require(_tokens.length >= MIN_BOUND_TOKENS);
_launched = true;
_publicSwap = true;
_mintPoolShare(INIT_POOL_SUPPLY);
_pushPoolShare(msg.sender, INIT_POOL_SUPPLY);
}
function AddTokenInitial(address token, uint balance, uint denorm)
external
_logs_
// _lock_ Bind does not lock because it jumps to `rebind`, which does
{
require(msg.sender == _poolOwner);
require(!_records[token].bound);
require(!_launched);
require(_tokens.length < MAX_BOUND_TOKENS);
_records[token] = Record({
bound: true,
index: _tokens.length,
denorm: 0, // balance and denorm will be validated
balance: 0 // and set by `rebind`
//locktime: block.timestamp
});
_tokens.push(token);
rebind(token, balance * 98/100, denorm);
}
function AddfETHInitial(address token, uint balance, uint denorm)
external
_logs_
// _lock_ Bind does not lock because it jumps to `rebind`, which does
{
require(token == fETH);
require(msg.sender == _poolOwner);
require(!_records[token].bound);
require(!_launched);
require(_tokens.length < MAX_BOUND_TOKENS);
_records[token] = Record({
bound: true,
index: _tokens.length,
denorm: 0, // balance and denorm will be validated
balance: 0 // and set by `rebind`
//locktime: block.timestamp
});
_tokens.push(token);
rebind(token, balance * 99/100, denorm);
}
function rebind(address token, uint balance, uint denorm)
public
_logs_
_lock_
{
require(msg.sender == _poolOwner);
require(_records[token].bound);
require(!_launched);
require(denorm >= MIN_WEIGHT);
require(denorm <= MAX_WEIGHT);
require(balance >= MIN_BALANCE);
// Adjust the denorm and totalWeight
uint oldWeight = _records[token].denorm;
if (denorm > oldWeight) {
_totalWeight = badd(_totalWeight, bsub(denorm, oldWeight));
require(_totalWeight <= MAX_TOTAL_WEIGHT);
} else if (denorm < oldWeight) {
_totalWeight = bsub(_totalWeight, bsub(oldWeight, denorm));
}
_records[token].denorm = denorm;
// Adjust the balance record and actual token balance
uint oldBalance = _records[token].balance;
_records[token].balance = balance;
if (balance > oldBalance) {
_pullUnderlying(token, msg.sender, bsub(balance, oldBalance));
} else if (balance < oldBalance) {
// In this case liquidity is being withdrawn, so charge EXIT_FEE
uint tokenBalanceWithdrawn = bsub(oldBalance, balance);
uint tokenExitFee = bmul(tokenBalanceWithdrawn, EXIT_FEE);
_pushUnderlying(token, msg.sender, bsub(tokenBalanceWithdrawn, tokenExitFee));
_pushUnderlying(token, _factory, tokenExitFee);
}
}
function saveLostTokens(address token, uint amount)
external
_logs_
_lock_
{
require(msg.sender == _controller);
require(!_records[token].bound);
uint bal = IERC20(token).balanceOf(address(this));
require(amount <= bal);
_pushUnderlying(token, msg.sender, amount);
}
function getSpotPrice(address tokenIn, address tokenOut)
external view
_viewlock_
returns (uint spotPrice)
{
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
Record storage inRecord = _records[tokenIn];
Record storage outRecord = _records[tokenOut];
return calcSpotPrice(inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, _swapFee);
}
function addBothLiquidity(uint poolAmountOut, uint[] calldata maxAmountsIn)
external
_logs_
_lock_
{
require(_launched, "ERR_NOT_LAUNCHED");
uint poolTotal = totalSupply();
uint ratio = bdiv(poolAmountOut, poolTotal);
require(ratio != 0, "ERR_MATH_APPROX");
for (uint i = 0; i < _tokens.length; i++) {
address t = _tokens[i];
uint bal = _records[t].balance;
uint tokenAmountIn = bmul(ratio, bal);
require(tokenAmountIn != 0, "ERR_MATH_APPROX");
require(tokenAmountIn <= maxAmountsIn[i], "ERR_LIMIT_IN");
emit LOG_JOIN(msg.sender, t, tokenAmountIn, 0);
_pullUnderlying(t, msg.sender, tokenAmountIn);
_records[FEG].balance = IERC20(FEG).balanceOf(address(this));
_records[fETH].balance = IERC20(fETH).balanceOf(address(this));
}
_mintPoolShare(poolAmountOut);
_pushPoolShare(msg.sender, poolAmountOut);
}
function removeBothLiquidity(uint poolAmountIn, uint[] calldata minAmountsOut)
external
_logs_
_lock_
{
require(_launched, "ERR_NOT_LAUNCHED");
userLock storage ulock = _userlock[msg.sender];
if(ulock.setLock == true) {
require(ulock.unlockTime <= block.timestamp, "Liquidity is locked, you cannot removed liquidity until after lock time.");
}
uint poolTotal = totalSupply();
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
uint pAiAfterExitFee = bsub(poolAmountIn, exitFee);
uint ratio = bdiv(pAiAfterExitFee, poolTotal);
require(ratio != 0, "ERR_MATH_APPROX");
_pullPoolShare(msg.sender, poolAmountIn);
_pushPoolShare(_factory, exitFee);
_burnPoolShare(pAiAfterExitFee);
for (uint i = 0; i < _tokens.length; i++) {
address t = _tokens[i];
uint bal = _records[t].balance;
uint tokenAmountOut = bmul(ratio, bal);
require(tokenAmountOut != 0, "ERR_MATH_APPROX");
require(tokenAmountOut >= minAmountsOut[i], "ERR_LIMIT_OUT");
emit LOG_EXIT(msg.sender, t, tokenAmountOut, 0);
_pushUnderlying(t, msg.sender, tokenAmountOut);
_records[FEG].balance = IERC20(FEG).balanceOf(address(this));
_records[fETH].balance = IERC20(fETH).balanceOf(address(this));
}
}
function BUY(
address tokenIn,
uint tokenAmountIn,
address tokenOut,
uint minAmountOut,
uint maxPrice
) noContract
external
_logs_
_lock_
returns (uint tokenAmountOut, uint spotPriceAfter)
{
require(tokenIn == fETH, "Can only buy with fETH");
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
require(_publicSwap, "ERR_SWAP_NOT_PUBLIC");
Record storage inRecord = _records[address(tokenIn)];
Record storage outRecord = _records[address(tokenOut)];
require(tokenAmountIn <= bmul(inRecord.balance, MAX_IN_RATIO), "ERR_MAX_IN_RATIO");
uint spotPriceBefore = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceBefore <= maxPrice, "ERR_BAD_LIMIT_PRICE");
uint tokenInFee;
(tokenAmountOut, tokenInFee) = calcOutGivenIn(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
tokenAmountIn * 99/100,
_swapFee * 0
);
require(tokenAmountOut >= minAmountOut, "ERR_LIMIT_OUT");
uint reserves = calcReservesFromFee(tokenInFee, _reservesRatio);
spotPriceAfter = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceAfter >= spotPriceBefore, "ERR_MATH_APPROX");
require(spotPriceAfter <= maxPrice, "ERR_LIMIT_PRICE");
require(spotPriceBefore <= bdiv(tokenAmountIn, tokenAmountOut), "ERR_MATH_APPROX");
emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn * 99/100, tokenAmountOut, reserves);
totalReserves[address(tokenIn)] = badd(totalReserves[address(tokenIn)], reserves);
emit LOG_ADD_RESERVES(address(tokenIn), reserves);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
_records[FEG].balance = IERC20(FEG).balanceOf(address(this));
_records[fETH].balance = IERC20(fETH).balanceOf(address(this));
return (tokenAmountOut, spotPriceAfter);
}
function SELL(
address tokenIn,
uint tokenAmountIn,
address tokenOut,
uint minAmountOut,
uint maxPrice
) noContract
external
_logs_
_lock_
returns (uint tokenAmountOut, uint spotPriceAfter)
{
require(tokenIn == FEG, "Can only sell FEG");
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
require(_publicSwap, "ERR_SWAP_NOT_PUBLIC");
Record storage inRecord = _records[address(tokenIn)];
Record storage outRecord = _records[address(tokenOut)];
require(tokenAmountIn <= bmul(inRecord.balance, MAX_SELL_RATIO), "ERR_SELL_RATIO");
uint spotPriceBefore = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceBefore <= maxPrice, "ERR_BAD_LIMIT_PRICE");
uint tokenInFee;
(tokenAmountOut, tokenInFee) = calcOutGivenIn(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
tokenAmountIn * 98/100,
_swapFee
);
require(tokenAmountOut >= minAmountOut, "ERR_LIMIT_OUT");
uint reserves = calcReservesFromFee(tokenInFee, _reservesRatio);
spotPriceAfter = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceAfter >= spotPriceBefore, "ERR_MATH_APPROX");
require(spotPriceAfter <= maxPrice, "ERR_LIMIT_PRICE");
require(spotPriceBefore <= bdiv(tokenAmountIn, tokenAmountOut), "ERR_MATH_APPROX");
emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn * 98/100, tokenAmountOut, reserves);
totalReserves[address(tokenIn)] = badd(totalReserves[address(tokenIn)], reserves);
emit LOG_ADD_RESERVES(address(tokenIn), reserves);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
uint256 tokAmountI = bmul(tokenAmountOut, bdiv(25, 10000));
//uint256 tokAmountI2 = bmul(tokenAmountOut, bdiv(10, 10000));
//uint256 tokAmountI1 = bsub(tokenAmountOut, badd(tokAmountI, tokAmountI2));
uint256 tokAmountI1 = bsub(tokenAmountOut, tokAmountI);
_pushUnderlying(tokenOut, msg.sender, tokAmountI1);
_pushUnderlying1(tokenOut, tokAmountI);
//_pushUnderlying2(tokenOut, tokAmountI2);
_records[FEG].balance = IERC20(FEG).balanceOf(address(this));
_records[fETH].balance = IERC20(fETH).balanceOf(address(this));
return (tokenAmountOut, spotPriceAfter);
}
function setLockLiquidity() external {
address user = msg.sender;
userLock storage ulock = _userlock[user];
ulock.setLock = true;
ulock.unlockTime = block.timestamp + 90 days ;
}
function emergencyLockOverride(address user, bool _bool) external {
require(msg.sender == _controller);
//address user = msg.sender;
userLock storage ulock = _userlock[user];
ulock.setLock = _bool;
}
function addLiquidityfETH(address tokenIn, uint tokenAmountIn, uint minPoolAmountOut)
external
_logs_
_lock_
returns (uint poolAmountOut)
{
require(tokenIn == fETH, "Can only add fETH");
require(_launched, "ERR_NOT_FINALIZED");
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(tokenAmountIn <= bmul(_records[tokenIn].balance, MAX_1_RATIO), "ERR_MAX_IN_RATIO");
Record storage inRecord = _records[tokenIn];
uint reserves;
(poolAmountOut, reserves) = calcPoolOutGivenSingleIn(
inRecord.balance,
inRecord.denorm,
_totalSupply,
_totalWeight,
tokenAmountIn,
_swapFee,
_reservesRatio
);
require(poolAmountOut >= minPoolAmountOut, "ERR_LIMIT_OUT");
//inRecord.balance = bsub(badd(inRecord.balance, reserves);
emit LOG_JOIN(msg.sender, tokenIn, tokenAmountIn, reserves);
totalReserves[address(tokenIn)] = badd(totalReserves[address(tokenIn)], reserves);
emit LOG_ADD_RESERVES(address(tokenIn), reserves);
_mintPoolShare(poolAmountOut);
_pushPoolShare(msg.sender, poolAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
_records[FEG].balance = IERC20(FEG).balanceOf(address(this));
_records[fETH].balance = IERC20(fETH).balanceOf(address(this));
return poolAmountOut;
}
function addLiquidityFEG(address tokenIn, uint tokenAmountIn, uint minPoolAmountOut)
external
_logs_
_lock_
returns (uint poolAmountOut)
{
require(tokenIn == FEG, "Can only add FEG");
require(_launched, "ERR_NOT_FINALIZED");
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(tokenAmountIn <= bmul(_records[tokenIn].balance, MAX_1_RATIO), "ERR_MAX_IN_RATIO");
Record storage inRecord = _records[tokenIn];
uint reserves;
(poolAmountOut, reserves) = calcPoolOutGivenSingleIn(
inRecord.balance,
inRecord.denorm,
_totalSupply,
_totalWeight,
tokenAmountIn,
_swapFee,
_reservesRatio
);
require(poolAmountOut >= minPoolAmountOut, "ERR_LIMIT_OUT");
// inRecord.balance = bsub(badd(inRecord.balance, tokenAmountIn * 98/100), reserves);
emit LOG_JOIN(msg.sender, tokenIn, tokenAmountIn, reserves);
totalReserves[address(tokenIn)] = badd(totalReserves[address(tokenIn)], reserves);
emit LOG_ADD_RESERVES(address(tokenIn), reserves);
_mintPoolShare(poolAmountOut);
_pushPoolShare(msg.sender, poolAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
return poolAmountOut;
}
function RemoveLiquidityPoolAmountIn(address tokenOut, uint poolAmountIn, uint minAmountOut)
external
_logs_
_lock_
returns (uint tokenAmountOut)
{
require(_launched, "ERR_NOT_LAUNCHED");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
userLock storage ulock = _userlock[msg.sender];
if(ulock.setLock == true) {
require(ulock.unlockTime <= block.timestamp, "Liquidity is locked, you cannot removed liquidity until after lock time.");
}
Record storage outRecord = _records[tokenOut];
tokenAmountOut = calcSingleOutGivenPoolIn(
outRecord.balance,
outRecord.denorm,
_totalSupply,
_totalWeight,
poolAmountIn,
_swapFee
);
require(tokenAmountOut >= minAmountOut, "ERR_LIMIT_OUT");
require(tokenAmountOut <= bmul(_records[tokenOut].balance, MAX_1_RATIO), "ERR_MAX_OUT_RATIO");
uint tokenAmountOutZeroFee = calcSingleOutGivenPoolIn(
outRecord.balance,
outRecord.denorm,
_totalSupply,
_totalWeight,
poolAmountIn,
0
);
uint reserves = calcReserves(
tokenAmountOutZeroFee,
tokenAmountOut,
_reservesRatio
);
//outRecord.balance = bsub(bsub(outRecord.balance, tokenAmountOut), reserves);
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOut, reserves);
totalReserves[address(tokenOut)] = badd(totalReserves[address(tokenOut)], reserves);
emit LOG_ADD_RESERVES(address(tokenOut), reserves);
_pullPoolShare(msg.sender, poolAmountIn);
_burnPoolShare(bsub(poolAmountIn, exitFee));
_pushPoolShare(_factory, exitFee);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
_records[FEG].balance = IERC20(FEG).balanceOf(address(this));
_records[fETH].balance = IERC20(fETH).balanceOf(address(this));
return tokenAmountOut;
}
function RemoveLiquidityExtactAmountOut(address tokenOut, uint tokenAmountOut, uint maxPoolAmountIn)
external
_logs_
_lock_
returns (uint poolAmountIn)
{
require(_launched, "ERR_NOT_LAUNCHED");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
require(tokenAmountOut <= bmul(_records[tokenOut].balance, MAX_1_RATIO), "ERR_MAX_OUT_RATIO");
userLock storage ulock = _userlock[msg.sender];
if(ulock.setLock == true) {
require(ulock.unlockTime <= block.timestamp, "Liquidity is locked, you cannot removed liquidity until after lock time.");
}
Record storage outRecord = _records[tokenOut];
uint reserves;
(poolAmountIn, reserves) = calcPoolInGivenSingleOut(
outRecord.balance,
outRecord.denorm,
_totalSupply,
_totalWeight,
tokenAmountOut,
_swapFee,
_reservesRatio
);
require(poolAmountIn != 0, "ERR_MATH_APPROX");
require(poolAmountIn <= maxPoolAmountIn, "ERR_LIMIT_IN");
outRecord.balance = bsub(bsub(outRecord.balance, tokenAmountOut), reserves);
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOut, reserves);
totalReserves[address(tokenOut)] = badd(totalReserves[address(tokenOut)], reserves);
emit LOG_ADD_RESERVES(address(tokenOut), reserves);
_pullPoolShare(msg.sender, poolAmountIn);
_burnPoolShare(bsub(poolAmountIn, exitFee));
_pushPoolShare(_factory, exitFee);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
_records[FEG].balance = IERC20(FEG).balanceOf(address(this));
_records[fETH].balance = IERC20(fETH).balanceOf(address(this));
return poolAmountIn;
}
function claimTotalReserves(address reservesAddress)
external
_logs_
_lock_
{
require(msg.sender == _factory);
for (uint i = 0; i < _tokens.length; i++) {
address t = _tokens[i];
uint tokenAmountOut = totalReserves[t];
totalReserves[t] = 0;
emit LOG_CLAIM_RESERVES(reservesAddress, t, tokenAmountOut);
_pushUnderlying(t, reservesAddress, tokenAmountOut);
}
}
// ==
// 'Underlying' token-manipulation functions make external calls but are NOT locked
// You must `_lock_` or otherwise ensure reentry-safety
function _pullUnderlying(address erc20, address from, uint amount)
internal
{
bool xfer = IERC20(erc20).transferFrom(from, address(this), amount);
require(xfer, "ERR_ERC20_FALSE");
}
function _pushUnderlying(address erc20, address to, uint amount)
internal
{
bool xfer = IERC20(erc20).transfer(to, amount);
require(xfer, "ERR_ERC20_FALSE");
}
function _pushUnderlying1(address erc20, uint amount)
internal
{
bool xfer = IERC20(erc20).transfer(FEGstake, amount);
require(xfer, "ERR_ERC20_FALSE");
}
function _pushUnderlying2(address erc20, uint amount)
internal
{
bool xfer = IERC20(erc20).transfer(pairRewardPool, amount);
require(xfer, "ERR_ERC20_FALSE");
}
function _pullPoolShare(address from, uint amount)
internal
{
_pull(from, amount);
}
function _pushPoolShare(address to, uint amount)
internal
{
_push(to, amount);
}
function _mintPoolShare(uint amount)
internal
{
_mint(amount);
}
function _burnPoolShare(uint amount)
internal
{
_burn(amount);
}
}File 2 of 2: TRYfinance
/* TRY token has been being developed since 10/2020 and has more features than most other DEFI token's on the market, here is a summary of built in features that TRY token offers:
* We added a brand new feature never seen before in any DEFI token, a tx reward pool, 1% of all transactions are given to the reward pool and are awarded to the sender of every 25th transaction.
* We added a deflationary burn fee of 1% on every tx which is automatically sent directly to the burn address upon every transfer, this feature will ensure a truly deflationary model.
* We wanted to discourage token dumping so we added a 5% antiDumpFee to all TRY sold on UNIswap. This fee is distributed to all TRYstake users when buyback feature is performed.
* Previous rebalance liquidity models used a liquidity divisor as a liquidity reward, however that process made the rebalance feature not as effective since it had to rebalance its own rewards.
* To help replace the removal of awarding liquidity providers via the Buyback function we will allow LP tokens to farm TRY tokens directly on TRYfarm.
* We coded this contract to have the ability to ADDfunds into TRYstake so it can directly be its own UNIswap sell fee rewards distributor. The staking rewards distribution is called every time
a user performs the rebalance liquidity function. The rebalance function still burns TRY that it purchases with the rebalance increasing the effectiveness of the deflationary model.
* When Buyback function is called the caller gets a 4% reward of the buyback TRY amount and 96% of the buyback TRY amount gets sent directly to the burn address.
* We coded the buyback function to work on 2 hour intervals and set the rate to 1%, we also added the ability for this contract to add 20 seconds to the buyback interval on each use of the
buyback function. This will help ensure that the buyback feature cannot be manipulated and insure maximum life expectancy of the feature.
* We ensured that all of TRY protocols are whitelist able so when you use them you will not incur any transactional fee's when sending TRY to those protocols.
* Once this contract creates the UNIswap pair the LP tokens that are sent back are unable to be removed, there is no withdrawal code for these LP tokens this locked them for their intended purpose forever.
* We added the ability to add and remove blacklist addresses, this will help insure that we can properly fight hackers and malicious intents on TRY token's economy.
* We added createUNISwapPair function that will ensure ETH collected for liquidity can only be used for that one specific purpose, TRY presale contract automatically sends ETH liquidity to this contract.
* We are sure that TRY will be the most successful project to ever use a rebalancer style feature, TRYstake will ensure TRY tokens are happy earning in the staking contracts and not on the market to lower
the price. UNIswap sell fees will discourage selling, while offering incentivized rewards for staking. TRYfarm will directly reward liquidity providers in replacement of the liquidity reward distribution
on the previous model. The Tx Reward pool feature helps complete the package, TRY token has the most rewarding features of any DEFI token!
For more information please visit try.finance/whitepaper.html
*/
pragma solidity ^0.5.17;
contract Context {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
contract WhitelistAdminRole is Context {
using Roles for Roles.Role;
event WhitelistAdminAdded(address indexed account);
event WhitelistAdminRemoved(address indexed account);
Roles.Role private _whitelistAdmins;
constructor () internal {
_addWhitelistAdmin(_msgSender());
}
modifier onlyWhitelistAdmin() {
require(isWhitelistAdmin(_msgSender()), "WhitelistAdminRole: caller does not have the WhitelistAdmin role");
_;
}
function isWhitelistAdmin(address account) public view returns (bool) {
return _whitelistAdmins.has(account);
}
function addWhitelistAdmin(address account) public onlyWhitelistAdmin {
_addWhitelistAdmin(account);
}
function renounceWhitelistAdmin() public {
_removeWhitelistAdmin(_msgSender());
}
function _addWhitelistAdmin(address account) internal {
_whitelistAdmins.add(account);
emit WhitelistAdminAdded(account);
}
function _removeWhitelistAdmin(address account) internal {
_whitelistAdmins.remove(account);
emit WhitelistAdminRemoved(account);
}
}
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);
}
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;
}
function ceil(uint a, uint m) internal pure returns (uint r) {
return (a + m - 1) / m * m;
}
}
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
constructor (uint256 totalSupply) public {
_mint(_msgSender(),totalSupply);
}
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
}
contract ERC20Burnable is Context, ERC20 {
function burn(uint256 amount) public {
_burn(_msgSender(), amount);
}
function burnFrom(address account, uint256 amount) public {
_burnFrom(account, amount);
}
}
library Roles {
struct Role {
mapping (address => bool) bearer;
}
function add(Role storage role, address account) internal {
require(!has(role, account), "Roles: account already has role");
role.bearer[account] = true;
}
function remove(Role storage role, address account) internal {
require(has(role, account), "Roles: account does not have role");
role.bearer[account] = false;
}
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0), "Roles: account is the zero address");
return role.bearer[account];
}
}
contract ERC20Detailed is IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
constructor (string memory name, string memory symbol, uint8 decimals) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
}
contract ERC20TransferLiquidityLock is ERC20 {
using SafeMath for uint256;
event Rebalance(uint256 tokenBurnt);
event SupplyTRYStake(uint256 tokenAmount);
event RewardStakers(uint256 stakingRewards);
address public uniswapV2Router = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address public uniswapV2Factory = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
address public uniswapV2Pair;
address public TRYStake;
address public presaleAddress;
address public LPFarm;
address public Master = address (uniswapV2Router);
address public Trident = address (this);
address payable public treasury;
mapping(address => bool) public feelessAddr;
mapping(address => bool) public unlocked;
mapping(address => bool) public oracle;
mapping(address => bool) public blacklist;
uint256 public rewardPoolDivisor;
uint256 public rebalanceRewardDivisor;
uint256 public rebalanceDivisor;
uint256 public burnTxFee;
uint256 public antiDumpFee;
uint256 public minRebalanceAmount;
uint256 public lastRebalance;
uint256 public rebalanceInterval;
address public burnAddr = 0x000000000000000000000000000000000000dEaD;
bool public LPLocked;
uint256 public txNumber;
uint256 one = 1000000000000000000;
uint256 public trans100 = 25000000000000000000;
uint256 public stakePool = 0;
uint256 public rewardPool = 0;
bool public locked;
Balancer balancer;
constructor() public {
lastRebalance = block.timestamp;
burnTxFee = 100;
rewardPoolDivisor = 100;
antiDumpFee = 20;
rebalanceRewardDivisor = 25;
rebalanceDivisor = 100;
rebalanceInterval = 2 hours;
minRebalanceAmount = 100e18;
treasury = msg.sender;
balancer = new Balancer(treasury);
feelessAddr[address(this)] = true;
feelessAddr[address(balancer)] = true;
feelessAddr[address(uniswapV2Router)] = true;
feelessAddr[address(uniswapV2Factory)] = true;
feelessAddr[address(TRYStake)] = true;
feelessAddr[address(presaleAddress)] = true;
locked = true;
LPLocked = true;
unlocked[msg.sender] = false;
unlocked[address(this)] = true;
unlocked[address(balancer)] = true;
unlocked[address(balancer)] = true;
unlocked[address(uniswapV2Router)] = true;
unlocked[address(presaleAddress)] = true;
txNumber = 0;
}
function calculateFees(address from, address to, uint256 amount) public view returns( uint256 rewardtx, uint256 Burntx, uint256 selltx){
}
function isContract(address _addr) public view returns (bool _isContract){
uint32 size;
assembly {
size := extcodesize(_addr)}
return (size > 0);
}
function _transfer(address from, address to, uint256 amount) internal {
if(locked && unlocked[from] != true && unlocked[to] != true)
revert("Transfers are locked until after presale.");
if(blacklist [from] == true || blacklist [to] == true)
revert("Address is blacklisted");
uint256 Burntx = 0;
uint256 rewardtx = 0;
if(feelessAddr[from] == false && feelessAddr[to] == false){
if (burnTxFee != 0) {
Burntx = amount.div(burnTxFee);
amount = amount.sub(Burntx);
super._transfer(from, address(burnAddr), Burntx);
}
if (rewardPoolDivisor != 0) {
txNumber = txNumber.add(one);
rewardtx = amount.div(rewardPoolDivisor);
amount = amount.sub(rewardtx);
super._transfer(from, address(this), rewardtx);
rewardPool += rewardtx;
if(txNumber == trans100){
require( !(isContract(from)), 'inValid caller');
super._transfer(address(this), from, rewardPool);
rewardPool = 0;
txNumber = 0;
}
}
if (antiDumpFee != 0 && oracle[to]) {
uint256 selltx = amount.div(antiDumpFee);
stakePool += selltx;
amount = amount.sub(selltx);
super._transfer(from, address(this), selltx);
}
super._transfer(from, to, amount);
}
else {
super._transfer(from, to, amount);
}
}
function () external payable {}
function RebalanceLiquidity() public {
require(balanceOf(msg.sender) >= minRebalanceAmount, "You do not have the required amount of TRY.");
require(block.timestamp > lastRebalance + rebalanceInterval, "It is too early to use this function.");
lastRebalance = block.timestamp;
uint256 _lockableSupply = stakePool;
_addRebalanceInterval();
_rewardStakers(_lockableSupply);
uint256 amountToRemove = ERC20(uniswapV2Pair).balanceOf(address(this)).div(rebalanceDivisor);
remLiquidity(amountToRemove);
uint _locked = balancer.rebalance(rebalanceRewardDivisor);
emit Rebalance(_locked);
}
function _addRebalanceInterval() private {
rebalanceInterval = rebalanceInterval.add(20 seconds);
}
function _rewardStakers(uint256 stakingRewards) private {
if(TRYStake != address(0)) {
TRYstakingContract(TRYStake).ADDFUNDS(stakingRewards);
stakePool= 0;
emit RewardStakers(stakingRewards);
}
}
function remLiquidity(uint256 lpAmount) private returns(uint ETHAmount) {
ERC20(uniswapV2Pair).approve(uniswapV2Router, lpAmount);
(ETHAmount) = IUniswapV2Router02(uniswapV2Router)
.removeLiquidityETHSupportingFeeOnTransferTokens(
address(this),
lpAmount,
0,
0,
address(balancer),
block.timestamp);
}
function lockableSupply() external view returns (uint256) {
return balanceOf(address(this));
}
function lockedSupply() external view returns (uint256) {
uint256 lpTotalSupply = ERC20(uniswapV2Pair).totalSupply();
uint256 lpBalance = lockedLiquidity();
uint256 percentOfLpTotalSupply = lpBalance.mul(1e12).div(lpTotalSupply);
uint256 uniswapBalance = balanceOf(uniswapV2Pair);
uint256 _lockedSupply = uniswapBalance.mul(percentOfLpTotalSupply).div(1e12);
return _lockedSupply;
}
function burnedSupply() external view returns (uint256) {
uint256 lpTotalSupply = ERC20(uniswapV2Pair).totalSupply();
uint256 lpBalance = burnedLiquidity();
uint256 percentOfLpTotalSupply = lpBalance.mul(1e12).div(lpTotalSupply);
uint256 uniswapBalance = balanceOf(uniswapV2Pair);
uint256 _burnedSupply = uniswapBalance.mul(percentOfLpTotalSupply).div(1e12);
return _burnedSupply;
}
function burnableLiquidity() public view returns (uint256) {
return ERC20(uniswapV2Pair).balanceOf(address(this));
}
function burnedLiquidity() public view returns (uint256) {
return ERC20(uniswapV2Pair).balanceOf(address(0));
}
function lockedLiquidity() public view returns (uint256) {
return burnableLiquidity().add(burnedLiquidity());
}
}
interface TRYstakingContract {
function ADDFUNDS(uint256 stakingRewards) external;
}
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
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);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}
interface IUniswapV2Router02 {
function WETH() external pure returns (address);
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
}
interface IUniswapV2Pair {
function sync() external;
}
contract ERC20Governance is ERC20, ERC20Detailed {
using SafeMath for uint256;
function _transfer(address from, address to, uint256 amount) internal {
_moveDelegates(_delegates[from], _delegates[to], amount);
super._transfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal {
_moveDelegates(address(0), _delegates[account], amount);
super._mint(account, amount);
}
function _burn(address account, uint256 amount) internal {
_moveDelegates(_delegates[account], address(0), amount);
super._burn(account, amount);
}
mapping (address => address) internal _delegates;
struct Checkpoint {
uint32 fromBlock;
uint256 votes;
}
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
mapping (address => uint32) public numCheckpoints;
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
mapping (address => uint) public nonces;
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
function delegates(address delegator)
external
view
returns (address)
{
return _delegates[delegator];
}
function delegate(address delegatee) external {
return _delegate(msg.sender, delegatee);
}
function delegateBySig(
address delegatee,
uint nonce,
uint expiry,
uint8 v,
bytes32 r,
bytes32 s
)
external
{
bytes32 domainSeparator = keccak256(
abi.encode(
DOMAIN_TYPEHASH,
keccak256(bytes(name())),
getChainId(),
address(this)
)
);
bytes32 structHash = keccak256(
abi.encode(
DELEGATION_TYPEHASH,
delegatee,
nonce,
expiry
)
);
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
domainSeparator,
structHash
)
);
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), "ERC20Governance::delegateBySig: invalid signature");
require(nonce == nonces[signatory]++, "ERC20Governance::delegateBySig: invalid nonce");
require(now <= expiry, "ERC20Governance::delegateBySig: signature expired");
return _delegate(signatory, delegatee);
}
function getCurrentVotes(address account)
external
view
returns (uint256)
{
uint32 nCheckpoints = numCheckpoints[account];
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
}
function getPriorVotes(address account, uint blockNumber)
external
view
returns (uint256)
{
require(blockNumber < block.number, "ERC20Governance::getPriorVotes: not yet determined");
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints - 1].votes;
}
if (checkpoints[account][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2;
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlock == blockNumber) {
return cp.votes;
} else if (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoints[account][lower].votes;
}
function _delegate(address delegator, address delegatee)
internal
{
address currentDelegate = _delegates[delegator];
uint256 delegatorBalance = balanceOf(delegator);
_delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint256 srcRepNew = srcRepOld.sub(amount);
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep != address(0)) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint256 dstRepNew = dstRepOld.add(amount);
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
function _writeCheckpoint(
address delegatee,
uint32 nCheckpoints,
uint256 oldVotes,
uint256 newVotes
)
internal
{
uint32 blockNumber = safe32(block.number, "ERC20Governance::_writeCheckpoint: block number exceeds 32 bits");
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
numCheckpoints[delegatee] = nCheckpoints + 1;
}
emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
}
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2**32, errorMessage);
return uint32(n);
}
function getChainId() internal pure returns (uint) {
uint256 chainId;
assembly { chainId := chainid() }
return chainId;
}
}
contract Balancer {
using SafeMath for uint256;
TRYfinance token;
address public burnAddr = 0x000000000000000000000000000000000000dEaD;
address payable public treasury;
constructor(address payable treasury_) public {
token = TRYfinance(msg.sender);
treasury = treasury_;
}
function () external payable {}
function rebalance(uint rebalanceRewardDivisor) external returns (uint256) {
require(msg.sender == address(token), "only token contract can perform this function");
swapEthForTokens(address(this).balance, rebalanceRewardDivisor);
uint256 lockableBalance = token.balanceOf(address(this));
uint256 callerReward = lockableBalance.div(rebalanceRewardDivisor);
token.transfer(tx.origin, callerReward);
token.transfer(burnAddr, lockableBalance.sub(callerReward));
return lockableBalance.sub(callerReward);
}
function swapEthForTokens(uint256 EthAmount, uint rebalanceRewardDivisor) private {
address[] memory uniswapPairPath = new address[](2);
uniswapPairPath[0] = IUniswapV2Router02(token.uniswapV2Router()).WETH();
uniswapPairPath[1] = address(token);
uint256 treasuryAmount = EthAmount.div(rebalanceRewardDivisor);
treasury.transfer(treasuryAmount);
token.approve(token.uniswapV2Router(), EthAmount);
IUniswapV2Router02(token.uniswapV2Router())
.swapExactETHForTokensSupportingFeeOnTransferTokens.value(EthAmount.sub(treasuryAmount))(
0,
uniswapPairPath,
address(this),
block.timestamp);
}
}
contract TRYfinance is
ERC20(100000e18),
ERC20Detailed("TRYfinance", "TRY", 18),
ERC20Burnable,
ERC20Governance,
ERC20TransferLiquidityLock,
WhitelistAdminRole
{
function createUNISwapPair(uint amountTokenDesired) public onlyWhitelistAdmin {
uint amountETH = address(this).balance;
approve(address(uniswapV2Router), amountTokenDesired);
IUniswapV2Router01(uniswapV2Router).addLiquidityETH.value(amountETH)(
address(this),
amountTokenDesired,
0,
0,
address(this),
now);
}
function quickApproveTRYStake() public {
_approve(_msgSender(), TRYStake, 10000e18);
}
function quickApproveMaster() public {
_approve(_msgSender(), Master, 10000e18);
}
function quickApproveFarm() public {
_approve(_msgSender(), LPFarm, 10000e18);
}
function setUniswapV2Router(address _uniswapV2Router) public onlyWhitelistAdmin {
uniswapV2Router = _uniswapV2Router;
}
function setUniswapV2Pair(address _uniswapV2Pair) public onlyWhitelistAdmin {
uniswapV2Pair = _uniswapV2Pair;
}
function setUniswapV2Factory(address _uniswapV2Factory) public onlyWhitelistAdmin {
uniswapV2Factory = _uniswapV2Factory;
}
function setTrans100(uint256 _trans100) public onlyWhitelistAdmin {
require(_trans100 <= 100e18, "Cannot set over 100 transactions");
trans100 = _trans100;
}
function setRewardPoolDivisor(uint256 _rdiv) public onlyWhitelistAdmin {
require(_rdiv >= 100, "Cannot set over 1% RewardPoolDivisor");
rewardPoolDivisor = _rdiv;
}
function setRebalanceDivisor(uint256 _rebalanceDivisor) public onlyWhitelistAdmin {
if (_rebalanceDivisor != 0) {
require(_rebalanceDivisor >= 10, "Cannot set rebalanceDivisor over 10%");
require(_rebalanceDivisor <= 100, "Cannot set rebalanceDivisor under 1%");
}
rebalanceDivisor = _rebalanceDivisor;
}
function addTRYStake(address _stake) public onlyWhitelistAdmin {
TRYStake = _stake;
}
function addPresaleAddress(address _presaleaddress) public onlyWhitelistAdmin {
presaleAddress = _presaleaddress;
}
function addLPFarm(address _farm) public onlyWhitelistAdmin {
LPFarm = _farm;
}
function addMaster(address _master) public onlyWhitelistAdmin {
Master = _master;
}
function addTrident(address _Trident) public onlyWhitelistAdmin {
Trident = _Trident;
}
function setMaster () public onlyWhitelistAdmin {
ERC20(Trident).approve(Master, 100000e18);
}
function setTrident () public onlyWhitelistAdmin {
ERC20(Trident).approve(TRYStake, 100000e18);
}
function rewardStaking(uint256 stakingRewards) internal {
TRYstakingContract(TRYStake).ADDFUNDS(stakingRewards);
emit SupplyTRYStake(stakingRewards);
}
function setRebalanceInterval(uint256 _interval) public onlyWhitelistAdmin {
require(_interval<= 7200, "Cannot set over 2 hour interval");
require(_interval>= 3600, "Cannot set under 1 hour interval");
rebalanceInterval = _interval;
}
function setRebalanceRewardDivisior(uint256 _rDivisor) public onlyWhitelistAdmin {
if (_rDivisor != 0) {
require(_rDivisor <= 25, "Cannot set rebalanceRewardDivisor under 4%");
require(_rDivisor >= 10, "Cannot set rebalanceRewardDivisor over 10%");
}
rebalanceRewardDivisor = _rDivisor;
}
function toggleFeeless(address _addr) public onlyWhitelistAdmin {
feelessAddr[_addr] = true;
}
function toggleFees(address _addr) public onlyWhitelistAdmin {
feelessAddr[_addr] = false;
}
function toggleUnlocked(address _addr) public onlyWhitelistAdmin {
unlocked[_addr] = !unlocked[_addr];
}
function setOracle(address _addr, bool _bool) public onlyWhitelistAdmin {
oracle[_addr] = _bool;
}
function setBlackListAddress(address _addr, bool _bool) public onlyWhitelistAdmin {
blacklist[_addr] = _bool;
}
function activateTrading() public onlyWhitelistAdmin {
locked = false;
}
function setMinRebalanceAmount(uint256 amount_) public onlyWhitelistAdmin {
require(amount_ <= 1000e18, "Cannot set over 1000 TRY tokens");
require(amount_ >= 20e18, "Cannot set under 20 TRY tokens");
minRebalanceAmount = amount_;
}
function setBurnTxFee(uint256 amount_) public onlyWhitelistAdmin {
require(amount_ >= 100, "Cannot set over 1% burnTxFee");
burnTxFee = amount_;
}
function setAntiDumpFee(uint256 amount_) public onlyWhitelistAdmin {
require(amount_ >= 10, "Cannot set over 10% antiDumpFee");
require(amount_ <= 100, "Cannot set under 1% antiDumpFee");
antiDumpFee = amount_;
}
}