AXIA Protocol - Smart Contract Audit Report

Summary

Axia Protocol AXIA Protocol is a Decentralized platform for Cryptocurrency Index Fund management which presents cryptocurrency enthusiasts/investors with opportunities of one-time investments in baskets of cryptocurrencies (Axia Funds) saving them time and energy that would have been spent sifting through thousands of tokens in search of which ones to buy for a portfolio. With Axia Funds, investors can be rest assured that their portfolio will only grow in proļ¬ts over time.

AXIA Protocol consists of 7 Smart Contracts: The Protocol's token contract includes all the standard ERC20 functions as defined in the ERC20 protocol by the Ethereum Foundation.

Additional features included in the contract:
  • The token contract contains no mint function, so the supply of the token shall never increase. There is a burn function which could decrease the token's total supply.
  • Ownership/Adminship - Some functions are protected and can only be called by the contract Owner/Administrator.
  • Owners have the ability to update the rate variables for pools.
  • Utilization of SafeMath to prevent overflows.
Audit Findings Summary
  • Overall, no serious security issues were identified.
  • The contract uses an assert check instead of a require check in the mulDiv() and scaledToken()functions. This is out of line with Solidity best practices, but in this case the usage poses no issue to the integrity of the contract.
  • The _minStakeAmount(), poolconfigs(), unstakeburnrate() and poolpercentages() functions are technically vulnerable to an arithmetic overflow, but it entirely in the control of the contract owner and thus no security issue is present.

We ran over 400,000 transactions interacting with this suite of contracts on a test blockchain to determine these results.
Date: October 22nd, 2020
Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
SuicideN/APASS
State Change External CallsN/APASS
Unchecked RetvalN/APASS
User Supplied AssertionA user can trigger an assertion violation due to SafeMath's interger overflow protections,
but their transaction will revert safely.
Warning
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

 + [Int] ERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] ASP 
    - [Ext] scaledToken #
    - [Ext] totalFrozen

 + [Int] OSP 
    - [Ext] scaledToken #
    - [Ext] totalFrozen

 + [Int] DSP 
    - [Ext] scaledToken #
    - [Ext] totalFrozen

 + [Int] USP 
    - [Ext] scaledToken #
    - [Ext] totalFrozen

 +  AXIATOKEN (ERC20)
    - [Pub]  #
    - [Pub] poolconfigs #
       - modifiers: onlyAdministrator
    - [Pub] burningPoolconfigs #
       - modifiers: onlyAdministrator
    - [Pub] secondAndDay #
       - modifiers: onlyAdministrator
    - [Pub] nextEpoch #
       - modifiers: onlyAdministrator
    - [Pub] whitelistOnEmission #
       - modifiers: onlyAdministrator
    - [Pub] unwhitelistOnEmission #
       - modifiers: onlyAdministrator
    - [Pub] supplyeffect #
       - modifiers: onlyBurningPool
    - [Pub] poolpercentages #
       - modifiers: onlyAdministrator
    - [Pub] Burn #
    - [Pub] transfer #
    - [Pub] approve #
    - [Pub] transferFrom #
    - [Prv] _transfer #
    - [Int] emittingAmount #
    - [Pub] ospfrozen
    - [Pub] dspfrozen
    - [Pub] uspfrozen
    - [Pub] aspfrozen
    - [Pub] mulDiv
    - [Prv] fullMul
  
							

Source Code

Click here to download the source code as a .sol file.




pragma solidity 0.6.4;

library SafeMath {

    /**

     * @dev Returns the addition of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `+` operator.

     *

     * Requirements:

     *

     * - Addition cannot overflow.

     */

    function add(uint256 a, uint256 b) internal pure returns (uint256) {

        uint256 c = a + b;

        require(c >= a, "SafeMath: addition overflow");



        return c;

    }

 

    /**

     * @dev Returns the subtraction of two unsigned integers, reverting on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {

        return sub(a, b, "SafeMath: subtraction overflow");

    }



    /**

     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b <= a, errorMessage);

        uint256 c = a - b;



        return c;

    }



    /**

     * @dev Returns the multiplication of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `*` operator.

     *

     * Requirements:

     *

     * - Multiplication cannot overflow.

     */

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the

        // benefit is lost if 'b' is also tested.

        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522

        if (a == 0) {

            return 0;

        }



        uint256 c = a * b;

        require(c / a == b, "SafeMath: multiplication overflow");



        return c;

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b) internal pure returns (uint256) {

        return div(a, b, "SafeMath: division by zero");

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b > 0, errorMessage);

        uint256 c = a / b;

        // assert(a == b * c + a % b); // There is no case in which this doesn't hold



        return c;

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {

        return mod(a, b, "SafeMath: modulo by zero");

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts with custom message when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b != 0, errorMessage);

        return a % b;

    }

}



//ERC20 Interface

interface ERC20 {

    function totalSupply() external view returns (uint);

    function balanceOf(address account) external view returns (uint);

    function transfer(address, uint) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint);

    function approve(address, uint) external returns (bool);

    function transferFrom(address, address, uint) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint value);

    event Approval(address indexed owner, address indexed spender, uint value);

    }

    

interface ASP {

    

   function scaledToken(uint amount) external returns(bool);

   function totalFrozen() external view returns (uint256);

 }



interface OSP {

    

   function scaledToken(uint amount) external returns(bool);

   function totalFrozen() external view returns (uint256);

 }

 

interface DSP {

    

   function scaledToken(uint amount) external returns(bool);

   function totalFrozen() external view returns (uint256);

 }



interface USP {

    

   function scaledToken(uint amount) external returns(bool);

   function totalFrozen() external view returns (uint256);

 }

    

//======================================AXIA CONTRACT=========================================//

