Deus.finance - Smart Contract Audit Report

Summary

Combine.finance Audit Report Deus.finance intends to let you trade real-world assets and derivatives, like stocks and commodities, directly on the Ethereum blockchain. The platform's "mirrored" assets are 1:1 pegged with its real-world equivalent and can be moved anywhere as an ERC20 token. Deus makes trading stocks on Uniswap and other decentralized exchanges a reality. The project is currently in beta.

For this audit, we analyzed Deus's two token contracts (DEUS - Governance; DEA - Stablecoin), and the platform's Automated Market Maker & Staking interfaces. Note that we have not completed a full audit of Deus's upcoming rStocks platform or the Sands of Time vault.

Notable security features of the contracts:
  • Users can successfully stake a series of single assets or Uniswap LP tokens to earn interest/fees as well as Deus's native stablecoin, DEA.
  • DEUS and DEA tokens minting ability has been granted to the StaticPriceSale contract to distribute tokens. The minterRoleAdmin control (which can enable other addresses to mint) has been transferred to the burn address (0x00000....)
  • Ownership - Some functions are protected and can only be called by the contract owner. Ownership of the contracts has been transfered to the platform's DAO contract.
  • Utilization of SafeMath (or similarily safe functions) across all contracts to prevent overflows.
Audit Findings Summary:
  • Currently, the project is in beta. Deus's stablecoin, DEA, has yet to be proven - the project intends to peg it's value to $1 USD in early 2021.
  • No security issues from outside attackers were identified.
  • Date: November 19th, 2020

We ran over 400,000 transactions interacting with this suite of contracts on a test blockchain to determine these results.
Date: November 19th, 2020
Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesGovernance functions rely upon the block.number envornmental variable.
The risk associated with this is extremley low.
Warning
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 AssertionN/APASS
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

 +  DEUSToken (ERC20, AccessControl)
    - [Pub]  #
       - modifiers: ERC20
    - [Pub] mint #
    - [Pub] burn #
    - [Pub] setCurrentPointIndex #

							

Source Code

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


//Be name khoda

//SPDX-License-Identifier: MIT

pragma solidity ^0.6.12;

import "support/AccessControl.sol";
import "support/ERC20.sol";

contract DEUSToken is ERC20, AccessControl{

	uint256 public currentPointIndex = 0;

	bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
	bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
	bytes32 public constant CURRENT_POINT_INDEX_SETTER_ROLE = keccak256("CURRENT_POINT_INDEX_SETTER_ROLE");

	constructor() public ERC20("DEUS", "DEUS") {
		_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
	}

	function mint(address to, uint256 amount) public {
        // Check that the calling account has the minter role
        require(hasRole(MINTER_ROLE, msg.sender), "Caller is not a minter");
        _mint(to, amount);
    }

	function burn(address from, uint256 amount) public {
        require(hasRole(BURNER_ROLE, msg.sender), "Caller is not a burner");
        _burn(from, amount);
    }

	function setCurrentPointIndex(uint256 _currentPointIndex) public {
		require(hasRole(CURRENT_POINT_INDEX_SETTER_ROLE, msg.sender), "Caller is not a currentPointIndex setter");
		currentPointIndex = _currentPointIndex;
	}

}
//Dar panah khoda

Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



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

 +  DEAToken (ERC20, AccessControl)
    - [Pub]  #
       - modifiers: ERC20
    - [Pub] mint #
    - [Pub] burn #
    - [Pub] rebase #
    - [Pub] totalSupply
    - [Pub] balanceOf
    - [Pub] allowance
    - [Pub] approve #
    - [Pub] increaseAllowance #
    - [Pub] decreaseAllowance #
    - [Pub] transferFrom #
    - [Pub] transfer #
    - [Int] _beforeTokenTransfer #

							

Source Code

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



//Be name
//si deus si dea

pragma solidity ^0.6.12;

import "support/AccessControl.sol";
import "./ERC20.sol";

contract DEAToken is ERC20, AccessControl{

    using SafeMath for uint256;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
    bytes32 public constant REBASER_ROLE = keccak256("REBASER_ROLE");

    uint256 public rebaseMultiplier = 1e18;
    uint256 public scale = 1e18;

    event Rebase(uint256 oldCoefficient, uint256 newCoefficient);

    constructor() public ERC20("DEA", "DEA") {
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _mint(msg.sender, 166670e18);
    }

    function mint(address to, uint256 amount) public {
        require(hasRole(MINTER_ROLE, msg.sender), "Caller is not a minter");
        _mint(to, amount.mul(scale).div(rebaseMultiplier));
    }

    function burn(address from, uint256 amount) public {
        require(hasRole(BURNER_ROLE, msg.sender), "Caller is not a burner");
        _burn(from, amount.mul(scale).div(rebaseMultiplier));
    }

    function rebase(uint256 _rebaseMultiplier) public {
        require(hasRole(REBASER_ROLE, msg.sender), "Caller is not a rebaser");
        emit Rebase(rebaseMultiplier, _rebaseMultiplier);
        rebaseMultiplier = _rebaseMultiplier;
    }    function totalSupply() public view override returns (uint256){
        return super.totalSupply().mul(rebaseMultiplier).div(scale);
    }
    function balanceOf(address account) public view override returns (uint256){
        return super.balanceOf(account).mul(rebaseMultiplier).div(scale);
    }    function allowance(address owner, address spender) public view override returns (uint256){
        return super.allowance(owner, spender);
    }
    function approve(address spender, uint256 amount) public override returns (bool){
        return super.approve(spender, amount);
    }
    function increaseAllowance(address spender, uint256 addedValue) public override returns (bool) {
        return super.increaseAllowance(spender, addedValue);
    }
    function decreaseAllowance(address spender, uint256 subtractedValue) public override returns (bool) {
        return super.decreaseAllowance(spender, subtractedValue);
    }

    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
        _transfer(sender, recipient, amount.mul(scale).div(rebaseMultiplier));
        _approve(sender, _msgSender(), allowance(sender, _msgSender()).sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    function transfer(address recipient, uint256 amount) public override returns (bool) {
        return super.transfer(recipient, amount.mul(scale).div(rebaseMultiplier));
    }

    function _beforeTokenTransfer(address from, address to, uint256 value) internal virtual override {
        emit Transfer(from, to, value.mul(rebaseMultiplier).div(scale));
    }
}

//Dar panah khoda

Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



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

 + [Int] StakedToken 
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] transferFrom #

 + [Int] RewardToken 
    - [Ext] balanceOf
    - [Ext] transfer #

 +  Staking (Ownable)
    - [Pub]  #
    - [Pub] setWallets #
       - modifiers: onlyOwner
    - [Pub] setShares #
       - modifiers: onlyOwner
    - [Pub] setRewardPerBlock #
       - modifiers: onlyOwner
    - [Pub] update #
    - [Ext] pendingReward
    - [Pub] deposit #
    - [Pub] withdraw #
    - [Pub] withdrawParticleCollector #
    - [Pub] emergencyWithdraw #
    - [Pub] withdrawAllRewardTokens #
       - modifiers: onlyOwner
    - [Pub] withdrawAllStakedtokens #
       - modifiers: onlyOwner

							

Source Code

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



//Be name khoda
//si deus si DEA

pragma solidity 0.6.12;

import "support/SafeMath.sol";
import "support/Ownable.sol";

interface StakedToken {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}

interface RewardToken {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);

}

