ETH Price: $2,602.14 (-4.45%)

Contract Diff Checker

Contract Name:
DextokenFactoryCollateral

Contract Source Code:

pragma solidity 0.5.17;


/**
 * @title Address
 * @dev Check if the address is a contract using eip-1052
 */
library Address {
    function isContract(address account) internal view returns (bool) {
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != 0x0 && codehash != accountHash);
    }
}

pragma solidity 0.5.17;


contract Context {
    constructor () internal { }

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }
}

// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity 0.5.17;

import "./Math.sol";
import "./SafeMath.sol";
import "./DextokenPoolCollateral.sol";


contract DextokenFactoryCollateral {
    using SafeMath for uint;

    event PoolCreated(address indexed token0, address indexed pair, address indexed creator, uint);

    address public owner;
    address public feePool;
    address public collateral;

    mapping(address => mapping(address => address)) private _allPools;
    address [] public allPoolsAddress;

    constructor(address token1) public {
        owner = msg.sender;
        feePool = address(0);
        collateral = token1;
    }

    function createPool(address token0, uint Ct, uint Pt) external returns (address pool) {
        require(token0 != address(0), 'createPool: zero address');
        require(feePool != address(0), 'createPool: feePool not set');
        require(_allPools[token0][msg.sender] == address(0), 'createPool: user pool exists');
        bytes memory bytecode = type(DextokenPoolCollateral).creationCode;
        bytes32 salt = keccak256(abi.encodePacked(token0, collateral, msg.sender));
        /// precompute the address where a contract will be deployed
        assembly {
            pool := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
        IDextokenPool(pool).initialize(token0, collateral, Ct, Pt);
        _allPools[token0][msg.sender] = pool;
        allPoolsAddress.push(pool);
        emit PoolCreated(token0, pool, msg.sender, allPoolsAddress.length);
        return pool;
    }

    function getFeePool() external view returns (address) {
        return feePool;
    }

    function setFeePool(address _feePool) external {
        require(msg.sender == owner, "setFeePool: Forbidden");
        feePool = _feePool;
    }

    function getAllPools() external view returns (address [] memory) {
        return allPoolsAddress;
    }   
}   

// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity 0.5.17;

import "./Math.sol";
import "./SafeMath.sol";
import "./SafeERC20.sol";
import "./ReentrancyGuard.sol";
import "./IDextokenPool.sol";
import "./IDextokenFactory.sol";
import "./LPToken.sol";


contract DextokenPoolCollateral is LPToken, IDextokenPool, ReentrancyGuard {
    using SafeERC20 for IERC20;
    using SafeMath for uint;

    /// AMM fee
    uint public constant FEE_BASE      = 100; // 1%
    uint public constant FEE_FACTOR    = 3;

    IDextokenFactory public factory;

    /// The collateral token
    IERC20 public COLLATERAL;

    /// Pooling
    uint public totalLiquidity;
    IERC20 public token0;

    /// Speculative AMM
    struct AMM {
        uint Ct;
        uint Pt;
        uint Nt;
        uint lastUpdateTime;
    }

    /// AMM states
    AMM private _AMM;

    modifier updatePriceTick() {   
        _;
        /// step the price tick (t+1)
        _AMM.lastUpdateTime = _lastPriceTickApplicable();   
    }

    constructor() public {
        factory = IDextokenFactory(msg.sender);
        _AMM.lastUpdateTime = 0;
        totalLiquidity = 0;
    }

    function initialize(address _token0, address _token1, uint _Ct, uint _Pt) 
        external 
    {
        require(msg.sender == address(factory), 'initialize: Forbidden');

        token0 = IERC20(_token0); 
        require(_Ct <= token0.totalSupply(), "initialize: Invalid _Ct");     
        
        /// snapshot of the pooled token
        _AMM.Ct = _Ct;
        _AMM.Pt = _Pt;
        _AMM.Nt = _AMM.Pt.mul(_AMM.Ct).div(1e18);

        /// The collateral token
        COLLATERAL = IERC20(_token1);  
    }

    function deposit(uint amount) 
        external 
        nonReentrant
        updatePriceTick()
    {
        require(amount > 0, "deposit: invalid amount");
        uint _totalBalance = getPoolBalance();
        address _token0 = address(token0);
        uint _Ct = _AMM.Ct.add(amount);
        uint _Nt = _AMM.Nt;

        // liquidity at price tick (t)
        uint spotPrice = getSpotPrice(_Ct, _Nt);
        uint liquidity = spotPrice.mul(amount);
        require(liquidity > 0, "deposit: invalid user liquidity");

        _totalBalance = _totalBalance.add(amount);
        uint _totalLiquidity = totalLiquidity.add(liquidity);

        // mint liquidity tokens
        uint mintedTokens = _calcLiquidityToken(_totalLiquidity, _totalBalance, liquidity);

        /// calculate the virtual collateral tokens at price tick (t)
        uint _Mb = COLLATERAL.balanceOf(address(this)).mul(mintedTokens).div(totalSupply().add(mintedTokens));

        // move price tick to (t+1) 
        _AMM.Ct = _Ct;
        _AMM.Nt = _Nt.add(_Mb);
        totalLiquidity = _totalLiquidity;

        // mint liquidity token at price tick (t+1)
        _mintLiquidityToken(msg.sender, mintedTokens);
        _tokenSafeTransferFrom(_token0, msg.sender, address(this), amount);
        emit TokenDeposit(_token0, msg.sender, amount, spotPrice);        
    }

    function withdraw(uint tokens) 
        external 
        nonReentrant
        updatePriceTick()
    {
        require(tokens > 0, "withdraw: invalid tokens");
        require(totalSupply() > 0, "withdraw: insufficient liquidity");
        require(balanceOf(msg.sender) >= tokens, "withdraw: insufficient tokens");
        address _token0 = address(token0);
      
        // liquidity at price tick (t)
        uint amount = liquidityTokenToAmount(tokens);

        /// calculate the collateral token shares
        uint balance = COLLATERAL.balanceOf(address(this));
        uint amountOut = balance.mul(tokens).div(totalSupply());

        /// Ensure the amountOut is not more than the balance in the contract.
        /// Preventing underflow due to very low values of the balance.        
        require(amountOut <= balance, "withdraw: insufficient ETH balance");

        // prepare for price tick (t+1)
        uint _Ct = _AMM.Ct;
        uint _Nt = _AMM.Nt;
        _Ct = _Ct.sub(amount);
        _Nt = _Nt.sub(amountOut);

        // liquidity at price tick (t+1)        
        uint spotPrice = getSpotPrice(_Ct, _Nt);
        totalLiquidity = spotPrice.mul(getPoolBalance().sub(amount));

        _AMM.Ct = _Ct;
        _AMM.Nt = _Nt;

        _tokenSafeTransfer(_token0, msg.sender, amount);
        _tokenSafeTransfer(address(COLLATERAL), msg.sender, amountOut);

        _burnLiquidityToken(msg.sender, tokens);
        emit TokenWithdraw(_token0, msg.sender, amount, spotPrice);
    }

    function swapExactETHForTokens(
        uint amountIn,
        uint minAmountOut,
        uint maxPrice,
        uint deadline
    )
        external 
        nonReentrant
        returns (uint)
    {
        require(COLLATERAL.balanceOf(msg.sender) >= amountIn, "swapExactETHForTokens: Insufficient collateral balance");
        require(deadline > _lastPriceTickApplicable(), "swapExactETHForTokens: Invalid transaction");
        require(amountIn > 0, "swapExactETHForTokens: Invalid amountIn");
        uint spotPrice;
        IERC20 _COLLATERAL = COLLATERAL;

        /// the price tick at (t)
        /// increase the collateral token supply including interests rate        
        {
            spotPrice = getSpotPrice(_AMM.Ct, _AMM.Nt.add(amountIn));
            require(spotPrice <= maxPrice, "swapExactETHForTokens: Invalid price slippage");
        }

        /// check amount out without fees
        uint amountOut = amountIn.mul(1e18).div(spotPrice);
        require(amountOut >= minAmountOut, "swapExactETHForTokens: Invalid amountOut");

        /// split fees and check exact amount out
        uint feeAmountIn = _calcFees(amountIn);
        uint exactAmountIn = amountIn.sub(feeAmountIn);
        uint exactAmountOut = exactAmountIn.mul(1e18).div(spotPrice);

        /// increase the collateral token supply
        _AMM.Nt = _AMM.Nt.add(exactAmountIn);
        spotPrice = getSpotPrice(_AMM.Ct.sub(exactAmountOut), _AMM.Nt);
        totalLiquidity = spotPrice.mul(getPoolBalance().sub(exactAmountOut));

        /// transfer the collateral tokens in
        _tokenSafeTransferFrom(address(_COLLATERAL), msg.sender, address(this), amountIn);
        
        /// transfer fees
        _tokenSafeTransfer(address(_COLLATERAL), factory.getFeePool(), feeAmountIn);

        /// move to the next price tick (t+1)
        _withdrawAndTransfer(msg.sender, exactAmountOut);

        emit SwapExactETHForTokens(address(this), exactAmountOut, amountIn, spotPrice, msg.sender);
        return exactAmountOut;
    } 

    function swapExactTokensForETH(
        uint amountIn,
        uint minAmountOut,
        uint minPrice,
        uint deadline
    )
        external 
        nonReentrant
        returns (uint)
    {
        require(token0.balanceOf(msg.sender) >= amountIn, "swapExactTokensForETH: Insufficient user balance");    
        require(deadline > _lastPriceTickApplicable(), "swapExactTokensForETH: Invalid order");
        require(amountIn > 0, "swapExactTokensForETH: Invalid amountIn");
        uint _Nt = _AMM.Nt;
        IERC20 _COLLATERAL = COLLATERAL;

        /// add liquidity at the price tick (t)
        uint spotPrice = getSpotPrice(_AMM.Ct.add(amountIn), _Nt);
        require(spotPrice >= minPrice, "swapExactTokensForETH: Invalid price slippage");

        /// user receives
        uint amountOut = spotPrice.mul(amountIn).div(1e18);
        require(_COLLATERAL.balanceOf(address(this)) >= amountOut, "swapExactTokensForETH: Insufficient collateral liquidity");
        require(amountOut >= minAmountOut, "swapExactTokensForETH: Invalid amountOut");

        /// split fees
        uint feeAmountOut = _calcFees(amountOut);
        uint exactAmountOut = amountOut.sub(feeAmountOut);

        /// decrease the collateral token, and add liquidity 
        /// providers' fee shares back to the pool
        _AMM.Nt = _Nt.sub(exactAmountOut);

        totalLiquidity = spotPrice.mul(getPoolBalance().add(amountIn));

        /// move the next price tick (t+1)
        _depositAndTransfer(msg.sender, amountIn);

        /// transfer the collateral token out
        _tokenSafeTransfer(address(_COLLATERAL), msg.sender, exactAmountOut);

        emit SwapExactTokensForETH(address(this), exactAmountOut, amountIn, spotPrice, msg.sender);
        return exactAmountOut;
    }

    function getLastUpdateTime() external view returns (uint) {
        return _AMM.lastUpdateTime;
    }  

    function getCirculatingSupply() external view returns (uint) {
        return _AMM.Ct;
    }    

    function getUserbase() external view returns (uint) {
        return _AMM.Nt;
    }

    function getToken() external view returns (address) {
        return address(token0);
    }

    function getTotalLiquidity() external view returns (uint) {
        return totalLiquidity.div(1e18);
    }  

    function liquidityOf(address account) external view returns (uint) {
        return balanceOf(account);
    }

    function liquiditySharesOf(address account) external view returns (uint) {
        uint userTokens = balanceOf(account);
        if (userTokens == 0) {
            return 0;
        }
        return totalSupply()
            .mul(1e18)
            .div(userTokens);
    }  

    function mean() public view returns (uint) {
        return _AMM.Nt
            .mul(_AMM.Pt);
    }

    function getPoolBalance() public view returns (uint) {
        return token0.balanceOf(address(this));
    }

    function getPrice() public view returns (uint) {
        return _AMM.Nt.mul(1e18).div(_AMM.Ct);
    }   

    function getSpotPrice(uint _Ct, uint _Nt) public pure returns (uint) {
        return _Nt.mul(1e18).div(_Ct);
    }

    function liquidityTokenToAmount(uint token) public view returns (uint) {
        if (totalSupply() == 0) {
            return 0;
        }        
        return getPoolBalance()
            .mul(token)
            .div(totalSupply());
    }  

    function liquidityFromAmount(uint amount) public view returns (uint) {
        return getPrice().mul(amount); 
    }

    function _depositAndTransfer(address account, uint amount) 
        internal
        updatePriceTick()
    {
        _AMM.Ct = _AMM.Ct.add(amount);    
        _tokenSafeTransferFrom(address(token0), account, address(this), amount);
    }

    function _withdrawAndTransfer(address account, uint amount) 
        internal
        updatePriceTick()
    {
        _AMM.Ct = _AMM.Ct.sub(amount);    
        _tokenSafeTransfer(address(token0), account, amount);
    }
    
    function _lastPriceTickApplicable() internal view returns (uint) {
        return Math.max(block.timestamp, _AMM.lastUpdateTime);
    }

    function _mintLiquidityToken(address to, uint amount) internal {
        _mint(address(this), amount);
        _transfer(address(this), to, amount);
    }

    function _burnLiquidityToken(address from, uint amount) internal {
        _transfer(from, address(this), amount);
        _burn(address(this), amount);
    } 

    function _calcFees(uint amount) internal pure returns (uint) {
        return amount.mul(FEE_FACTOR).div(FEE_BASE);
    }

    function _calcLiquidityToken(
        uint _totalLiquidity, 
        uint _totalBalance, 
        uint _liquidity
    ) 
        internal 
        pure 
        returns (uint) 
    {
        if (_totalLiquidity == 0) {
            return 0;
        }    
        return _totalBalance
            .mul(_liquidity)
            .div(_totalLiquidity);
    }

    function _tokenSafeTransfer(
        address token,
        address to,
        uint amount
    ) internal {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, amount));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "_tokenSafeTransfer failed");
    }

    function _tokenSafeTransferFrom(
        address token,
        address from,
        address to,
        uint amount
    ) internal {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "_tokenSafeTransferFrom failed");
    }                    
}