contract AXIATOKEN is ERC20 {

    

    using SafeMath for uint256;

    

//======================================AXIA EVENTS=========================================//



    event NewEpoch(uint epoch, uint emission, uint nextepoch);

    event NewDay(uint epoch, uint day, uint nextday);

    event BurnEvent(address indexed pool, address indexed burnaddress, uint amount);

    event emissions(address indexed root, address indexed pool, uint value);

    event TrigRewardEvent(address indexed root, address indexed receiver, uint value);

    event BasisPointAdded(uint value);

    

    

   // ERC-20 Parameters

    string public name; 

    string public symbol;

    uint public decimals; 

    uint public startdecimal;

    uint public override totalSupply;

    uint public initialsupply;

    

     //======================================STAKING POOLS=========================================//

    

    address public lonePool;

    address public swapPool;

    address public DefiPool;

    address public OraclePool;

    

    address public burningPool;

    

    uint public pool1Amount;

    uint public pool2Amount;

    uint public pool3Amount;

    uint public pool4Amount;

    uint public basisAmount;

    uint public poolAmountTrig;

    

    

    uint public TrigAmount;

    

    

    // ERC-20 Mappings

    mapping(address => uint) public override balanceOf;

    mapping(address => mapping(address => uint)) public override allowance;

    

    

    // Public Parameters

    uint crypto; 

    uint startcrypto;

    uint public emission;

    uint public currentEpoch; 

    uint public currentDay;

    uint public daysPerEpoch; 

    uint public secondsPerDay;

    uint public genesis;

    uint public nextEpochTime; 

    uint public nextDayTime;

    uint public amountToEmit;

    uint public BPE;

    

    //======================================BASIS POINT VARIABLES=========================================//

    uint public bpValue;

    uint public actualValue;

    uint public TrigReward;

    uint public burnAmount;

    address administrator;

    uint totalEmitted;

    

    uint256 public pool1percentage = 500;

    uint256 public pool2percentage = 4500;

    uint256 public pool3percentage = 2500;

    uint256 public pool4percentage = 2500;

    uint256 public basispercentage = 500;

    uint256 public trigRewardpercentage = 20;

    

    

    address public messagesender;

     

    // Public Mappings

    

    mapping(address=>bool) public emission_Whitelisted;

    



    //=====================================CREATION=========================================//

    // Constructor

    constructor() public {

        name = "AXIA TOKEN (axiaprotocol.io)"; 

        symbol = "AXIAv3"; 

        decimals = 18; 

        startdecimal = 16;

        crypto = 1*10**decimals; 

        startcrypto =  1*10**startdecimal; 

        totalSupply = 3800000*crypto;                                 

        initialsupply = 120000000*startcrypto;

        emission = 7200*crypto; 

        currentEpoch = 1; 

        currentDay = 1;                             

        genesis = now;

        

        daysPerEpoch = 180; 

        secondsPerDay = 86400; 

       

        administrator = msg.sender;

        balanceOf[administrator] = initialsupply; 

        emit Transfer(administrator, address(this), initialsupply);                                

        nextEpochTime = genesis + (secondsPerDay * daysPerEpoch);                                   

        nextDayTime = genesis + secondsPerDay;                                                      

        

        emission_Whitelisted[administrator] = true;

        

        

        

    }

    

//========================================CONFIGURATIONS=========================================//

    

    function poolconfigs(address _axia, address _swap, address _defi, address _oracle) public onlyAdministrator returns (bool success) {

        

        lonePool = _axia;

        swapPool = _swap;

        DefiPool = _defi;

        OraclePool = _oracle;

        

        

        

        return true;

    }

    

    function burningPoolconfigs(address _pooladdress) public onlyAdministrator returns (bool success) {

           

        burningPool = _pooladdress;

        

        return true;

    }

    

    

    modifier onlyAdministrator() {

        require(msg.sender == administrator, "Ownable: caller is not the owner");

        _;

    }

    

    modifier onlyBurningPool() {

        require(msg.sender == burningPool, "Authorization: Only the pool that allows burn can call on this");

        _;

    }

    

    function secondAndDay(uint _secondsperday, uint _daysperepoch) public onlyAdministrator returns (bool success) {

       secondsPerDay = _secondsperday;

       daysPerEpoch = _daysperepoch;

        return true;

    }

    

    function nextEpoch(uint _nextepoch) public onlyAdministrator returns (bool success) {

       nextEpochTime = _nextepoch;

       

        return true;

    }

    

    function whitelistOnEmission(address _address) public onlyAdministrator returns (bool success) {

       emission_Whitelisted[_address] = true;

        return true;

    }

    

    function unwhitelistOnEmission(address _address) public onlyAdministrator returns (bool success) {

       emission_Whitelisted[_address] = false;

        return true;

    }

    

    

    function supplyeffect(uint _amount) public onlyBurningPool returns (bool success) {

       totalSupply -= _amount;

       emit BurnEvent(burningPool, address(0x0), _amount);

        return true;

    }

    

    function poolpercentages(uint _p1, uint _p2, uint _p3, uint _p4, uint _basispercent, uint trigRe) public onlyAdministrator returns (bool success) {

       

       pool1percentage = _p1;

       pool2percentage = _p2;

       pool3percentage = _p3;

       pool4percentage = _p4;

       basispercentage = _basispercent;

       trigRewardpercentage = trigRe;

       

       return true;

    }

    

    function Burn(uint _amount) public returns (bool success) {

       

       require(balanceOf[msg.sender] >= _amount, "You do not have the amount of tokens you wanna burn in your wallet");

       balanceOf[msg.sender] -= _amount;

       totalSupply -= _amount;

       emit BurnEvent(msg.sender, address(0x0), _amount);

       return true;

       

    }

    

   //========================================ERC20=========================================//

    // ERC20 Transfer function

    function transfer(address to, uint value) public override returns (bool success) {

        _transfer(msg.sender, to, value);

        return true;

    }

    // ERC20 Approve function

    function approve(address spender, uint value) public override returns (bool success) {

        allowance[msg.sender][spender] = value;

        emit Approval(msg.sender, spender, value);

        return true;

    }

    // ERC20 TransferFrom function

    function transferFrom(address from, address to, uint value) public override returns (bool success) {

        require(value <= allowance[from][msg.sender], 'Must not send more than allowance');

        allowance[from][msg.sender] -= value;

        _transfer(from, to, value);

        return true;

    }

    

  

    

    // Internal transfer function which includes the Fee

    function _transfer(address _from, address _to, uint _value) private {

        

        messagesender = msg.sender; //this is the person actually making the call on this function

        

        

        require(balanceOf[_from] >= _value, 'Must not send more than balance');

        require(balanceOf[_to] + _value >= balanceOf[_to], 'Balance overflow');

        

        balanceOf[_from] -= _value;

        

        

        if(emission_Whitelisted[messagesender] == false){ 

          

                if(now >= nextDayTime){

                

                amountToEmit = emittingAmount();

                

                

                uint basisAmountQuota = mulDiv(amountToEmit, basispercentage, 10000);

                amountToEmit = amountToEmit - basisAmountQuota;

                basisAmount = basisAmountQuota;

                

                pool1Amount = mulDiv(amountToEmit, pool1percentage, 10000);

                pool2Amount = mulDiv(amountToEmit, pool2percentage, 10000);

                pool3Amount = mulDiv(amountToEmit, pool3percentage, 10000);

                pool4Amount = mulDiv(amountToEmit, pool4percentage, 10000);

                

                

                

                poolAmountTrig = mulDiv(amountToEmit, trigRewardpercentage, 10000);

                TrigAmount = poolAmountTrig.div(2);

                

                pool1Amount = pool1Amount.sub(TrigAmount);

                pool2Amount = pool2Amount.sub(TrigAmount);

                

                TrigReward = poolAmountTrig;

                

                uint Ofrozenamount = ospfrozen();

                uint Dfrozenamount = dspfrozen();

                uint Ufrozenamount = uspfrozen();

                uint Afrozenamount = aspfrozen();

                

                balanceOf[address(this)] += basisAmount;

                emit Transfer(address(this), address(this), basisAmount);

                BPE += basisAmount;

                

                

                if(Ofrozenamount > 0){

                    

                OSP(OraclePool).scaledToken(pool4Amount);

                balanceOf[OraclePool] += pool4Amount;

                emit Transfer(address(this), OraclePool, pool4Amount);

                

                

                    

                }else{

                  

                 balanceOf[address(this)] += pool4Amount; 

                 emit Transfer(address(this), address(this), pool4Amount);

                 

                 BPE += pool4Amount;

                    

                }

                

                if(Dfrozenamount > 0){

                    

                DSP(DefiPool).scaledToken(pool3Amount);

                balanceOf[DefiPool] += pool3Amount;

                emit Transfer(address(this), DefiPool, pool3Amount);

                

                

                    

                }else{

                  

                 balanceOf[address(this)] += pool3Amount; 

                 emit Transfer(address(this), address(this), pool3Amount);

                 BPE += pool3Amount;

                    

                }

                

                if(Ufrozenamount > 0){

                    

                USP(swapPool).scaledToken(pool2Amount);

                balanceOf[swapPool] += pool2Amount;

                emit Transfer(address(this), swapPool, pool2Amount);

                

                    

                }else{

                  

                 balanceOf[address(this)] += pool2Amount; 

                 emit Transfer(address(this), address(this), pool2Amount);

                 BPE += pool2Amount;

                    

                }

                

                if(Afrozenamount > 0){

                    

                 ASP(lonePool).scaledToken(pool1Amount);

                 balanceOf[lonePool] += pool1Amount;

                 emit Transfer(address(this), lonePool, pool1Amount);

                

                }else{

                  

                 balanceOf[address(this)] += pool1Amount; 

                 emit Transfer(address(this), address(this), pool1Amount);

                 BPE += pool1Amount;

                    

                }

                

                nextDayTime += secondsPerDay;

                currentDay += 1; 

                emit NewDay(currentEpoch, currentDay, nextDayTime);

                

                //reward the wallet that triggered the EMISSION

                balanceOf[_from] += TrigReward; //this is rewardig the person that triggered the emission

                emit Transfer(address(this), _from, TrigReward);

                emit TrigRewardEvent(address(this), msg.sender, TrigReward);

                

            }

        

            

        }

       

       balanceOf[_to] += _value;

       emit Transfer(_from, _to, _value);

    }

    

    



    

   

    //======================================EMISSION========================================//

    // Internal - Update emission function

    

    function emittingAmount() internal returns(uint){

       

        if(now >= nextEpochTime){

            

            currentEpoch += 1;

            

            if(currentEpoch > 10){

            

               emission = BPE;

               BPE -= emission.div(2);

               balanceOf[address(this)] -= emission.div(2);

            

               

            }

            emission = emission/2;

            nextEpochTime += (secondsPerDay * daysPerEpoch);

            emit NewEpoch(currentEpoch, emission, nextEpochTime);

          

        }

        

        return emission;

        

        

    }

  

  

  

    function ospfrozen() public view returns(uint){

        

        return OSP(OraclePool).totalFrozen();

       

    }

    

    function dspfrozen() public view returns(uint){

        

        return DSP(DefiPool).totalFrozen();

       

    }

    

    function uspfrozen() public view returns(uint){

        

        return USP(swapPool).totalFrozen();

       

    } 

    

    function aspfrozen() public view returns(uint){

        

        return ASP(lonePool).totalFrozen();

       

    }

    

     function mulDiv (uint x, uint y, uint z) public pure returns (uint) {

          (uint l, uint h) = fullMul (x, y);

          assert (h < z);

          uint mm = mulmod (x, y, z);

          if (mm > l) h -= 1;

          l -= mm;

          uint pow2 = z & -z;

          z /= pow2;

          l /= pow2;

          l += h * ((-pow2) / pow2 + 1);

          uint r = 1;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          return l * r;

    }

    

     function fullMul (uint x, uint y) private pure returns (uint l, uint h) {

          uint mm = mulmod (x, y, uint (-1));

          l = x * y;

          h = mm - l;

          if (mm < l) h -= 1;

    }

    

   

}

Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #
    - [Ext] supplyeffect #

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

 +  ASP 
    - [Pub]  #
    - [Pub] tokenconfigs #
       - modifiers: onlyCreator
    - [Pub] _minStakeAmount #
       - modifiers: onlyCreator
    - [Pub] stakingStatus #
       - modifiers: onlyCreator
    - [Pub] unstakeburnrate #
       - modifiers: onlyCreator
    - [Pub] MIN_DIVIDENDS_DUR_TIME #
       - modifiers: onlyCreator
    - [Ext] StakeAxiaTokens #
    - [Ext] UnstakeAxiaTokens #
    - [Pub] totalFrozen
    - [Pub] frozenOf
    - [Pub] dividendsOf
    - [Pub] userData
    - [Int] _stake #
    - [Int] _unstake #
    - [Pub] TakeDividends #
    - [Ext] scaledToken #
       - modifiers: onlyAxiaToken
    - [Pub] mulDiv
    - [Prv] fullMul


							