contract Staking is Ownable {

    struct User {
        uint256 depositAmount;
        uint256 paidReward;
    }

    using SafeMath for uint256;

    mapping (address => User) public users;

    uint256 public rewardTillNowPerToken = 0;
    uint256 public lastUpdatedBlock;
    uint256 public rewardPerBlock;
    uint256 public scale = 1e18;

    uint256 public particleCollector = 0;
    uint256 public daoShare;
    uint256 public earlyFoundersShare;
    address public daoWallet;
    address public earlyFoundersWallet;
    // init with 1 instead of 0 to avoid division by zero
    uint256 public totalStakedToken = 1;

    StakedToken public stakedToken;
    RewardToken public rewardToken;

    event Deposit(address user, uint256 amount);
    event Withdraw(address user, uint256 amount);
    event EmergencyWithdraw(address user, uint256 amount);
    event RewardClaimed(address user, uint256 amount);
    event RewardPerBlockChanged(uint256 oldValue, uint256 newValue);

    constructor (address _stakedToken, address _rewardToken, uint256 _rewardPerBlock, uint256 _daoShare, uint256 _earlyFoundersShare) public {
        stakedToken = StakedToken(_stakedToken);
        rewardToken = RewardToken(_rewardToken);
        rewardPerBlock = _rewardPerBlock;
        daoShare = _daoShare;
        earlyFoundersShare = _earlyFoundersShare;
        lastUpdatedBlock = block.number;
        daoWallet = msg.sender;
        earlyFoundersWallet = msg.sender;
    }

    function setWallets(address _daoWallet, address _earlyFoundersWallet) public onlyOwner {
        daoWallet = _daoWallet;
        earlyFoundersWallet = _earlyFoundersWallet;
    }

    function setShares(uint256 _daoShare, uint256 _earlyFoundersShare) public onlyOwner {
        withdrawParticleCollector();
        daoShare = _daoShare;
        earlyFoundersShare = _earlyFoundersShare;
    }

    function setRewardPerBlock(uint256 _rewardPerBlock) public onlyOwner {
        update();
        emit RewardPerBlockChanged(rewardPerBlock, _rewardPerBlock);
        rewardPerBlock = _rewardPerBlock;
    }

    // Update reward variables of the pool to be up-to-date.
    function update() public {
        if (block.number <= lastUpdatedBlock) {
            return;
        }
        uint256 rewardAmount = (block.number - lastUpdatedBlock).mul(rewardPerBlock);

        rewardTillNowPerToken = rewardTillNowPerToken.add(rewardAmount.mul(scale).div(totalStakedToken));
        lastUpdatedBlock = block.number;
    }

    // View function to see pending reward on frontend.
    function pendingReward(address _user) external view returns (uint256) {
        User storage user = users[_user];
        uint256 accRewardPerToken = rewardTillNowPerToken;

        if (block.number > lastUpdatedBlock) {
            uint256 rewardAmount = (block.number - lastUpdatedBlock).mul(rewardPerBlock);
            accRewardPerToken = accRewardPerToken.add(rewardAmount.mul(scale).div(totalStakedToken));
        }
        return user.depositAmount.mul(accRewardPerToken).div(scale).sub(user.paidReward);
    }

    function deposit(uint256 amount) public {
        User storage user = users[msg.sender];
        update();

        if (user.depositAmount > 0) {
            uint256 _pendingReward = user.depositAmount.mul(rewardTillNowPerToken).div(scale).sub(user.paidReward);
            rewardToken.transfer(msg.sender, _pendingReward);
            emit RewardClaimed(msg.sender, _pendingReward);
        }

        user.depositAmount = user.depositAmount.add(amount);
        user.paidReward = user.depositAmount.mul(rewardTillNowPerToken).div(scale);

        stakedToken.transferFrom(address(msg.sender), address(this), amount);
        totalStakedToken = totalStakedToken.add(amount);
        emit Deposit(msg.sender, amount);
    }

    function withdraw(uint256 amount) public {
        User storage user = users[msg.sender];
        require(user.depositAmount >= amount, "withdraw amount exceeds deposited amount");
        update();

        uint256 _pendingReward = user.depositAmount.mul(rewardTillNowPerToken).div(scale).sub(user.paidReward);
        rewardToken.transfer(msg.sender, _pendingReward);
        emit RewardClaimed(msg.sender, _pendingReward);

        uint256 particleCollectorShare = _pendingReward.mul(daoShare.add(earlyFoundersShare)).div(scale);
        particleCollector = particleCollector.add(particleCollectorShare);

        if (amount > 0) {
            user.depositAmount = user.depositAmount.sub(amount);
            stakedToken.transfer(address(msg.sender), amount);
            totalStakedToken = totalStakedToken.sub(amount);
            emit Withdraw(msg.sender, amount);
        }

        user.paidReward = user.depositAmount.mul(rewardTillNowPerToken).div(scale);
    }

    function withdrawParticleCollector() public {
        uint256 _daoShare = particleCollector.mul(daoShare).div(daoShare.add(earlyFoundersShare));
        rewardToken.transfer(daoWallet, _daoShare);

        uint256 _earlyFoundersShare = particleCollector.mul(earlyFoundersShare).div(daoShare.add(earlyFoundersShare));
        rewardToken.transfer(earlyFoundersWallet, _earlyFoundersShare);

        particleCollector = 0;
    }

    // Withdraw without caring about rewards. EMERGENCY ONLY.
    function emergencyWithdraw() public {
        User storage user = users[msg.sender];

        totalStakedToken = totalStakedToken.sub(user.depositAmount);
        stakedToken.transfer(msg.sender, user.depositAmount);

        emit EmergencyWithdraw(msg.sender, user.depositAmount);

        user.depositAmount = 0;
        user.paidReward = 0;
    }    // Add temporary withdrawal functionality for owner(DAO) to transfer all tokens to a safe place.
    // Contract ownership will transfer to address(0x) after full auditing of codes.
    function withdrawAllRewardTokens(address to) public onlyOwner {
        uint256 totalRewardTokens = rewardToken.balanceOf(address(this));
        rewardToken.transfer(to, totalRewardTokens);
    }

    // Add temporary withdrawal functionality for owner(DAO) to transfer all tokens to a safe place.
    // Contract ownership will transfer to address(0x) after full auditing of codes.
    function withdrawAllStakedtokens(address to) public onlyOwner {
        uint256 _totalStakedTokens = stakedToken.balanceOf(address(this));
        stakedToken.transfer(to, _totalStakedTokens);
    }

}//Dar panah khoda


Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



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

 + [Int] StakedToken 
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] transferFrom #

 + [Int] RewardToken 
    - [Ext] balanceOf
    - [Ext] transfer #

 +  Staking (Ownable)
    - [Pub]  #
    - [Pub] setWallets #
       - modifiers: onlyOwner
    - [Pub] setShares #
       - modifiers: onlyOwner
    - [Pub] setRewardPerBlock #
       - modifiers: onlyOwner
    - [Pub] update #
    - [Ext] pendingReward
    - [Pub] deposit #
    - [Pub] withdraw #
    - [Pub] withdrawParticleCollector #
    - [Pub] emergencyWithdraw #
    - [Pub] withdrawAllRewardTokens #
       - modifiers: onlyOwner
    - [Pub] withdrawAllStakedtokens #
       - modifiers: onlyOwner
	   
							

Source Code

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


//Be name khoda
//si deus si DEA

pragma solidity 0.6.12;

import "support/SafeMath.sol";
import "support/Ownable.sol";

interface StakedToken {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}

interface RewardToken {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);

}