pragma solidity 0.5.17;

import "./Context.sol";
import "./IERC20.sol";
import "./SafeMath.sol";


/**
 * @dev The ERC20 standard implementation.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint;

    mapping (address => uint) private _balances;
    mapping (address => mapping (address => uint)) private _allowances;

    uint private _totalSupply;

    function totalSupply() public view returns (uint) {
        return _totalSupply;
    }

    function balanceOf(address account) public view returns (uint) {
        return _balances[account];
    }

    function transfer(address recipient, uint amount) public returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view returns (uint) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint amount) public returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(address sender, address recipient, uint amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    function increaseAllowance(address spender, uint addedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    function decreaseAllowance(address spender, uint subtractedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    function _transfer(address sender, address recipient, uint amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    function _mint(address account, uint amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    function _burn(address account, uint amount) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    function _approve(address owner, address spender, uint amount) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }
}

pragma solidity 0.5.17;

import "./IERC20.sol";


contract ERC20Detailed is IERC20 {
    string private _name;
    string private _symbol;
    uint8 private _decimals;

    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view returns (uint8) {
        return _decimals;
    }
}

pragma solidity 0.5.17;


interface IDextokenExchange {
    event SwapExactAmountOut(
        address indexed poolIn, 
        uint amountSwapIn, 
        address indexed poolOut, 
        uint exactAmountOut,
        address indexed to
    );

    event SwapExactAmountIn(
        address indexed poolIn, 
        uint amountSwapIn, 
        address indexed poolOut, 
        uint exactAmountOut,
        address indexed to
    );
    
	function swapMaxAmountOut(
        address poolIn,
        address poolOut, 
        uint maxAmountOut,
        uint deadline
    ) external;

    function swapExactAmountIn(
        address poolIn,
        address poolOut, 
        uint exactAmountIn,
        uint deadline
    ) external;  
}

pragma solidity 0.5.17;


interface IDextokenFactory {
    function getFeePool() external view returns (address);
}

pragma solidity 0.5.17;


interface IDextokenPool {
    event TokenDeposit(
        address indexed token, 
        address indexed account, 
        uint amount,
        uint spotPrice
    );

    event TokenWithdraw(
        address indexed token, 
        address indexed account, 
        uint amount,
        uint spotPrice
    );

    event SwapExactETHForTokens(
        address indexed poolOut, 
        uint amountOut, 
        uint amountIn,
        uint spotPrice,
        address indexed account
    );

    event SwapExactTokensForETH(
        address indexed poolOut, 
        uint amountOut, 
        uint amountIn, 
        uint spotPrice,
        address indexed account
    );

    /// Speculative AMM
    function initialize(address _token0, address _token1, uint _Ct, uint _Pt) external;
    function mean() external view returns (uint);
    function getLastUpdateTime() external view returns (uint);
    function getCirculatingSupply() external view returns (uint);
    function getUserbase() external view returns (uint);
    function getPrice() external view returns (uint);
    function getSpotPrice(uint _Ct, uint _Nt) external pure returns (uint);
	function getToken() external view returns (address);

    /// Pool Management
    function getPoolBalance() external view returns (uint);    
    function getTotalLiquidity() external view returns (uint);
    function liquidityOf(address account) external view returns (uint);
    function liquiditySharesOf(address account) external view returns (uint);
    function liquidityTokenToAmount(uint token) external view returns (uint);
    function liquidityFromAmount(uint amount) external view returns (uint);
    function deposit(uint amount) external;
    function withdraw(uint tokens) external;

    /// Trading
    function swapExactETHForTokens(
        uint amountIn,
        uint minAmountOut,
        uint maxPrice,
        uint deadline
    ) external returns (uint);

    function swapExactTokensForETH(
        uint amountIn,
        uint minAmountOut,
        uint minPrice,
        uint deadline
    ) external returns (uint);
}

pragma solidity 0.5.17;


interface IERC20 {
    function totalSupply() external view returns (uint);
    function balanceOf(address account) external view returns (uint);
    function transfer(address recipient, uint amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint);
    function approve(address spender, uint amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint amount) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}

pragma solidity 0.5.17;


interface IWETH {
    function name() external view returns (string memory);

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

    function decimals() external view returns (uint8);

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

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

    function deposit() external payable;

    function withdraw(uint wad) external;

    function totalSupply() external view returns (uint);

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

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

    function transferFrom(address src, address dst, uint wad) external returns (bool);
}

// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity 0.5.17;

import "./ERC20.sol";


contract LPToken is ERC20 {
    string public constant name     = "DEXG Liquidity Pool";
    string public constant symbol   = "DEXG-LP";
    uint8  public constant decimals = 18;
}

pragma solidity ^0.5.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

pragma solidity 0.5.17;

contract Migrations {
  address public owner;
  uint public last_completed_migration;

  constructor() public {
    owner = msg.sender;
  }

  modifier restricted() {
    if (msg.sender == owner) _;
  }

  function setCompleted(uint completed) public restricted {
    last_completed_migration = completed;
  }
}

pragma solidity ^0.5.17;

contract Ownable {
    address public owner;
    address public newOwner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() public {
        owner = msg.sender;
        newOwner = address(0);
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier onlyNewOwner() {
        require(msg.sender != address(0));
        require(msg.sender == newOwner);
        _;
    }
    
    function isOwner(address account) public view returns (bool) {
        if(account == owner) {
            return true;
        }
        else {
            return false;
        }
    }

    function transferOwnership(address _newOwner) public onlyOwner {
        require(_newOwner != address(0));
        newOwner = _newOwner;
    }

    function acceptOwnership() public onlyNewOwner {
        emit OwnershipTransferred(owner, newOwner);        
        owner = newOwner;
        newOwner = address(0);
    }
}

pragma solidity ^0.5.17;

import "./Owned.sol";


contract Pausable is Ownable {
    event Paused(address account);
    event Unpaused(address account);

    bool private _paused;

    constructor () public {
        _paused = false;
    }    

    modifier whenNotPaused() {
        require(!_paused);
        _;
    }

    modifier whenPaused() {
        require(_paused);
        _;
    }

    function paused() public view returns (bool) {
        return _paused;
    }

    function pause() public onlyOwner whenNotPaused {
        _paused = true;
        emit Paused(msg.sender);
    }

    function unpause() public onlyOwner whenPaused {
        _paused = false;
        emit Unpaused(msg.sender);
    }
}

pragma solidity ^0.5.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier
 * available, which can be aplied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 */
contract ReentrancyGuard {
    /// @dev counter to allow mutex lock with only one SSTORE operation
    uint256 private _guardCounter;

    constructor () internal {
        // The counter starts at one to prevent changing it from zero to a non-zero
        // value, which is a more expensive operation.
        _guardCounter = 1;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _guardCounter += 1;
        uint256 localCounter = _guardCounter;
        _;
        require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
    }
}

pragma solidity ^0.5.0;

import "./IERC20.sol";
import "./SafeMath.sol";
import "./Address.sol";


library SafeERC20 {
    using SafeMath for uint;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function safeApprove(IERC20 token, address spender, uint value) internal {
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

pragma solidity 0.5.17;


library SafeMath {
    function add(uint a, uint b) internal pure returns (uint) {
        uint c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }
    function sub(uint a, uint b) internal pure returns (uint) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }
    function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) {
        require(b <= a, errorMessage);
        uint c = a - b;

        return c;
    }
    function mul(uint a, uint b) internal pure returns (uint) {
        if (a == 0) {
            return 0;
        }

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

        return c;
    }
    function div(uint a, uint b) internal pure returns (uint) {
        return div(a, b, "SafeMath: division by zero");
    }
    function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint c = a / b;

        return c;
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):