Source Code

Click here to download the source code as a .sol file.


/**

 *Submitted for verification at Etherscan.io on 2020-10-09

*/



/*



* @dev This is the Axia Protocol Staking pool contract (AXIA LONE Pool), a part of the protocol where stakers are rewarded in AXIA tokens 

* when they make stakes of Axia tokens.



* stakers reward come from the daily emission from the total supply into circulation,

* this happens daily and upon the reach of a new epoch each made of 180 days, 

* halvings are experienced on the emitting amount of tokens.





* on the 11th epoch all the tokens would have been completed emitted into circulation,

* from here on, the stakers will still be earning from daily emissions

* which would now be coming from the accumulated basis points over the epochs.



* upon unstaking, stakers are charged a fee of 1% of their unstaking sum which is

* burnt forever, thereby reducing the total supply. this gives the Axia token its deflationary feature.





*/

pragma solidity 0.6.4;





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);

    

    function supplyeffect(uint _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 {

    /**

     * @dev Returns the addition of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `+` operator.

     *

     * Requirements:

     *

     * - Addition cannot overflow.

     */

    function add(uint256 a, uint256 b) internal pure returns (uint256) {

        uint256 c = a + b;

        require(c >= a, "SafeMath: addition overflow");



        return c;

    }

 

    /**

     * @dev Returns the subtraction of two unsigned integers, reverting on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {

        return sub(a, b, "SafeMath: subtraction overflow");

    }



    /**

     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b <= a, errorMessage);

        uint256 c = a - b;



        return c;

    }



    /**

     * @dev Returns the multiplication of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `*` operator.

     *

     * Requirements:

     *

     * - Multiplication cannot overflow.

     */

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the

        // benefit is lost if 'b' is also tested.

        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522

        if (a == 0) {

            return 0;

        }



        uint256 c = a * b;

        require(c / a == b, "SafeMath: multiplication overflow");



        return c;

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b) internal pure returns (uint256) {

        return div(a, b, "SafeMath: division by zero");

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b > 0, errorMessage);

        uint256 c = a / b;

        // assert(a == b * c + a % b); // There is no case in which this doesn't hold



        return c;

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {

        return mod(a, b, "SafeMath: modulo by zero");

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts with custom message when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b != 0, errorMessage);

        return a % b;

    }

}







contract ASP{

    

    using SafeMath for uint256;

    

    //======================================EVENTS=========================================//

    event StakeEvent(address indexed staker, address indexed pool, uint amount);

    event UnstakeEvent(address indexed unstaker, address indexed pool, uint amount);

    event RewardEvent(address indexed staker, address indexed pool, uint amount);

    event RewardStake(address indexed staker, address indexed pool, uint amount);

    

    

    //======================================STAKING POOL=========================================//

    address public Axiatoken;

    

    bool public stakingEnabled;

    

    uint256 constant private FLOAT_SCALAR = 2**64;

    uint256 public MINIMUM_STAKE = 1000000000000000000; // 1000 AXIA Tokens

	uint256 public MIN_DIVIDENDS_DUR = 18 hours;

	uint256 private  UNSTAKE_FEE = 1; //1% burns when you unstake

	uint public infocheck;

	uint _burnedAmount;

	uint actualValue;

    

    struct User {

		uint256 balance;

		uint256 frozen;

		int256 scaledPayout;  

		uint256 staketime;

	}



	struct Info {

		uint256 totalSupply;

		uint256 totalFrozen;

		mapping(address => User) users;

		uint256 scaledPayoutPerToken; //pool balance 

		address admin;

	}

	

	Info private info;

	

	

	constructor() public {

       

	    info.admin = msg.sender;

		stakingEnabled = false;

		

	}

	

//======================================ADMINSTRATION=========================================//



	modifier onlyCreator() {

        require(msg.sender == info.admin, "Ownable: caller is not the administrator");

        _;

    }

    

    modifier onlyAxiaToken() {

        require(msg.sender == Axiatoken, "Authorization: only token contract can call");

        _;

    }

    

	 function tokenconfigs(address _axiatoken) public onlyCreator returns (bool success) {

        Axiatoken = _axiatoken;

        return true;

    }

	

	function _minStakeAmount(uint256 _number) onlyCreator public {

		

		MINIMUM_STAKE = _number*1000000000000000000;

		

	}

    

    function stakingStatus(bool _status) public onlyCreator {

    require(Axiatoken != address(0), "Pool address is not yet setup");

	stakingEnabled = _status;

    }

    

    function unstakeburnrate(uint _rate) public onlyCreator returns (bool success) {

        UNSTAKE_FEE = _rate;

        return true;

    }

    

    

    function MIN_DIVIDENDS_DUR_TIME(uint256 _minDuration) public onlyCreator {

        

	MIN_DIVIDENDS_DUR = _minDuration;

	

    }

//======================================USER WRITE=========================================//



	function StakeAxiaTokens(uint256 _tokens) external {

		_stake(_tokens);

	}

    

    function UnstakeAxiaTokens(uint256 _tokens) external {

		_unstake(_tokens);

	}

	

//======================================USER READ=========================================//



	function totalFrozen() public view returns (uint256) {

		return info.totalFrozen;

	}

	

    function frozenOf(address _user) public view returns (uint256) {

		return info.users[_user].frozen;

	}



	function dividendsOf(address _user) public view returns (uint256) {

	    

	    if(info.users[_user].staketime < MIN_DIVIDENDS_DUR){

	        return 0;

	    }else{

	     return uint256(int256(info.scaledPayoutPerToken * info.users[_user].frozen) - info.users[_user].scaledPayout) / FLOAT_SCALAR;   

	    }

	}

	



	function userData(address _user) public view 

	returns (uint256 totalTokensFrozen, uint256 userFrozen, 

	uint256 userDividends, uint256 userStaketime, int256 scaledPayout) {

	    

		return (totalFrozen(), frozenOf(_user), dividendsOf(_user), info.users[_user].staketime, info.users[_user].scaledPayout);

	

	    

	}

	



//======================================ACTION CALLS=========================================//	

	

	function _stake(uint256 _amount) internal {

	    

	    require(stakingEnabled, "Staking not yet initialized");

	    

		require(IERC20(Axiatoken).balanceOf(msg.sender) >= _amount, "Insufficient Axia token balance");

		require(frozenOf(msg.sender) + _amount >= MINIMUM_STAKE, "Your amount is lower than the minimum amount allowed to stake");

		require(IERC20(Axiatoken).allowance(msg.sender, address(this)) >= _amount, "Not enough allowance given to contract yet to spend by user");

		

		info.users[msg.sender].staketime = now;

		info.totalFrozen += _amount;

		info.users[msg.sender].frozen += _amount;

		

		info.users[msg.sender].scaledPayout += int256(_amount * info.scaledPayoutPerToken); 

		IERC20(Axiatoken).transferFrom(msg.sender, address(this), _amount);      // Transfer liquidity tokens from the sender to this contract

		

        emit StakeEvent(msg.sender, address(this), _amount);

	}

	

	    

	

	function _unstake(uint256 _amount) internal {

	    

		require(frozenOf(msg.sender) >= _amount, "You currently do not have up to that amount staked");

		

		info.totalFrozen -= _amount;

		info.users[msg.sender].frozen -= _amount;

		info.users[msg.sender].scaledPayout -= int256(_amount * info.scaledPayoutPerToken);

		

		_burnedAmount = mulDiv(_amount, UNSTAKE_FEE, 100);

		actualValue = _amount.sub(_burnedAmount);

		

		require(IERC20(Axiatoken).transfer(msg.sender, actualValue), "Transaction failed");

        emit UnstakeEvent(address(this), msg.sender, actualValue);

		

		

		require(IERC20(Axiatoken).transfer(address(0x0), _burnedAmount), "Transaction failed");

 		IERC20(Axiatoken).supplyeffect(_burnedAmount);

 		

 		TakeDividends();

 		

		

	}

	

	



		

		

	function TakeDividends() public returns (uint256) {

		    

		uint256 _dividends = dividendsOf(msg.sender);

		require(_dividends >= 0, "you do not have any dividend yet");

		info.users[msg.sender].scaledPayout += int256(_dividends * FLOAT_SCALAR);

		

		require(IERC20(Axiatoken).transfer(msg.sender, _dividends), "Transaction Failed");    // Transfer dividends to msg.sender

		emit RewardEvent(msg.sender, address(this), _dividends);

		

		return _dividends;

	    

		    

	}

		

		

	function scaledToken(uint _amount) external onlyAxiaToken returns(bool){

            

    		info.scaledPayoutPerToken += _amount * FLOAT_SCALAR / info.totalFrozen;

    		infocheck = info.scaledPayoutPerToken;

    		return true;

            

    }

 

        

    function mulDiv (uint x, uint y, uint z) public pure returns (uint) {

              (uint l, uint h) = fullMul (x, y);

              assert (h < z);

              uint mm = mulmod (x, y, z);

              if (mm > l) h -= 1;

              l -= mm;

              uint pow2 = z & -z;

              z /= pow2;

              l /= pow2;

              l += h * ((-pow2) / pow2 + 1);

              uint r = 1;

              r *= 2 - z * r;

              r *= 2 - z * r;

              r *= 2 - z * r;

              r *= 2 - z * r;

              r *= 2 - z * r;

              r *= 2 - z * r;

              r *= 2 - z * r;

              r *= 2 - z * r;

              return l * r;

    }

        

    function fullMul (uint x, uint y) private pure returns (uint l, uint h) {

              uint mm = mulmod (x, y, uint (-1));

              l = x * y;

              h = mm - l;

              if (mm < l) h -= 1;

    }

 

    

}

Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

 +  DSP 
    - [Pub]  #
    - [Pub] tokenconfigs #
       - modifiers: onlyCreator
    - [Pub] _minStakeAmount #
       - modifiers: onlyCreator
    - [Pub] stakingStatus #
       - modifiers: onlyCreator
    - [Pub] MIN_DIVIDENDS_DUR_TIME #
       - modifiers: onlyCreator
    - [Ext] StakeTokens #
    - [Ext] UnstakeTokens #
    - [Pub] totalFrozen
    - [Pub] frozenOf
    - [Pub] dividendsOf
    - [Pub] userData
    - [Int] _stake #
    - [Int] _unstake #
    - [Pub] TakeDividends #
    - [Ext] scaledToken #
       - modifiers: onlyAxiaToken
    - [Pub] mulDiv
    - [Prv] fullMul
							