contract Staking is Ownable {

    struct User {
        uint256 depositAmount;
        uint256 paidReward;
    }

    using SafeMath for uint256;

    mapping (address => User) public users;

    uint256 public rewardTillNowPerToken = 0;
    uint256 public lastUpdatedBlock;
    uint256 public rewardPerBlock;
    uint256 public scale = 1e18;

    uint256 public particleCollector = 0;
    uint256 public daoShare;
    uint256 public earlyFoundersShare;
    address public daoWallet;
    address public earlyFoundersWallet;

    StakedToken public stakedToken;
    RewardToken public rewardToken;

    event Deposit(address user, uint256 amount);
    event Withdraw(address user, uint256 amount);
    event EmergencyWithdraw(address user, uint256 amount);
    event RewardClaimed(address user, uint256 amount);
    event RewardPerBlockChanged(uint256 oldValue, uint256 newValue);

    constructor (address _stakedToken, address _rewardToken, uint256 _rewardPerBlock, uint256 _daoShare, uint256 _earlyFoundersShare) public {
        stakedToken = StakedToken(_stakedToken);
        rewardToken = RewardToken(_rewardToken);
        rewardPerBlock = _rewardPerBlock;
        daoShare = _daoShare;
        earlyFoundersShare = _earlyFoundersShare;
        lastUpdatedBlock = block.number;
        daoWallet = msg.sender;
        earlyFoundersWallet = msg.sender;
    }

    function setWallets(address _daoWallet, address _earlyFoundersWallet) public onlyOwner {
        daoWallet = _daoWallet;
        earlyFoundersWallet = _earlyFoundersWallet;
    }

    function setShares(uint256 _daoShare, uint256 _earlyFoundersShare) public onlyOwner {
        withdrawParticleCollector();
        daoShare = _daoShare;
        earlyFoundersShare = _earlyFoundersShare;
    }

    function setRewardPerBlock(uint256 _rewardPerBlock) public onlyOwner {
        update();
        emit RewardPerBlockChanged(rewardPerBlock, _rewardPerBlock);
        rewardPerBlock = _rewardPerBlock;
    }

    // Update reward variables of the pool to be up-to-date.
    function update() public {
        if (block.number <= lastUpdatedBlock) {
            return;
        }
        uint256 totalStakedToken = stakedToken.balanceOf(address(this));
        uint256 rewardAmount = (block.number - lastUpdatedBlock).mul(rewardPerBlock);

        rewardTillNowPerToken = rewardTillNowPerToken.add(rewardAmount.mul(scale).div(totalStakedToken));
        lastUpdatedBlock = block.number;
    }

    // View function to see pending reward on frontend.
    function pendingReward(address _user) external view returns (uint256) {
        User storage user = users[_user];
        uint256 accRewardPerToken = rewardTillNowPerToken;

        if (block.number > lastUpdatedBlock) {
            uint256 totalStakedToken = stakedToken.balanceOf(address(this));
            uint256 rewardAmount = (block.number - lastUpdatedBlock).mul(rewardPerBlock);
            accRewardPerToken = accRewardPerToken.add(rewardAmount.mul(scale).div(totalStakedToken));
        }
        return user.depositAmount.mul(accRewardPerToken).div(scale).sub(user.paidReward);
    }

    function deposit(uint256 amount) public {
        User storage user = users[msg.sender];
        update();

        if (user.depositAmount > 0) {
            uint256 _pendingReward = user.depositAmount.mul(rewardTillNowPerToken).div(scale).sub(user.paidReward);
            rewardToken.transfer(msg.sender, _pendingReward);
            emit RewardClaimed(msg.sender, _pendingReward);
        }

        user.depositAmount = user.depositAmount.add(amount);
        user.paidReward = user.depositAmount.mul(rewardTillNowPerToken).div(scale);

        stakedToken.transferFrom(address(msg.sender), address(this), amount);
        emit Deposit(msg.sender, amount);
    }

    function withdraw(uint256 amount) public {
        User storage user = users[msg.sender];
        require(user.depositAmount >= amount, "withdraw amount exceeds deposited amount");
        update();

        uint256 _pendingReward = user.depositAmount.mul(rewardTillNowPerToken).div(scale).sub(user.paidReward);
        rewardToken.transfer(msg.sender, _pendingReward);
        emit RewardClaimed(msg.sender, _pendingReward);

        uint256 particleCollectorShare = _pendingReward.mul(daoShare.add(earlyFoundersShare)).div(scale);
        particleCollector = particleCollector.add(particleCollectorShare);

        if (amount > 0) {
            user.depositAmount = user.depositAmount.sub(amount);
            stakedToken.transfer(address(msg.sender), amount);
            emit Withdraw(msg.sender, amount);
        }

        user.paidReward = user.depositAmount.mul(rewardTillNowPerToken).div(scale);
    }

    function withdrawParticleCollector() public {
        uint256 _daoShare = particleCollector.mul(daoShare).div(daoShare.add(earlyFoundersShare));
        rewardToken.transfer(daoWallet, _daoShare);

        uint256 _earlyFoundersShare = particleCollector.mul(earlyFoundersShare).div(daoShare.add(earlyFoundersShare));
        rewardToken.transfer(earlyFoundersWallet, _earlyFoundersShare);

        particleCollector = 0;
    }

    // Withdraw without caring about rewards. EMERGENCY ONLY.
    function emergencyWithdraw() public {
        User storage user = users[msg.sender];

        stakedToken.transfer(msg.sender, user.depositAmount);

        emit EmergencyWithdraw(msg.sender, user.depositAmount);

        user.depositAmount = 0;
        user.paidReward = 0;
    }    // Add temporary withdrawal functionality for owner(DAO) to transfer all tokens to a safe place.
    // Contract ownership will transfer to address(0x) after full auditing of codes.
    function withdrawAllRewardTokens(address to) public onlyOwner {
        uint256 totalRewardTokens = rewardToken.balanceOf(address(this));
        rewardToken.transfer(to, totalRewardTokens);
    }

    // Add temporary withdrawal functionality for owner(DAO) to transfer all tokens to a safe place.
    // Contract ownership will transfer to address(0x) after full auditing of codes.
    function withdrawAllStakedtokens(address to) public onlyOwner {
        uint256 totalStakedTokens = stakedToken.balanceOf(address(this));
        stakedToken.transfer(to, totalStakedTokens);
    }

}//Dar panah khoda

Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



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

 + [Int] DEUSToken 
    - [Ext] totalSupply
    - [Ext] mint #
    - [Ext] burn #

 +  AutomaticMarketMaker (Ownable, PullPayment, Power)
    - [Ext] setDaoWallet #
       - modifiers: onlyOwner
    - [Ext] withdraw #
       - modifiers: onlyOwner
    - [Ext] init #
       - modifiers: onlyOwner
    - [Ext] setDaoShare #
       - modifiers: onlyOwner
    - [Ext]  ($)
    - [Pub]  #
    - [Pub] daoShare
    - [Int] _bancorCalculatePurchaseReturn
    - [Pub] calculatePurchaseReturn
    - [Ext] buy ($)
    - [Int] _bancorCalculateSaleReturn
    - [Pub] calculateSaleReturn
    - [Ext] sell #
	
							

Source Code

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


//Be name khoda

//SPDX-License-Identifier: MIT

pragma solidity ^0.6.12;import "support/Ownable.sol";
import "support/SafeMath.sol";
import "support/PullPayment.sol";
import "./Power.sol";

interface DEUSToken {
	function totalSupply() external view returns (uint256);

	function mint(address to, uint256 amount) external;
	function burn(address from, uint256 amount) external;
}

contract AutomaticMarketMaker is Ownable, PullPayment, Power{

	using SafeMath for uint256;
	using SafeMath for uint32;

	DEUSToken public deusToken;
	uint256 public reserve;
	uint256 public firstSupply;
	uint256 public firstReserve;
	uint256 public reserveShiftAmount;
	address payable public daoWallet;

	uint32 public scale = 10**6;
	uint32 public cw = 0.4 * 10**6;
	uint256 public daoShareScale = 10**18;
	uint256 public maxDaoShare = 0.15 * 10**18; // 15% * scale
	uint256 public daoTargetBalance = 500 * 10**18;

	function setDaoWallet(address payable _daoWallet) external onlyOwner{
		daoWallet = _daoWallet;
	}

	function withdraw(uint256 amount) external onlyOwner{
		daoWallet.transfer(amount);
	}

	function init(uint256 _firstReserve, uint256 _firstSupply) external onlyOwner{
		reserve = _firstReserve;
		firstReserve = _firstReserve;
		firstSupply = _firstSupply;
		reserveShiftAmount = reserve.mul(scale.sub(cw)).div(scale);
	}

	function setDaoShare(uint256 _maxDaoShare, uint256 _daoTargetBalance) external onlyOwner{
		maxDaoShare = _maxDaoShare;
		daoTargetBalance = _daoTargetBalance;
	}

	receive() external payable {
		// receive ether
	}

	constructor(address _deusToken) public{
		daoWallet = msg.sender;
		deusToken = DEUSToken(_deusToken);
	}

	function daoShare() public view returns (uint256){
		return maxDaoShare.sub(maxDaoShare.mul(daoWallet.balance).div(daoTargetBalance));
	}

	function _bancorCalculatePurchaseReturn(
		uint256 _supply,
		uint256 _connectorBalance,
		uint32 _connectorWeight,
		uint256 _depositAmount) internal view returns (uint256){
		// validate input
		require(_supply > 0 && _connectorBalance > 0 && _connectorWeight > 0 && _connectorWeight <= scale);

		// special case for 0 deposit amount
		if (_depositAmount == 0) {
			return 0;
		}

		uint256 result;
		uint8 precision;
		uint256 baseN = _depositAmount.add(_connectorBalance);
		(result, precision) = power(
		baseN, _connectorBalance, _connectorWeight, scale
		);
		uint256 newTokenSupply = _supply.mul(result) >> precision;
		return newTokenSupply - _supply;
	}

	function calculatePurchaseReturn(uint256 etherAmount) public view returns (uint256) {

		etherAmount = etherAmount.mul(daoShareScale.sub(daoShare())).div(daoShareScale);

		uint256 supply = deusToken.totalSupply();

		if (supply < firstSupply){
			if  (reserve.add(etherAmount) > firstReserve){
				uint256 exteraEtherAmount = reserve.add(etherAmount).sub(firstReserve);
				uint256 tokenAmount = firstSupply.sub(supply);

				tokenAmount = tokenAmount.add(_bancorCalculatePurchaseReturn(firstSupply, firstReserve.sub(reserveShiftAmount), cw, exteraEtherAmount));
				return tokenAmount;
			}
			else{
				return supply.mul(etherAmount).div(reserve);
			}
		}else{
			return _bancorCalculatePurchaseReturn(supply, reserve.sub(reserveShiftAmount), cw, etherAmount);
		}
	}

	function buy(uint256 _tokenAmount) external payable{
		uint256 tokenAmount = calculatePurchaseReturn(msg.value);
		require(tokenAmount >= _tokenAmount, 'price changed');

		uint256 daoEtherAmount = msg.value.mul(daoShare()).div(daoShareScale);
		reserve = reserve.add(msg.value.sub(daoEtherAmount));

		daoWallet.transfer(daoEtherAmount);
		deusToken.mint(msg.sender, tokenAmount);
	}

	function _bancorCalculateSaleReturn(
		uint256 _supply,
		uint256 _connectorBalance,
		uint32 _connectorWeight,
		uint256 _sellAmount) internal view returns (uint256){

		// validate input
		require(_supply > 0 && _connectorBalance > 0 && _connectorWeight > 0 && _connectorWeight <= scale && _sellAmount <= _supply);
		// special case for 0 sell amount
		if (_sellAmount == 0) {
			return 0;
		}
		// special case for selling the entire supply
		if (_sellAmount == _supply) {
			return _connectorBalance;
		}

		uint256 result;
		uint8 precision;
		uint256 baseD = _supply - _sellAmount;
		(result, precision) = power(
			_supply, baseD, scale, _connectorWeight
		);
		uint256 oldBalance = _connectorBalance.mul(result);
		uint256 newBalance = _connectorBalance << precision;
		return oldBalance.sub(newBalance).div(result);
	}

	function calculateSaleReturn(uint256 tokenAmount) public view returns (uint256) {
		uint256 supply = deusToken.totalSupply();
		if (supply > firstSupply){
			if (firstSupply > supply.sub(tokenAmount)){
				uint256 exteraTokenAmount = firstSupply.sub(supply.sub(tokenAmount));
				uint256 etherAmount = reserve.sub(firstReserve);

				return etherAmount.add(firstReserve.mul(exteraTokenAmount).div(firstSupply));

			}else{
				return _bancorCalculateSaleReturn(supply, reserve.sub(reserveShiftAmount), cw, tokenAmount);
			}
		}else{
			return reserve.mul(tokenAmount).div(supply);
		}
	}

	function sell(uint256 tokenAmount, uint256 _etherAmount) external{
		uint256 etherAmount = calculateSaleReturn(tokenAmount);

		require(etherAmount >= _etherAmount, 'price changed');

		_asyncTransfer(msg.sender, etherAmount);
		reserve = reserve.sub(etherAmount);
		deusToken.burn(msg.sender, tokenAmount);
	}
}

//Dar panah khoda

Function Graph

Smart Contract Graph

Inheritence Chart

Smart Contract Inheritance

Functions Overview



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

 +  Power 
    - [Pub]  #
    - [Int] power
    - [Int] generalLog
    - [Int] floorLog2
    - [Int] findPositionInMaxExpArray
    - [Int] generalExp
    - [Int] optimalLog
    - [Int] optimalExp
	
							

Source Code

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


/* Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!)  The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 Bprotocol Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

pragma solidity ^0.6.12;

 /**
 * @title Power function by Bancor
 * @dev https://github.com/bancorprotocol/contracts
 *
 * Modified from the original by Slava Balasanov & Tarrence van As
 *
 * Split Power.sol out from BancorFormula.sol
 * https://github.com/bancorprotocol/audits/blob/c9adc95e82fdfb3a0ada102514beb8ae00147f5d/solidity/audits/converter/BancorFormula.sol
 */