Source Code

Click here to download the source code as a .sol file.


/**

 *Submitted for verification at Etherscan.io on 2020-10-09

*/



/*



* @dev This is the Axia Protocol Staking pool 2 contract (Defi Fund Pool), 

* a part of the protocol where stakers are rewarded in AXIA tokens 

* when they make stakes of liquidity tokens from the oracle pool.



* stakers reward come from the daily emission from the total supply into circulation,

* this happens daily and upon the reach of a new epoch each made of 180 days, 

* halvings are experienced on the emitting amount of tokens.



* on the 11th epoch all the tokens would have been completed emitted into circulation,

* from here on, the stakers will still be earning from daily emissions

* which would now be coming from the accumulated basis points over the epochs.



* stakers are not charged any fee for unstaking.





*/

pragma solidity 0.6.4;



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 {

    /**

     * @dev Returns the addition of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `+` operator.

     *

     * Requirements:

     *

     * - Addition cannot overflow.

     */

    function add(uint256 a, uint256 b) internal pure returns (uint256) {

        uint256 c = a + b;

        require(c >= a, "SafeMath: addition overflow");



        return c;

    }

 

    /**

     * @dev Returns the subtraction of two unsigned integers, reverting on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {

        return sub(a, b, "SafeMath: subtraction overflow");

    }



    /**

     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b <= a, errorMessage);

        uint256 c = a - b;



        return c;

    }



    /**

     * @dev Returns the multiplication of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `*` operator.

     *

     * Requirements:

     *

     * - Multiplication cannot overflow.

     */

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the

        // benefit is lost if 'b' is also tested.

        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522

        if (a == 0) {

            return 0;

        }



        uint256 c = a * b;

        require(c / a == b, "SafeMath: multiplication overflow");



        return c;

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b) internal pure returns (uint256) {

        return div(a, b, "SafeMath: division by zero");

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b > 0, errorMessage);

        uint256 c = a / b;

        // assert(a == b * c + a % b); // There is no case in which this doesn't hold



        return c;

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {

        return mod(a, b, "SafeMath: modulo by zero");

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts with custom message when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b != 0, errorMessage);

        return a % b;

    }

}







contract DSP{

    

    using SafeMath for uint256;

    

//======================================EVENTS=========================================//

    event StakeEvent(address indexed staker, address indexed pool, uint amount);

    event UnstakeEvent(address indexed unstaker, address indexed pool, uint amount);

    event RewardEvent(address indexed staker, address indexed pool, uint amount);

    event RewardStake(address indexed staker, address indexed pool, uint amount);

    

    

//======================================STAKING POOLS=========================================//

    address public Axiatoken;

    address public DefiIndexFunds;

    

    address public administrator;

    

    bool public stakingEnabled;

    

    uint256 constant private FLOAT_SCALAR = 2**64;

    uint256 public MINIMUM_STAKE = 1000000000000000000; // 1 minimum

	uint256 public MIN_DIVIDENDS_DUR = 18 hours;

	

	uint public infocheck;

    

    struct User {

		uint256 balance;

		uint256 frozen;

		int256 scaledPayout;  

		uint256 staketime;

	}



	struct Info {

		uint256 totalSupply;

		uint256 totalFrozen;

		mapping(address => User) users;

		uint256 scaledPayoutPerToken; //pool balance 

		address admin;

	}

	

	Info private info;

	

	

	constructor() public {

	    

        info.admin = msg.sender;

        stakingEnabled = false;

	}



//======================================ADMINSTRATION=========================================//



	modifier onlyCreator() {

        require(msg.sender == info.admin, "Ownable: caller is not the administrator");

        _;

    }

    

    modifier onlyAxiaToken() {

        require(msg.sender == Axiatoken, "Authorization: only token contract can call");

        _;

    }

    

	 function tokenconfigs(address _axiatoken, address _defiindex) public onlyCreator returns (bool success) {

        require(_axiatoken != _defiindex, "Insertion of same address is not supported");

        require(_axiatoken != address(0) && _defiindex != address(0), "Insertion of address(0) is not supported");

        Axiatoken = _axiatoken;

        DefiIndexFunds = _defiindex;

        return true;

    }

	

	function _minStakeAmount(uint256 _number) onlyCreator public {

		

		MINIMUM_STAKE = _number*1000000000000000000;

		

	}

	

	function stakingStatus(bool _status) public onlyCreator {

	    require(Axiatoken != address(0) && DefiIndexFunds != address(0), "Pool addresses are not yet setup");

	stakingEnabled = _status;

    }

    

    

    function MIN_DIVIDENDS_DUR_TIME(uint256 _minDuration) public onlyCreator {

        

	MIN_DIVIDENDS_DUR = _minDuration;

	

    }

    

//======================================USER WRITE=========================================//



	function StakeTokens(uint256 _tokens) external {

		_stake(_tokens);

	}

	

	function UnstakeTokens(uint256 _tokens) external {

		_unstake(_tokens);

	}

    



//======================================USER READ=========================================//



	function totalFrozen() public view returns (uint256) {

		return info.totalFrozen;

	}

	

    function frozenOf(address _user) public view returns (uint256) {

		return info.users[_user].frozen;

	}



	function dividendsOf(address _user) public view returns (uint256) {

	    

	    if(info.users[_user].staketime < MIN_DIVIDENDS_DUR){

	        return 0;

	    }else{

	     return uint256(int256(info.scaledPayoutPerToken * info.users[_user].frozen) - info.users[_user].scaledPayout) / FLOAT_SCALAR;   

	    }

	    

	}

	



	function userData(address _user) public view 

	returns (uint256 totalTokensFrozen, uint256 userFrozen, 

	uint256 userDividends, uint256 userStaketime, int256 scaledPayout) {

	    

		return (totalFrozen(), frozenOf(_user), dividendsOf(_user), info.users[_user].staketime, info.users[_user].scaledPayout);

	

	    

	}

	



//======================================ACTION CALLS=========================================//	

	

	function _stake(uint256 _amount) internal {

	    

	    require(stakingEnabled, "Staking not yet initialized");

	    

		require(IERC20(DefiIndexFunds).balanceOf(msg.sender) >= _amount, "Insufficient DeFi AFT balance");

		require(frozenOf(msg.sender) + _amount >= MINIMUM_STAKE, "Your amount is lower than the minimum amount allowed to stake");

		require(IERC20(DefiIndexFunds).allowance(msg.sender, address(this)) >= _amount, "Not enough allowance given to contract yet to spend by user");

		

		info.users[msg.sender].staketime = now;

		info.totalFrozen += _amount;

		info.users[msg.sender].frozen += _amount;

		

		info.users[msg.sender].scaledPayout += int256(_amount * info.scaledPayoutPerToken); 

		IERC20(DefiIndexFunds).transferFrom(msg.sender, address(this), _amount);      // Transfer liquidity tokens from the sender to this contract

		

        emit StakeEvent(msg.sender, address(this), _amount);

	}

	

    

    

 

	function _unstake(uint256 _amount) internal {

	    

		require(frozenOf(msg.sender) >= _amount, "You currently do not have up to that amount staked");

		

		info.totalFrozen -= _amount;

		info.users[msg.sender].frozen -= _amount;

		info.users[msg.sender].scaledPayout -= int256(_amount * info.scaledPayoutPerToken);

		

		require(IERC20(DefiIndexFunds).transfer(msg.sender, _amount), "Transaction failed");

        emit UnstakeEvent(address(this), msg.sender, _amount);

		

		TakeDividends();

	}

	

		

	function TakeDividends() public returns (uint256) {

		    

		uint256 _dividends = dividendsOf(msg.sender);

		require(_dividends >= 0, "you do not have any dividend yet");

		info.users[msg.sender].scaledPayout += int256(_dividends * FLOAT_SCALAR);

		

		require(IERC20(Axiatoken).transfer(msg.sender, _dividends), "Transaction Failed");    // Transfer dividends to msg.sender

		emit RewardEvent(msg.sender, address(this), _dividends);

		

		return _dividends;

	    

		    

	}

 

    function scaledToken(uint _amount) external onlyAxiaToken returns(bool){

            

    		info.scaledPayoutPerToken += _amount * FLOAT_SCALAR / info.totalFrozen;

    		infocheck = info.scaledPayoutPerToken;

    		return true;

            

    }

 

        

    function mulDiv (uint x, uint y, uint z) public pure returns (uint) {

          (uint l, uint h) = fullMul (x, y);

          assert (h < z);

          uint mm = mulmod (x, y, z);

          if (mm > l) h -= 1;

          l -= mm;

          uint pow2 = z & -z;

          z /= pow2;

          l /= pow2;

          l += h * ((-pow2) / pow2 + 1);

          uint r = 1;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          return l * r;

    }

    

     function fullMul (uint x, uint y) private pure returns (uint l, uint h) {

          uint mm = mulmod (x, y, uint (-1));

          l = x * y;

          h = mm - l;

          if (mm < l) h -= 1;

    }

 

    

}


Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

 +  OSP 
    - [Pub]  #
    - [Pub] tokenconfigs #
       - modifiers: onlyCreator
    - [Pub] _minStakeAmount #
       - modifiers: onlyCreator
    - [Pub] stakingStatus #
       - modifiers: onlyCreator
    - [Pub] MIN_DIVIDENDS_DUR_TIME #
       - modifiers: onlyCreator
    - [Ext] StakeTokens #
    - [Ext] UnstakeTokens #
    - [Pub] totalFrozen
    - [Pub] frozenOf
    - [Pub] dividendsOf
    - [Pub] userData
    - [Int] _stake #
    - [Int] _unstake #
    - [Pub] TakeDividends #
    - [Ext] scaledToken #
       - modifiers: onlyAxiaToken
    - [Pub] mulDiv
    - [Prv] fullMul

							