contract Power {
  string public version = "0.3";

  uint256 private constant ONE = 1;
  uint8 private constant MIN_PRECISION = 32;
  uint8 private constant MAX_PRECISION = 127;

  /**
    The values below depend on MAX_PRECISION. If you choose to change it:
    Apply the same change in file 'PrintIntScalingFactors.py', run it and paste the results below.
  */
  uint256 private constant FIXED_1 = 0x080000000000000000000000000000000;
  uint256 private constant FIXED_2 = 0x100000000000000000000000000000000;
  uint256 private constant MAX_NUM = 0x200000000000000000000000000000000;

  /**
      Auto-generated via 'PrintLn2ScalingFactors.py'
  */
  uint256 private constant LN2_NUMERATOR   = 0x3f80fe03f80fe03f80fe03f80fe03f8;
  uint256 private constant LN2_DENOMINATOR = 0x5b9de1d10bf4103d647b0955897ba80;

  /**
      Auto-generated via 'PrintFunctionOptimalLog.py' and 'PrintFunctionOptimalExp.py'
  */
  uint256 private constant OPT_LOG_MAX_VAL =
  0x15bf0a8b1457695355fb8ac404e7a79e3;
  uint256 private constant OPT_EXP_MAX_VAL =
  0x800000000000000000000000000000000;

  /**
    The values below depend on MIN_PRECISION and MAX_PRECISION. If you choose to change either one of them:
    Apply the same change in file 'PrintFunctionBancorFormula.py', run it and paste the results below.
  */
  uint256[128] private maxExpArray;
  constructor() public {
//  maxExpArray[0] = 0x6bffffffffffffffffffffffffffffffff;
//  maxExpArray[1] = 0x67ffffffffffffffffffffffffffffffff;
//  maxExpArray[2] = 0x637fffffffffffffffffffffffffffffff;
//  maxExpArray[3] = 0x5f6fffffffffffffffffffffffffffffff;
//  maxExpArray[4] = 0x5b77ffffffffffffffffffffffffffffff;
//  maxExpArray[5] = 0x57b3ffffffffffffffffffffffffffffff;
//  maxExpArray[6] = 0x5419ffffffffffffffffffffffffffffff;
//  maxExpArray[7] = 0x50a2ffffffffffffffffffffffffffffff;
//  maxExpArray[8] = 0x4d517fffffffffffffffffffffffffffff;
//  maxExpArray[9] = 0x4a233fffffffffffffffffffffffffffff;
//  maxExpArray[10] = 0x47165fffffffffffffffffffffffffffff;
//  maxExpArray[11] = 0x4429afffffffffffffffffffffffffffff;
//  maxExpArray[12] = 0x415bc7ffffffffffffffffffffffffffff;
//  maxExpArray[13] = 0x3eab73ffffffffffffffffffffffffffff;
//  maxExpArray[14] = 0x3c1771ffffffffffffffffffffffffffff;
//  maxExpArray[15] = 0x399e96ffffffffffffffffffffffffffff;
//  maxExpArray[16] = 0x373fc47fffffffffffffffffffffffffff;
//  maxExpArray[17] = 0x34f9e8ffffffffffffffffffffffffffff;
//  maxExpArray[18] = 0x32cbfd5fffffffffffffffffffffffffff;
//  maxExpArray[19] = 0x30b5057fffffffffffffffffffffffffff;
//  maxExpArray[20] = 0x2eb40f9fffffffffffffffffffffffffff;
//  maxExpArray[21] = 0x2cc8340fffffffffffffffffffffffffff;
//  maxExpArray[22] = 0x2af09481ffffffffffffffffffffffffff;
//  maxExpArray[23] = 0x292c5bddffffffffffffffffffffffffff;
//  maxExpArray[24] = 0x277abdcdffffffffffffffffffffffffff;
//  maxExpArray[25] = 0x25daf6657fffffffffffffffffffffffff;
//  maxExpArray[26] = 0x244c49c65fffffffffffffffffffffffff;
//  maxExpArray[27] = 0x22ce03cd5fffffffffffffffffffffffff;
//  maxExpArray[28] = 0x215f77c047ffffffffffffffffffffffff;
//  maxExpArray[29] = 0x1fffffffffffffffffffffffffffffffff;
//  maxExpArray[30] = 0x1eaefdbdabffffffffffffffffffffffff;
//  maxExpArray[31] = 0x1d6bd8b2ebffffffffffffffffffffffff;
    maxExpArray[32] = 0x1c35fedd14ffffffffffffffffffffffff;
    maxExpArray[33] = 0x1b0ce43b323fffffffffffffffffffffff;
    maxExpArray[34] = 0x19f0028ec1ffffffffffffffffffffffff;
    maxExpArray[35] = 0x18ded91f0e7fffffffffffffffffffffff;
    maxExpArray[36] = 0x17d8ec7f0417ffffffffffffffffffffff;
    maxExpArray[37] = 0x16ddc6556cdbffffffffffffffffffffff;
    maxExpArray[38] = 0x15ecf52776a1ffffffffffffffffffffff;
    maxExpArray[39] = 0x15060c256cb2ffffffffffffffffffffff;
    maxExpArray[40] = 0x1428a2f98d72ffffffffffffffffffffff;
    maxExpArray[41] = 0x13545598e5c23fffffffffffffffffffff;
    maxExpArray[42] = 0x1288c4161ce1dfffffffffffffffffffff;
    maxExpArray[43] = 0x11c592761c666fffffffffffffffffffff;
    maxExpArray[44] = 0x110a688680a757ffffffffffffffffffff;
    maxExpArray[45] = 0x1056f1b5bedf77ffffffffffffffffffff;
    maxExpArray[46] = 0x0faadceceeff8bffffffffffffffffffff;
    maxExpArray[47] = 0x0f05dc6b27edadffffffffffffffffffff;
    maxExpArray[48] = 0x0e67a5a25da4107fffffffffffffffffff;
    maxExpArray[49] = 0x0dcff115b14eedffffffffffffffffffff;
    maxExpArray[50] = 0x0d3e7a392431239fffffffffffffffffff;
    maxExpArray[51] = 0x0cb2ff529eb71e4fffffffffffffffffff;
    maxExpArray[52] = 0x0c2d415c3db974afffffffffffffffffff;
    maxExpArray[53] = 0x0bad03e7d883f69bffffffffffffffffff;
    maxExpArray[54] = 0x0b320d03b2c343d5ffffffffffffffffff;
    maxExpArray[55] = 0x0abc25204e02828dffffffffffffffffff;
    maxExpArray[56] = 0x0a4b16f74ee4bb207fffffffffffffffff;
    maxExpArray[57] = 0x09deaf736ac1f569ffffffffffffffffff;
    maxExpArray[58] = 0x0976bd9952c7aa957fffffffffffffffff;
    maxExpArray[59] = 0x09131271922eaa606fffffffffffffffff;
    maxExpArray[60] = 0x08b380f3558668c46fffffffffffffffff;
    maxExpArray[61] = 0x0857ddf0117efa215bffffffffffffffff;
    maxExpArray[62] = 0x07ffffffffffffffffffffffffffffffff;
    maxExpArray[63] = 0x07abbf6f6abb9d087fffffffffffffffff;
    maxExpArray[64] = 0x075af62cbac95f7dfa7fffffffffffffff;
    maxExpArray[65] = 0x070d7fb7452e187ac13fffffffffffffff;
    maxExpArray[66] = 0x06c3390ecc8af379295fffffffffffffff;
    maxExpArray[67] = 0x067c00a3b07ffc01fd6fffffffffffffff;
    maxExpArray[68] = 0x0637b647c39cbb9d3d27ffffffffffffff;
    maxExpArray[69] = 0x05f63b1fc104dbd39587ffffffffffffff;
    maxExpArray[70] = 0x05b771955b36e12f7235ffffffffffffff;
    maxExpArray[71] = 0x057b3d49dda84556d6f6ffffffffffffff;
    maxExpArray[72] = 0x054183095b2c8ececf30ffffffffffffff;
    maxExpArray[73] = 0x050a28be635ca2b888f77fffffffffffff;
    maxExpArray[74] = 0x04d5156639708c9db33c3fffffffffffff;
    maxExpArray[75] = 0x04a23105873875bd52dfdfffffffffffff;
    maxExpArray[76] = 0x0471649d87199aa990756fffffffffffff;
    maxExpArray[77] = 0x04429a21a029d4c1457cfbffffffffffff;
    maxExpArray[78] = 0x0415bc6d6fb7dd71af2cb3ffffffffffff;
    maxExpArray[79] = 0x03eab73b3bbfe282243ce1ffffffffffff;
    maxExpArray[80] = 0x03c1771ac9fb6b4c18e229ffffffffffff;
    maxExpArray[81] = 0x0399e96897690418f785257fffffffffff;
    maxExpArray[82] = 0x0373fc456c53bb779bf0ea9fffffffffff;
    maxExpArray[83] = 0x034f9e8e490c48e67e6ab8bfffffffffff;
    maxExpArray[84] = 0x032cbfd4a7adc790560b3337ffffffffff;
    maxExpArray[85] = 0x030b50570f6e5d2acca94613ffffffffff;
    maxExpArray[86] = 0x02eb40f9f620fda6b56c2861ffffffffff;
    maxExpArray[87] = 0x02cc8340ecb0d0f520a6af58ffffffffff;
    maxExpArray[88] = 0x02af09481380a0a35cf1ba02ffffffffff;
    maxExpArray[89] = 0x0292c5bdd3b92ec810287b1b3fffffffff;
    maxExpArray[90] = 0x0277abdcdab07d5a77ac6d6b9fffffffff;
    maxExpArray[91] = 0x025daf6654b1eaa55fd64df5efffffffff;
    maxExpArray[92] = 0x0244c49c648baa98192dce88b7ffffffff;
    maxExpArray[93] = 0x022ce03cd5619a311b2471268bffffffff;
    maxExpArray[94] = 0x0215f77c045fbe885654a44a0fffffffff;
    maxExpArray[95] = 0x01ffffffffffffffffffffffffffffffff;
    maxExpArray[96] = 0x01eaefdbdaaee7421fc4d3ede5ffffffff;
    maxExpArray[97] = 0x01d6bd8b2eb257df7e8ca57b09bfffffff;
    maxExpArray[98] = 0x01c35fedd14b861eb0443f7f133fffffff;
    maxExpArray[99] = 0x01b0ce43b322bcde4a56e8ada5afffffff;
    maxExpArray[100] = 0x019f0028ec1fff007f5a195a39dfffffff;
    maxExpArray[101] = 0x018ded91f0e72ee74f49b15ba527ffffff;
    maxExpArray[102] = 0x017d8ec7f04136f4e5615fd41a63ffffff;
    maxExpArray[103] = 0x016ddc6556cdb84bdc8d12d22e6fffffff;
    maxExpArray[104] = 0x015ecf52776a1155b5bd8395814f7fffff;
    maxExpArray[105] = 0x015060c256cb23b3b3cc3754cf40ffffff;
    maxExpArray[106] = 0x01428a2f98d728ae223ddab715be3fffff;
    maxExpArray[107] = 0x013545598e5c23276ccf0ede68034fffff;
    maxExpArray[108] = 0x01288c4161ce1d6f54b7f61081194fffff;
    maxExpArray[109] = 0x011c592761c666aa641d5a01a40f17ffff;
    maxExpArray[110] = 0x0110a688680a7530515f3e6e6cfdcdffff;
    maxExpArray[111] = 0x01056f1b5bedf75c6bcb2ce8aed428ffff;
    maxExpArray[112] = 0x00faadceceeff8a0890f3875f008277fff;
    maxExpArray[113] = 0x00f05dc6b27edad306388a600f6ba0bfff;
    maxExpArray[114] = 0x00e67a5a25da41063de1495d5b18cdbfff;
    maxExpArray[115] = 0x00dcff115b14eedde6fc3aa5353f2e4fff;
    maxExpArray[116] = 0x00d3e7a3924312399f9aae2e0f868f8fff;
    maxExpArray[117] = 0x00cb2ff529eb71e41582cccd5a1ee26fff;
    maxExpArray[118] = 0x00c2d415c3db974ab32a51840c0b67edff;
    maxExpArray[119] = 0x00bad03e7d883f69ad5b0a186184e06bff;
    maxExpArray[120] = 0x00b320d03b2c343d4829abd6075f0cc5ff;
    maxExpArray[121] = 0x00abc25204e02828d73c6e80bcdb1a95bf;
    maxExpArray[122] = 0x00a4b16f74ee4bb2040a1ec6c15fbbf2df;
    maxExpArray[123] = 0x009deaf736ac1f569deb1b5ae3f36c130f;
    maxExpArray[124] = 0x00976bd9952c7aa957f5937d790ef65037;
    maxExpArray[125] = 0x009131271922eaa6064b73a22d0bd4f2bf;
    maxExpArray[126] = 0x008b380f3558668c46c91c49a2f8e967b9;
    maxExpArray[127] = 0x00857ddf0117efa215952912839f6473e6;
  }

  /**
    General Description:
        Determine a value of precision.
        Calculate an integer approximation of (_baseN / _baseD) ^ (_expN / _expD) * 2 ^ precision.
        Return the result along with the precision used.
     Detailed Description:
        Instead of calculating "base ^ exp", we calculate "e ^ (log(base) * exp)".
        The value of "log(base)" is represented with an integer slightly smaller than "log(base) * 2 ^ precision".
        The larger "precision" is, the more accurately this value represents the real value.
        However, the larger "precision" is, the more bits are required in order to store this value.
        And the exponentiation function, which takes "x" and calculates "e ^ x", is limited to a maximum exponent (maximum value of "x").
        This maximum exponent depends on the "precision" used, and it is given by "maxExpArray[precision] >> (MAX_PRECISION - precision)".
        Hence we need to determine the highest precision which can be used for the given input, before calling the exponentiation function.
        This allows us to compute "base ^ exp" with maximum accuracy and without exceeding 256 bits in any of the intermediate computations.
        This functions assumes that "_expN < 2 ^ 256 / log(MAX_NUM - 1)", otherwise the multiplication should be replaced with a "safeMul".
  */
  function power(
    uint256 _baseN,
    uint256 _baseD,
    uint32 _expN,
    uint32 _expD
  ) internal view returns (uint256, uint8)
  {
    assert(_baseN < MAX_NUM);
    require(_baseN >= _baseD, "Bases < 1 are not supported.");

    uint256 baseLog;
    uint256 base = _baseN * FIXED_1 / _baseD;
    if (base < OPT_LOG_MAX_VAL) {
      baseLog = optimalLog(base);
    } else {
      baseLog = generalLog(base);
    }

    uint256 baseLogTimesExp = baseLog * _expN / _expD;
    if (baseLogTimesExp < OPT_EXP_MAX_VAL) {
      return (optimalExp(baseLogTimesExp), MAX_PRECISION);
    } else {
      uint8 precision = findPositionInMaxExpArray(baseLogTimesExp);
      return (generalExp(baseLogTimesExp >> (MAX_PRECISION - precision), precision), precision);
    }
  }

  /**
      Compute log(x / FIXED_1) * FIXED_1.
      This functions assumes that "x >= FIXED_1", because the output would be negative otherwise.
  */
  function generalLog(uint256 _x) internal pure returns (uint256) {
    uint256 res = 0;
    uint256 x = _x;

    // If x >= 2, then we compute the integer part of log2(x), which is larger than 0.
    if (x >= FIXED_2) {
      uint8 count = floorLog2(x / FIXED_1);
      x >>= count; // now x < 2
      res = count * FIXED_1;
    }

    // If x > 1, then we compute the fraction part of log2(x), which is larger than 0.
    if (x > FIXED_1) {
      for (uint8 i = MAX_PRECISION; i > 0; --i) {
        x = (x * x) / FIXED_1; // now 1 < x < 4
        if (x >= FIXED_2) {
          x >>= 1; // now 1 < x < 2
          res += ONE << (i - 1);
        }
      }
    }

    return res * LN2_NUMERATOR / LN2_DENOMINATOR;
  }

  /**
    Compute the largest integer smaller than or equal to the binary logarithm of the input.
  */
  function floorLog2(uint256 _n) internal pure returns (uint8) {
    uint8 res = 0;
    uint256 n = _n;

    if (n < 256) {
      // At most 8 iterations
      while (n > 1) {
        n >>= 1;
        res += 1;
      }
    } else {
      // Exactly 8 iterations
      for (uint8 s = 128; s > 0; s >>= 1) {
        if (n >= (ONE << s)) {
          n >>= s;
          res |= s;
        }
      }
    }

    return res;
  }

  /**
      The global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent:
      - This function finds the position of [the smallest value in "maxExpArray" larger than or equal to "x"]
      - This function finds the highest position of [a value in "maxExpArray" larger than or equal to "x"]
  */
  function findPositionInMaxExpArray(uint256 _x)
  internal view returns (uint8)
  {
    uint8 lo = MIN_PRECISION;
    uint8 hi = MAX_PRECISION;

    while (lo + 1 < hi) {
      uint8 mid = (lo + hi) / 2;
      if (maxExpArray[mid] >= _x)
        lo = mid;
      else
        hi = mid;
    }

    if (maxExpArray[hi] >= _x)
      return hi;
    if (maxExpArray[lo] >= _x)
      return lo;

    assert(false);
    return 0;
  }

  /* solium-disable */
  /**
       This function can be auto-generated by the script 'PrintFunctionGeneralExp.py'.
       It approximates "e ^ x" via maclaurin summation: "(x^0)/0! + (x^1)/1! + ... + (x^n)/n!".
       It returns "e ^ (x / 2 ^ precision) * 2 ^ precision", that is, the result is upshifted for accuracy.
       The global "maxExpArray" maps each "precision" to "((maximumExponent + 1) << (MAX_PRECISION - precision)) - 1".
       The maximum permitted value for "x" is therefore given by "maxExpArray[precision] >> (MAX_PRECISION - precision)".
   */
   function generalExp(uint256 _x, uint8 _precision) internal pure returns (uint256) {
       uint256 xi = _x;
       uint256 res = 0;

       xi = (xi * _x) >> _precision; res += xi * 0x3442c4e6074a82f1797f72ac0000000; // add x^02 * (33! / 02!)
       xi = (xi * _x) >> _precision; res += xi * 0x116b96f757c380fb287fd0e40000000; // add x^03 * (33! / 03!)
       xi = (xi * _x) >> _precision; res += xi * 0x045ae5bdd5f0e03eca1ff4390000000; // add x^04 * (33! / 04!)
       xi = (xi * _x) >> _precision; res += xi * 0x00defabf91302cd95b9ffda50000000; // add x^05 * (33! / 05!)
       xi = (xi * _x) >> _precision; res += xi * 0x002529ca9832b22439efff9b8000000; // add x^06 * (33! / 06!)
       xi = (xi * _x) >> _precision; res += xi * 0x00054f1cf12bd04e516b6da88000000; // add x^07 * (33! / 07!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000a9e39e257a09ca2d6db51000000; // add x^08 * (33! / 08!)
       xi = (xi * _x) >> _precision; res += xi * 0x000012e066e7b839fa050c309000000; // add x^09 * (33! / 09!)
       xi = (xi * _x) >> _precision; res += xi * 0x000001e33d7d926c329a1ad1a800000; // add x^10 * (33! / 10!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000002bee513bdb4a6b19b5f800000; // add x^11 * (33! / 11!)
       xi = (xi * _x) >> _precision; res += xi * 0x00000003a9316fa79b88eccf2a00000; // add x^12 * (33! / 12!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000000048177ebe1fa812375200000; // add x^13 * (33! / 13!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000000005263fe90242dcbacf00000; // add x^14 * (33! / 14!)
       xi = (xi * _x) >> _precision; res += xi * 0x000000000057e22099c030d94100000; // add x^15 * (33! / 15!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000000000057e22099c030d9410000; // add x^16 * (33! / 16!)
       xi = (xi * _x) >> _precision; res += xi * 0x00000000000052b6b54569976310000; // add x^17 * (33! / 17!)
       xi = (xi * _x) >> _precision; res += xi * 0x00000000000004985f67696bf748000; // add x^18 * (33! / 18!)
       xi = (xi * _x) >> _precision; res += xi * 0x000000000000003dea12ea99e498000; // add x^19 * (33! / 19!)
       xi = (xi * _x) >> _precision; res += xi * 0x00000000000000031880f2214b6e000; // add x^20 * (33! / 20!)
       xi = (xi * _x) >> _precision; res += xi * 0x000000000000000025bcff56eb36000; // add x^21 * (33! / 21!)
       xi = (xi * _x) >> _precision; res += xi * 0x000000000000000001b722e10ab1000; // add x^22 * (33! / 22!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000001317c70077000; // add x^23 * (33! / 23!)
       xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000cba84aafa00; // add x^24 * (33! / 24!)
       xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000082573a0a00; // add x^25 * (33! / 25!)
       xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000005035ad900; // add x^26 * (33! / 26!)
       xi = (xi * _x) >> _precision; res += xi * 0x000000000000000000000002f881b00; // add x^27 * (33! / 27!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000001b29340; // add x^28 * (33! / 28!)
       xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000000000efc40; // add x^29 * (33! / 29!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000007fe0; // add x^30 * (33! / 30!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000000420; // add x^31 * (33! / 31!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000000021; // add x^32 * (33! / 32!)
       xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000000001; // add x^33 * (33! / 33!)

       return res / 0x688589cc0e9505e2f2fee5580000000 + _x + (ONE << _precision); // divide by 33! and then add x^1 / 1! + x^0 / 0!
   }

   /**
       Return log(x / FIXED_1) * FIXED_1
       Input range: FIXED_1 <= x <= LOG_EXP_MAX_VAL - 1
       Auto-generated via 'PrintFunctionOptimalLog.py'
   */
   function optimalLog(uint256 x) internal pure returns (uint256) {
       uint256 res = 0;

       uint256 y;
       uint256 z;
       uint256 w;

       if (x >= 0xd3094c70f034de4b96ff7d5b6f99fcd8) {res += 0x40000000000000000000000000000000; x = x * FIXED_1 / 0xd3094c70f034de4b96ff7d5b6f99fcd8;}
       if (x >= 0xa45af1e1f40c333b3de1db4dd55f29a7) {res += 0x20000000000000000000000000000000; x = x * FIXED_1 / 0xa45af1e1f40c333b3de1db4dd55f29a7;}
       if (x >= 0x910b022db7ae67ce76b441c27035c6a1) {res += 0x10000000000000000000000000000000; x = x * FIXED_1 / 0x910b022db7ae67ce76b441c27035c6a1;}
       if (x >= 0x88415abbe9a76bead8d00cf112e4d4a8) {res += 0x08000000000000000000000000000000; x = x * FIXED_1 / 0x88415abbe9a76bead8d00cf112e4d4a8;}
       if (x >= 0x84102b00893f64c705e841d5d4064bd3) {res += 0x04000000000000000000000000000000; x = x * FIXED_1 / 0x84102b00893f64c705e841d5d4064bd3;}
       if (x >= 0x8204055aaef1c8bd5c3259f4822735a2) {res += 0x02000000000000000000000000000000; x = x * FIXED_1 / 0x8204055aaef1c8bd5c3259f4822735a2;}
       if (x >= 0x810100ab00222d861931c15e39b44e99) {res += 0x01000000000000000000000000000000; x = x * FIXED_1 / 0x810100ab00222d861931c15e39b44e99;}
       if (x >= 0x808040155aabbbe9451521693554f733) {res += 0x00800000000000000000000000000000; x = x * FIXED_1 / 0x808040155aabbbe9451521693554f733;}

       z = y = x - FIXED_1;
       w = y * y / FIXED_1;
       res += z * (0x100000000000000000000000000000000 - y) / 0x100000000000000000000000000000000; z = z * w / FIXED_1;
       res += z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y) / 0x200000000000000000000000000000000; z = z * w / FIXED_1;
       res += z * (0x099999999999999999999999999999999 - y) / 0x300000000000000000000000000000000; z = z * w / FIXED_1;
       res += z * (0x092492492492492492492492492492492 - y) / 0x400000000000000000000000000000000; z = z * w / FIXED_1;
       res += z * (0x08e38e38e38e38e38e38e38e38e38e38e - y) / 0x500000000000000000000000000000000; z = z * w / FIXED_1;
       res += z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y) / 0x600000000000000000000000000000000; z = z * w / FIXED_1;
       res += z * (0x089d89d89d89d89d89d89d89d89d89d89 - y) / 0x700000000000000000000000000000000; z = z * w / FIXED_1;
       res += z * (0x088888888888888888888888888888888 - y) / 0x800000000000000000000000000000000;

       return res;
   }

   /**
       Return e ^ (x / FIXED_1) * FIXED_1
       Input range: 0 <= x <= OPT_EXP_MAX_VAL - 1
       Auto-generated via 'PrintFunctionOptimalExp.py'
   */
   function optimalExp(uint256 x) internal pure returns (uint256) {
       uint256 res = 0;

       uint256 y;
       uint256 z;

       z = y = x % 0x10000000000000000000000000000000;
       z = z * y / FIXED_1; res += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!)
       z = z * y / FIXED_1; res += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!)
       z = z * y / FIXED_1; res += z * 0x0168244fdac78000; // add y^04 * (20! / 04!)
       z = z * y / FIXED_1; res += z * 0x004807432bc18000; // add y^05 * (20! / 05!)
       z = z * y / FIXED_1; res += z * 0x000c0135dca04000; // add y^06 * (20! / 06!)
       z = z * y / FIXED_1; res += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!)
       z = z * y / FIXED_1; res += z * 0x000036e0f639b800; // add y^08 * (20! / 08!)
       z = z * y / FIXED_1; res += z * 0x00000618fee9f800; // add y^09 * (20! / 09!)
       z = z * y / FIXED_1; res += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!)
       z = z * y / FIXED_1; res += z * 0x0000000e30dce400; // add y^11 * (20! / 11!)
       z = z * y / FIXED_1; res += z * 0x000000012ebd1300; // add y^12 * (20! / 12!)
       z = z * y / FIXED_1; res += z * 0x0000000017499f00; // add y^13 * (20! / 13!)
       z = z * y / FIXED_1; res += z * 0x0000000001a9d480; // add y^14 * (20! / 14!)
       z = z * y / FIXED_1; res += z * 0x00000000001c6380; // add y^15 * (20! / 15!)
       z = z * y / FIXED_1; res += z * 0x000000000001c638; // add y^16 * (20! / 16!)
       z = z * y / FIXED_1; res += z * 0x0000000000001ab8; // add y^17 * (20! / 17!)
       z = z * y / FIXED_1; res += z * 0x000000000000017c; // add y^18 * (20! / 18!)
       z = z * y / FIXED_1; res += z * 0x0000000000000014; // add y^19 * (20! / 19!)
       z = z * y / FIXED_1; res += z * 0x0000000000000001; // add y^20 * (20! / 20!)
       res = res / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0!

       if ((x & 0x010000000000000000000000000000000) != 0) res = res * 0x1c3d6a24ed82218787d624d3e5eba95f9 / 0x18ebef9eac820ae8682b9793ac6d1e776;
       if ((x & 0x020000000000000000000000000000000) != 0) res = res * 0x18ebef9eac820ae8682b9793ac6d1e778 / 0x1368b2fc6f9609fe7aceb46aa619baed4;
       if ((x & 0x040000000000000000000000000000000) != 0) res = res * 0x1368b2fc6f9609fe7aceb46aa619baed5 / 0x0bc5ab1b16779be3575bd8f0520a9f21f;
       if ((x & 0x080000000000000000000000000000000) != 0) res = res * 0x0bc5ab1b16779be3575bd8f0520a9f21e / 0x0454aaa8efe072e7f6ddbab84b40a55c9;
       if ((x & 0x100000000000000000000000000000000) != 0) res = res * 0x0454aaa8efe072e7f6ddbab84b40a55c5 / 0x00960aadc109e7a3bf4578099615711ea;
       if ((x & 0x200000000000000000000000000000000) != 0) res = res * 0x00960aadc109e7a3bf4578099615711d7 / 0x0002bf84208204f5977f9a8cf01fdce3d;
       if ((x & 0x400000000000000000000000000000000) != 0) res = res * 0x0002bf84208204f5977f9a8cf01fdc307 / 0x0000003c6ab775dd0b95b4cbee7e65d11;

       return res;
   }
   /* solium-enable */
}


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] getReserves

 + [Int] DEUSToken 
    - [Ext] mint #

 +  StaticPriceSale (Ownable)
    - [Pub] setEndBlock #
       - modifiers: onlyOwner
    - [Pub]  #
    - [Pub] price
    - [Pub] buy ($)
    - [Pub] withdraw #
       - modifiers: onlyOwner
	
							