Source Code

Click here to download the source code as a .sol file.


/**

 *Submitted for verification at Etherscan.io on 2020-10-09

*/



/*



* @dev This is the Axia Protocol Staking pool 1 contract (Oracle FUND Pool), 

* a part of the protocol where stakers are rewarded in AXIA tokens 

* when they make stakes of liquidity tokens from the oracle pool.



* stakers reward come from the daily emission from the total supply into circulation,

* this happens daily and upon the reach of a new epoch each made of 180 days, 

* halvings are experienced on the emitting amount of tokens.



* on the 11th epoch all the tokens would have been completed emitted into circulation,

* from here on, the stakers will still be earning from daily emissions

* which would now be coming from the accumulated basis points over the epochs.



* stakers are not charged any fee for unstaking.



*/

pragma solidity 0.6.4;



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 {

    /**

     * @dev Returns the addition of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `+` operator.

     *

     * Requirements:

     *

     * - Addition cannot overflow.

     */

    function add(uint256 a, uint256 b) internal pure returns (uint256) {

        uint256 c = a + b;

        require(c >= a, "SafeMath: addition overflow");



        return c;

    }

 

    /**

     * @dev Returns the subtraction of two unsigned integers, reverting on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {

        return sub(a, b, "SafeMath: subtraction overflow");

    }



    /**

     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b <= a, errorMessage);

        uint256 c = a - b;



        return c;

    }



    /**

     * @dev Returns the multiplication of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `*` operator.

     *

     * Requirements:

     *

     * - Multiplication cannot overflow.

     */

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the

        // benefit is lost if 'b' is also tested.

        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522

        if (a == 0) {

            return 0;

        }



        uint256 c = a * b;

        require(c / a == b, "SafeMath: multiplication overflow");



        return c;

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b) internal pure returns (uint256) {

        return div(a, b, "SafeMath: division by zero");

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b > 0, errorMessage);

        uint256 c = a / b;

        // assert(a == b * c + a % b); // There is no case in which this doesn't hold



        return c;

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {

        return mod(a, b, "SafeMath: modulo by zero");

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts with custom message when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b != 0, errorMessage);

        return a % b;

    }

}







contract OSP{

    

    using SafeMath for uint256;

    

//======================================EVENTS=========================================//

    event StakeEvent(address indexed staker, address indexed pool, uint amount);

    event UnstakeEvent(address indexed unstaker, address indexed pool, uint amount);

    event RewardEvent(address indexed staker, address indexed pool, uint amount);

    event RewardStake(address indexed staker, address indexed pool, uint amount);

    

    

//======================================STAKING POOLS=========================================//

    address public Axiatoken;

    address public OracleIndexFunds;

    

    address public administrator;

    

    bool public stakingEnabled;

    

    uint256 constant private FLOAT_SCALAR = 2**64;

    uint256 public MINIMUM_STAKE = 1000000000000000000; // 1 minimum

	uint256  public MIN_DIVIDENDS_DUR = 18 hours;

	

	uint public infocheck;

    

    struct User {

		uint256 balance;

		uint256 frozen;

		int256 scaledPayout;  

		uint256 staketime;

	}



	struct Info {

		uint256 totalSupply;

		uint256 totalFrozen;

		mapping(address => User) users;

		uint256 scaledPayoutPerToken;

		address admin;

	}

	

	Info private info;

	

	

	constructor() public {

	    

        info.admin = msg.sender;

        stakingEnabled = false;

	}



//======================================ADMINSTRATION=========================================//



	modifier onlyCreator() {

        require(msg.sender == info.admin, "Ownable: caller is not the administrator");

        _;

    }

    

    modifier onlyAxiaToken() {

        require(msg.sender == Axiatoken, "Authorization: only token contract can call");

        _;

    }

    

	 function tokenconfigs(address _axiatoken, address _oracleindex) public onlyCreator returns (bool success) {

	    require(_axiatoken != _oracleindex, "Insertion of same address is not supported");

	    require(_axiatoken != address(0) && _oracleindex != address(0), "Insertion of address(0) is not supported");

        Axiatoken = _axiatoken;

        OracleIndexFunds = _oracleindex;

        return true;

    }

	

	function _minStakeAmount(uint256 _number) onlyCreator public {

		

		MINIMUM_STAKE = _number*1000000000000000000;

		

	}

	

	function stakingStatus(bool _status) public onlyCreator {

	require(Axiatoken != address(0) && OracleIndexFunds != address(0), "Pool addresses are not yet setup");

	stakingEnabled = _status;

    }

    

    function MIN_DIVIDENDS_DUR_TIME(uint256 _minDuration) public onlyCreator {

        

	MIN_DIVIDENDS_DUR = _minDuration;

	

    }

//======================================USER WRITE=========================================//



	function StakeTokens(uint256 _tokens) external {

		_stake(_tokens);

	}

	

	function UnstakeTokens(uint256 _tokens) external {

		_unstake(_tokens);

	}

    



//======================================USER READ=========================================//



	function totalFrozen() public view returns (uint256) {

		return info.totalFrozen;

	}

	

    function frozenOf(address _user) public view returns (uint256) {

		return info.users[_user].frozen;

	}



	function dividendsOf(address _user) public view returns (uint256) {

	    

	    if(info.users[_user].staketime < MIN_DIVIDENDS_DUR){

	        return 0;

	    }else{

	     return uint256(int256(info.scaledPayoutPerToken * info.users[_user].frozen) - info.users[_user].scaledPayout) / FLOAT_SCALAR;   

	    }

	}

	



	function userData(address _user) public view 

	returns (uint256 totalTokensFrozen, uint256 userFrozen, 

	uint256 userDividends, uint256 userStaketime, int256 scaledPayout) {

	    

		return (totalFrozen(), frozenOf(_user), dividendsOf(_user), info.users[_user].staketime, info.users[_user].scaledPayout);

	

	    

	}

	



//======================================ACTION CALLS=========================================//	

	

	function _stake(uint256 _amount) internal {

	    

	    require(stakingEnabled, "Staking not yet initialized");

	    

		require(IERC20(OracleIndexFunds).balanceOf(msg.sender) >= _amount, "Insufficient Oracle AFT token balance");

		require(frozenOf(msg.sender) + _amount >= MINIMUM_STAKE, "Your amount is lower than the minimum amount allowed to stake");

		require(IERC20(OracleIndexFunds).allowance(msg.sender, address(this)) >= _amount, "Not enough allowance given to contract yet to spend by user");

		

		info.users[msg.sender].staketime = now;

		info.totalFrozen += _amount;

		info.users[msg.sender].frozen += _amount;

		

		info.users[msg.sender].scaledPayout += int256(_amount * info.scaledPayoutPerToken); 

		IERC20(OracleIndexFunds).transferFrom(msg.sender, address(this), _amount);      

		

        emit StakeEvent(msg.sender, address(this), _amount);

	}

	

    

    

 

	function _unstake(uint256 _amount) internal {

	    

		require(frozenOf(msg.sender) >= _amount, "You currently do not have up to that amount staked");

		

		info.totalFrozen -= _amount;

		info.users[msg.sender].frozen -= _amount;

		info.users[msg.sender].scaledPayout -= int256(_amount * info.scaledPayoutPerToken);

		

		require(IERC20(OracleIndexFunds).transfer(msg.sender, _amount), "Transaction failed");

        emit UnstakeEvent(address(this), msg.sender, _amount);

        

        TakeDividends();

		

	}

	

		

	function TakeDividends() public returns (uint256) {

		    

		uint256 _dividends = dividendsOf(msg.sender);

		require(_dividends >= 0, "you do not have any dividend yet");

		info.users[msg.sender].scaledPayout += int256(_dividends * FLOAT_SCALAR);

		

		require(IERC20(Axiatoken).transfer(msg.sender, _dividends), "Transaction Failed");    // Transfer dividends to msg.sender

		emit RewardEvent(msg.sender, address(this), _dividends);

		

		return _dividends;

	    

		    

	}

	

 

    function scaledToken(uint _amount) external onlyAxiaToken returns(bool){

            

    		info.scaledPayoutPerToken += _amount * FLOAT_SCALAR / info.totalFrozen;

    		infocheck = info.scaledPayoutPerToken;

    		return true;

            

    }

 

        

    function mulDiv (uint x, uint y, uint z) public pure returns (uint) {

          (uint l, uint h) = fullMul (x, y);

          assert (h < z);

          uint mm = mulmod (x, y, z);

          if (mm > l) h -= 1;

          l -= mm;

          uint pow2 = z & -z;

          z /= pow2;

          l /= pow2;

          l += h * ((-pow2) / pow2 + 1);

          uint r = 1;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          return l * r;

    }

    

     function fullMul (uint x, uint y) private pure returns (uint l, uint h) {

          uint mm = mulmod (x, y, uint (-1));

          l = x * y;

          h = mm - l;

          if (mm < l) h -= 1;

    }

 

    

}

Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

 +  USP 
    - [Pub]  #
    - [Pub] tokenconfigs #
       - modifiers: onlyCreator
    - [Pub] _minStakeAmount #
       - modifiers: onlyCreator
    - [Pub] stakingStatus #
       - modifiers: onlyCreator
    - [Pub] MIN_DIVIDENDS_DUR_TIME #
       - modifiers: onlyCreator
    - [Ext] StakeAxiaTokens #
    - [Ext] UnstakeAxiaTokens #
    - [Pub] totalFrozen
    - [Pub] frozenOf
    - [Pub] dividendsOf
    - [Pub] userData
    - [Int] _stake #
    - [Int] _unstake #
    - [Pub] TakeDividends #
    - [Ext] scaledToken #
       - modifiers: onlyAxiaToken
    - [Pub] mulDiv
    - [Prv] fullMul
							

Source Code

Click here to download the source code as a .sol file.



/**

 *Submitted for verification at Etherscan.io on 2020-10-09

*/



/*



* @dev This is the Axia Protocol Staking pool 3 contract (SWAP Pool), 

* a part of the protocol where stakers are rewarded in AXIA tokens 

* when they make stakes of liquidity tokens from the oracle pool.



* stakers reward come from the daily emission from the total supply into circulation,

* this happens daily and upon the reach of a new epoch each made of 180 days, 

* halvings are experienced on the emitting amount of tokens.



* on the 11th epoch all the tokens would have been completed emitted into circulation,

* from here on, the stakers will still be earning from daily emissions

* which would now be coming from the accumulated basis points over the epochs.



* stakers are not charged any fee for unstaking.



*/

pragma solidity 0.6.4;



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 {

    /**

     * @dev Returns the addition of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `+` operator.

     *

     * Requirements:

     *

     * - Addition cannot overflow.

     */

    function add(uint256 a, uint256 b) internal pure returns (uint256) {

        uint256 c = a + b;

        require(c >= a, "SafeMath: addition overflow");



        return c;

    }

 

    /**

     * @dev Returns the subtraction of two unsigned integers, reverting on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {

        return sub(a, b, "SafeMath: subtraction overflow");

    }



    /**

     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b <= a, errorMessage);

        uint256 c = a - b;



        return c;

    }



    /**

     * @dev Returns the multiplication of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `*` operator.

     *

     * Requirements:

     *

     * - Multiplication cannot overflow.

     */

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the

        // benefit is lost if 'b' is also tested.

        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522

        if (a == 0) {

            return 0;

        }



        uint256 c = a * b;

        require(c / a == b, "SafeMath: multiplication overflow");



        return c;

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b) internal pure returns (uint256) {

        return div(a, b, "SafeMath: division by zero");

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b > 0, errorMessage);

        uint256 c = a / b;

        // assert(a == b * c + a % b); // There is no case in which this doesn't hold



        return c;

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {

        return mod(a, b, "SafeMath: modulo by zero");

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts with custom message when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b != 0, errorMessage);

        return a % b;

    }

}







contract USP{

    

    using SafeMath for uint256;

    

//======================================EVENTS=========================================//

    event StakeEvent(address indexed staker, address indexed pool, uint amount);

    event UnstakeEvent(address indexed unstaker, address indexed pool, uint amount);

    event RewardEvent(address indexed staker, address indexed pool, uint amount);

    event RewardStake(address indexed staker, address indexed pool, uint amount);

    

    

//======================================STAKING POOLS=========================================//

    address public Axiatoken;

    address public UniswapV2;

    

    bool public stakingEnabled;

    

    uint256 constant private FLOAT_SCALAR = 2**64;

    uint256 public MINIMUM_STAKE = 1000000000000000000; // 1 minimum

	uint256 public MIN_DIVIDENDS_DUR = 18 hours;

	

	uint public infocheck;

    

    struct User {

		uint256 balance;

		uint256 frozen;

		int256 scaledPayout;  

		uint256 staketime;

	}



	struct Info {

		uint256 totalSupply;

		uint256 totalFrozen;

		mapping(address => User) users;

		uint256 scaledPayoutPerToken; //pool balance 

		address admin;

	}

	

	Info private info;

	

	

	constructor() public {

	    

        info.admin = msg.sender;

        stakingEnabled = false;

	}



//======================================ADMINSTRATION=========================================//



	modifier onlyCreator() {

        require(msg.sender == info.admin, "Ownable: caller is not the administrator");

        _;

    }

    

    modifier onlyAxiaToken() {

        require(msg.sender == Axiatoken, "Authorization: only token contract can call");

        _;

    }

    

	 function tokenconfigs(address _axiatoken, address _univ2) public onlyCreator returns (bool success) {

        require(_axiatoken != _univ2, "Insertion of same address is not supported");

        require(_axiatoken != address(0) && _univ2 != address(0), "Insertion of address(0) is not supported");

        Axiatoken = _axiatoken;

        UniswapV2 = _univ2;

        return true;

    }

	

	function _minStakeAmount(uint256 _number) onlyCreator public {

		

		MINIMUM_STAKE = _number*1000000000000000000;

		

	}

	

	function stakingStatus(bool _status) public onlyCreator {

	require(Axiatoken != address(0) && UniswapV2 != address(0), "Pool addresses are not yet setup");

	stakingEnabled = _status;

    }

    

    

    function MIN_DIVIDENDS_DUR_TIME(uint256 _minDuration) public onlyCreator {

        

	MIN_DIVIDENDS_DUR = _minDuration;

	

    }

    

//======================================USER WRITE=========================================//



	function StakeAxiaTokens(uint256 _tokens) external {

		_stake(_tokens);

	}

	

	function UnstakeAxiaTokens(uint256 _tokens) external {

		_unstake(_tokens);

	}

    



//======================================USER READ=========================================//



	function totalFrozen() public view returns (uint256) {

		return info.totalFrozen;

	}

	

    function frozenOf(address _user) public view returns (uint256) {

		return info.users[_user].frozen;

	}



	function dividendsOf(address _user) public view returns (uint256) {

	    

	    if(info.users[_user].staketime < MIN_DIVIDENDS_DUR){

	        return 0;

	    }else{

	     return uint256(int256(info.scaledPayoutPerToken * info.users[_user].frozen) - info.users[_user].scaledPayout) / FLOAT_SCALAR;   

	   }

	}

	



	function userData(address _user) public view 

	returns (uint256 totalTokensFrozen, uint256 userFrozen, 

	uint256 userDividends, uint256 userStaketime, int256 scaledPayout) {

	    

		return (totalFrozen(), frozenOf(_user), dividendsOf(_user), info.users[_user].staketime, info.users[_user].scaledPayout);

	

	    

	}

	



//======================================ACTION CALLS=========================================//	

	

	function _stake(uint256 _amount) internal {

	    

	    require(stakingEnabled, "Staking not yet initialized");

	    

		require(IERC20(UniswapV2).balanceOf(msg.sender) >= _amount, "Insufficient SWAP AFT balance");

		require(frozenOf(msg.sender) + _amount >= MINIMUM_STAKE, "Your amount is lower than the minimum amount allowed to stake");

		require(IERC20(UniswapV2).allowance(msg.sender, address(this)) >= _amount, "Not enough allowance given to contract yet to spend by user");

		

		info.users[msg.sender].staketime = now;

		info.totalFrozen += _amount;

		info.users[msg.sender].frozen += _amount;

		

		info.users[msg.sender].scaledPayout += int256(_amount * info.scaledPayoutPerToken); 

		IERC20(UniswapV2).transferFrom(msg.sender, address(this), _amount);      // Transfer liquidity tokens from the sender to this contract

		

        emit StakeEvent(msg.sender, address(this), _amount);

	}

	

    

    

 

	function _unstake(uint256 _amount) internal {

	    

		require(frozenOf(msg.sender) >= _amount, "You currently do not have up to that amount staked");

		

		info.totalFrozen -= _amount;

		info.users[msg.sender].frozen -= _amount;

		info.users[msg.sender].scaledPayout -= int256(_amount * info.scaledPayoutPerToken);

		

		require(IERC20(UniswapV2).transfer(msg.sender, _amount), "Transaction failed");

        emit UnstakeEvent(address(this), msg.sender, _amount);

        

        TakeDividends();

		

	}

	

	

		

	function TakeDividends() public returns (uint256) {

		

		uint256 _dividends = dividendsOf(msg.sender);

		require(_dividends >= 0, "you do not have any dividend yet");

		info.users[msg.sender].scaledPayout += int256(_dividends * FLOAT_SCALAR);

		require(IERC20(Axiatoken).transfer(msg.sender, _dividends), "Transaction Failed");    // Transfer dividends to msg.sender

		emit RewardEvent(msg.sender, address(this), _dividends);

		

		return _dividends;

	    

		    

	}

	

 

    function scaledToken(uint _amount) external onlyAxiaToken returns(bool){

            

    		info.scaledPayoutPerToken += _amount * FLOAT_SCALAR / info.totalFrozen;

    		infocheck = info.scaledPayoutPerToken;

    		return true;

            

    }

 

        

    function mulDiv (uint x, uint y, uint z) public pure returns (uint) {

          (uint l, uint h) = fullMul (x, y);

          assert (h < z);

          uint mm = mulmod (x, y, z);

          if (mm > l) h -= 1;

          l -= mm;

          uint pow2 = z & -z;

          z /= pow2;

          l /= pow2;

          l += h * ((-pow2) / pow2 + 1);

          uint r = 1;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          r *= 2 - z * r;

          return l * r;

    }

    

     function fullMul (uint x, uint y) private pure returns (uint l, uint h) {

          uint mm = mulmod (x, y, uint (-1));

          l = x * y;

          h = mm - l;

          if (mm < l) h -= 1;

    }

 

    

}


Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

 +  SWAPCONTRACT 
    - [Pub]  #
    - [Pub] tokenConfig #
       - modifiers: onlyCreator
    - [Pub] swapStatus #
       - modifiers: onlyCreator
    - [Ext] swap #
    - [Ext] swapAll #
    - [Pub] GetLeftOverV1 #
       - modifiers: onlyCreator
    - [Pub] GetLeftOverV2 #
       - modifiers: onlyCreator
	   
							