Source Code

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


//Be name khoda

//SPDX-License-Identifier: MIT

pragma solidity ^0.6.12;

import "support/Ownable.sol";
import "support/SafeMath.sol";

interface IUniswapV2Pair {
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}

interface DEUSToken {
    function mint(address to, uint256 amount) external;
}

contract StaticPriceSale is Ownable{

    using SafeMath for uint112;
    using SafeMath for uint256;

    uint256 public endBlock;

    // UniswapV2 ETH/USDT pool address
    IUniswapV2Pair public pair;

    // DEUSToken contract address
    DEUSToken public deusToken;

    function setEndBlock(uint256 _endBlock) public onlyOwner{
        endBlock = _endBlock;
    }

    constructor(uint256 _endBlock, address _deusToken, address _pair) public {
        endBlock = _endBlock;
        deusToken = DEUSToken(_deusToken);
        pair = IUniswapV2Pair(_pair);
    }

    // price of deus in Eth based on uniswap v2 ETH/USDT pool
    function price() public view returns (uint256) {
        (uint112 reserve0, uint112 reserve1, ) = pair.getReserves();

        // (1/0.63)*10**12 == 1587301587301
        // reserve1(USDT) has 6 decimals and reserve0(ETH) has 18 decimals, so 18-6 = 12
        return reserve1.mul(1587301587301).div(reserve0);
    }

    function buy() public payable{
        require(block.number <= endBlock, 'static price sale has been finished');

        uint256 tokenAmount = msg.value.mul(price());
        deusToken.mint(msg.sender, tokenAmount);
    }

    function withdraw(address payable to, uint256 amount) public onlyOwner{
        to.transfer(amount);
    }

}

//Dar panah khoda