Source Code

Click here to download the source code as a .sol file.





pragma solidity 0.6.4;





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 {

    /**

     * @dev Returns the addition of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `+` operator.

     *

     * Requirements:

     *

     * - Addition cannot overflow.

     */

    function add(uint256 a, uint256 b) internal pure returns (uint256) {

        uint256 c = a + b;

        require(c >= a, "SafeMath: addition overflow");



        return c;

    }

 

    /**

     * @dev Returns the subtraction of two unsigned integers, reverting on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {

        return sub(a, b, "SafeMath: subtraction overflow");

    }



    /**

     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on

     * overflow (when the result is negative).

     *

     * Counterpart to Solidity's `-` operator.

     *

     * Requirements:

     *

     * - Subtraction cannot overflow.

     */

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b <= a, errorMessage);

        uint256 c = a - b;



        return c;

    }



    /**

     * @dev Returns the multiplication of two unsigned integers, reverting on

     * overflow.

     *

     * Counterpart to Solidity's `*` operator.

     *

     * Requirements:

     *

     * - Multiplication cannot overflow.

     */

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the

        // benefit is lost if 'b' is also tested.

        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522

        if (a == 0) {

            return 0;

        }



        uint256 c = a * b;

        require(c / a == b, "SafeMath: multiplication overflow");



        return c;

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b) internal pure returns (uint256) {

        return div(a, b, "SafeMath: division by zero");

    }



    /**

     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on

     * division by zero. The result is rounded towards zero.

     *

     * Counterpart to Solidity's `/` operator. Note: this function uses a

     * `revert` opcode (which leaves remaining gas untouched) while Solidity

     * uses an invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b > 0, errorMessage);

        uint256 c = a / b;

        // assert(a == b * c + a % b); // There is no case in which this doesn't hold



        return c;

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {

        return mod(a, b, "SafeMath: modulo by zero");

    }



    /**

     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

     * Reverts with custom message when dividing by zero.

     *

     * Counterpart to Solidity's `%` operator. This function uses a `revert`

     * opcode (which leaves remaining gas untouched) while Solidity uses an

     * invalid opcode to revert (consuming all remaining gas).

     *

     * Requirements:

     *

     * - The divisor cannot be zero.

     */

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

        require(b != 0, errorMessage);

        return a % b;

    }

}







contract SWAPCONTRACT{

    

   using SafeMath for uint256;

    

   address public V1;

   address public V2;

   bool swapEnabled;

   address administrator;

   

   constructor() public {

       

	    administrator = msg.sender;

		swapEnabled = false;

		

	}

	

//======================================ADMINSTRATION=========================================//



	modifier onlyCreator() {

        require(msg.sender == administrator, "Ownable: caller is not the administrator");

        _;

    }

   

   function tokenConfig(address _v1Address, address _v2Address) public onlyCreator returns(bool){

       require(_v1Address != address(0) && _v2Address != address(0), "Invalid address has been set");

       V1 = _v1Address;

       V2 = _v2Address;

       return true;

       

   }

   

   

   function swapStatus(bool _status) public onlyCreator returns(bool){

       require(V1 != address(0) && V2 != address(0), "V1 and V2 addresses are not set up yet");

       swapEnabled = _status;

   }

   

   

   

   

   function swap(uint256 _amount) external returns(bool){

       

       require(swapEnabled, "Swap not yet initialized");

       require(_amount > 0, "Invalid amount to swap");

       require(IERC20(V1).balanceOf(msg.sender) >= _amount, "You cannot swap more than what you hold");

       require(IERC20(V2).balanceOf(address(this)) >= _amount, "Insufficient amount of tokens to be swapped for");

       require(IERC20(V1).allowance(msg.sender, address(this)) >= _amount, "Insufficient allowance given to contract");

       

       require(IERC20(V1).transferFrom(msg.sender, address(this), _amount), "Transaction failed on root");

       require(IERC20(V2).transfer(msg.sender, _amount), "Transaction failed from base");

       

       return true;

       

   }

   

   function swapAll() external returns(bool){

       

       require(swapEnabled, "Swap not yet initialized");

       uint v1userbalance = IERC20(V1).balanceOf(msg.sender);

       uint v2contractbalance = IERC20(V2).balanceOf(address(this));

       

       require(v1userbalance > 0, "You cannot swap on zero balance");

       require(v2contractbalance >= v1userbalance, "Insufficient amount of tokens to be swapped for");

       require(IERC20(V1).allowance(msg.sender, address(this)) >= v1userbalance, "Insufficient allowance given to contract");

       

       require(IERC20(V1).transferFrom(msg.sender, address(this), v1userbalance), "Transaction failed on root");

       require(IERC20(V2).transfer(msg.sender, v1userbalance), "Transaction failed from base");

       

       return true;

       

   }

   

   

   function GetLeftOverV1() public onlyCreator returns(bool){

      

      require(administrator != address(0));

      require(administrator != address(this));

      require(V1 != address(0) && V2 != address(0), "V1 address not set up yet");

      uint bal = IERC20(V1).balanceOf(address(this));

      require(IERC20(V1).transfer(administrator, bal), "Transaction failed");

      

  }

  

  function GetLeftOverV2() public onlyCreator returns(bool){

      

      require(administrator != address(0));

      require(administrator != address(this));

      require(V1 != address(0) && V2 != address(0), "V1 address not set up yet");

      uint bal = IERC20(V2).balanceOf(address(this));

      require(IERC20(V2).transfer(administrator, bal), "Transaction failed");

      

  }

   

    

}

Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public

  + [Int] IUniswapV2Pair 
    - [Ext] name
    - [Ext] symbol
    - [Ext] decimals
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transfer #
    - [Ext] transferFrom #
    - [Ext] DOMAIN_SEPARATOR
    - [Ext] PERMIT_TYPEHASH
    - [Ext] nonces
    - [Ext] permit #
    - [Ext] MINIMUM_LIQUIDITY
    - [Ext] factory
    - [Ext] token0
    - [Ext] token1
    - [Ext] getReserves
    - [Ext] price0CumulativeLast
    - [Ext] price1CumulativeLast
    - [Ext] kLast
    - [Ext] mint #
    - [Ext] burn #
    - [Ext] swap #
    - [Ext] skim #
    - [Ext] sync #
    - [Ext] initialize #

 + [Int] IWETH 
    - [Ext] deposit ($)
    - [Ext] transfer #
    - [Ext] withdraw #

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod
    - [Int] min
    - [Int] sqrt

 + [Lib] UniswapV2Library 
    - [Int] sortTokens
    - [Int] pairFor
    - [Int] getReserves
    - [Int] quote
    - [Int] getAmountOut
    - [Int] getAmountIn
    - [Int] getAmountsOut
    - [Int] getAmountsIn

 +  UniswapZAP 
    - [Pub] initUniswapZAP #
    - [Ext]  ($)
    - [Ext]  ($)
    - [Pub] addLiquidityETHOnly ($)
    - [Int] _addLiquidity #
    - [Pub] getLPTokenPerEthUnit
    - [Int] getPairReserves
							

Source Code

Click here to download the source code as a .sol file.





pragma solidity ^0.6.12;





interface IUniswapV2Pair {

    event Approval(address indexed owner, address indexed spender, uint value);

    event Transfer(address indexed from, address indexed to, uint value);



    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint);

    function balanceOf(address owner) external view returns (uint);

    function allowance(address owner, address spender) external view returns (uint);



    function approve(address spender, uint value) external returns (bool);

    function transfer(address to, uint value) external returns (bool);

    function transferFrom(address from, address to, uint value) external returns (bool);



    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint);



    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;



    event Mint(address indexed sender, uint amount0, uint amount1);

    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);

    event Swap(

        address indexed sender,

        uint amount0In,

        uint amount1In,

        uint amount0Out,

        uint amount1Out,

        address indexed to

    );

    event Sync(uint112 reserve0, uint112 reserve1);



    function MINIMUM_LIQUIDITY() external pure returns (uint);

    function factory() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);

    function price0CumulativeLast() external view returns (uint);

    function price1CumulativeLast() external view returns (uint);

    function kLast() external view returns (uint);



    function mint(address to) external returns (uint liquidity);

    function burn(address to) external returns (uint amount0, uint amount1);

    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;

    function skim(address to) external;

    function sync() external;



    function initialize(address, address) external;

}



interface IWETH {

    function deposit() external payable;

    function transfer(address to, uint value) external returns (bool);

    function withdraw(uint) external;

}



/**

 * @dev Interface of the ERC20 standard as defined in the EIP.

 */

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);

}







/**

 * @dev Wrappers over Solidity's arithmetic operations with added overflow

 * checks.

 */

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) {

        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the

        // benefit is lost if 'b' is also tested.

        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522

        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;

        // assert(a == b * c + a % b); // There is no case in which this doesn't hold



        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 min(uint x, uint y) internal pure returns (uint z) {

        z = x < y ? x : y;

    }



    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)

    function sqrt(uint y) internal pure returns (uint z) {

        if (y > 3) {

            z = y;

            uint x = y / 2 + 1;

            while (x < z) {

                z = x;

                x = (y / x + x) / 2;

            }

        } else if (y != 0) {

            z = 1;

        }

    }

}









library UniswapV2Library {

    using SafeMath for uint;



    // returns sorted token addresses, used to handle return values from pairs sorted in this order

    function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {

        require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES');

        (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);

        require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS');

    }



    // calculates the CREATE2 address for a pair without making any external calls

    function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {

        (address token0, address token1) = sortTokens(tokenA, tokenB);

        pair = address(uint(keccak256(abi.encodePacked(

                hex'ff',

                factory,

                keccak256(abi.encodePacked(token0, token1)),

                hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // init code hash

            ))));

    }



    // fetches and sorts the reserves for a pair

    function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {

        (address token0,) = sortTokens(tokenA, tokenB);

        (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves();

        (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);

    }



    // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset

    function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {

        require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT');

        require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');

        amountB = amountA.mul(reserveB) / reserveA;

    }



    // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset

    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {

        require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');

        require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');

        uint amountInWithFee = amountIn.mul(997);

        uint numerator = amountInWithFee.mul(reserveOut);

        uint denominator = reserveIn.mul(1000).add(amountInWithFee);

        amountOut = numerator / denominator;

    }



    // given an output amount of an asset and pair reserves, returns a required input amount of the other asset

    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {

        require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');

        require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');

        uint numerator = reserveIn.mul(amountOut).mul(1000);

        uint denominator = reserveOut.sub(amountOut).mul(997);

        amountIn = (numerator / denominator).add(1);

    }



    // performs chained getAmountOut calculations on any number of pairs

    function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) {

        require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');

        amounts = new uint[](path.length);

        amounts[0] = amountIn;

        for (uint i; i < path.length - 1; i++) {

            (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]);

            amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);

        }

    }



    // performs chained getAmountIn calculations on any number of pairs

    function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) {

        require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');

        amounts = new uint[](path.length);

        amounts[amounts.length - 1] = amountOut;

        for (uint i = path.length - 1; i > 0; i--) {

            (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]);

            amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);

        }

    }

}



contract UniswapZAP {



    using SafeMath for uint256;



    address public _token;

    address public _tokenWETHPair;

    IWETH public _WETH;

    bool private initialized;



    function initUniswapZAP(address token, address WETH, address tokenWethPair) public  {

        require(!initialized);

        _token = token;

        _WETH = IWETH(WETH);

        _tokenWETHPair = tokenWethPair;

        initialized = true;

    }



    fallback() external payable {

        if(msg.sender != address(_WETH)){

             addLiquidityETHOnly(msg.sender);

        }

    }

    receive() external payable {

        if(msg.sender != address(_WETH)){

             addLiquidityETHOnly(msg.sender);

        }

    }





    function addLiquidityETHOnly(address payable to) public payable {

        require(to != address(0), "Invalid address");



        uint256 buyAmount = msg.value.div(2);

        require(buyAmount > 0, "Insufficient ETH amount");

        _WETH.deposit{value : msg.value}();



        (uint256 reserveWeth, uint256 reserveTokens) = getPairReserves();

        uint256 outTokens = UniswapV2Library.getAmountOut(buyAmount, reserveWeth, reserveTokens);

        

        _WETH.transfer(_tokenWETHPair, buyAmount);



        (address token0, address token1) = UniswapV2Library.sortTokens(address(_WETH), _token);

        IUniswapV2Pair(_tokenWETHPair).swap(_token == token0 ? outTokens : 0, _token == token1 ? outTokens : 0, address(this), "");



        _addLiquidity(outTokens, buyAmount, to);



    }



    function _addLiquidity(uint256 tokenAmount, uint256 wethAmount, address payable to) internal {

        (uint256 wethReserve, uint256 tokenReserve) = getPairReserves();



        uint256 optimalTokenAmount = UniswapV2Library.quote(wethAmount, wethReserve, tokenReserve);



        uint256 optimalWETHAmount;

        if (optimalTokenAmount > tokenAmount) {

            optimalWETHAmount = UniswapV2Library.quote(tokenAmount, tokenReserve, wethReserve);

            optimalTokenAmount = tokenAmount;

        }

        else

            optimalWETHAmount = wethAmount;



        assert(_WETH.transfer(_tokenWETHPair, optimalWETHAmount));

        assert(IERC20(_token).transfer(_tokenWETHPair, optimalTokenAmount));



        IUniswapV2Pair(_tokenWETHPair).mint(to);

        

        //refund dust

        if (tokenAmount > optimalTokenAmount)

            IERC20(_token).transfer(to, tokenAmount.sub(optimalTokenAmount));



        if (wethAmount > optimalWETHAmount) {

            uint256 withdrawAmount = wethAmount.sub(optimalWETHAmount);

            _WETH.withdraw(withdrawAmount);

            to.transfer(withdrawAmount);

        }

    }





    function getLPTokenPerEthUnit(uint ethAmt) public view  returns (uint liquidity){

        (uint256 reserveWeth, uint256 reserveTokens) = getPairReserves();

        uint256 outTokens = UniswapV2Library.getAmountOut(ethAmt.div(2), reserveWeth, reserveTokens);

        uint _totalSupply =  IUniswapV2Pair(_tokenWETHPair).totalSupply();



        (address token0, ) = UniswapV2Library.sortTokens(address(_WETH), _token);

        (uint256 amount0, uint256 amount1) = token0 == _token ? (outTokens, ethAmt.div(2)) : (ethAmt.div(2), outTokens);

        (uint256 _reserve0, uint256 _reserve1) = token0 == _token ? (reserveTokens, reserveWeth) : (reserveWeth, reserveTokens);

        liquidity = SafeMath.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);

    }



    function getPairReserves() internal view returns (uint256 wethReserves, uint256 tokenReserves) {

        (address token0,) = UniswapV2Library.sortTokens(address(_WETH), _token);

        (uint256 reserve0, uint reserve1,) = IUniswapV2Pair(_tokenWETHPair).getReserves();

        (wethReserves, tokenReserves) = token0 == _token ? (reserve1, reserve0) : (reserve0, reserve1);

    }



}