contract SATO is ERC20Detailed, Ownable {
        // PLEASE READ BEFORE CHANGING ANY ACCOUNTING OR MATH
        // Anytime there is division, there is a risk of numerical instability from rounding errors. In
        // order to minimize this risk, we adhere to the following guidelines:
        // 1) The conversion rate adopted is the number of gons that equals 1 SATO.
        //    The inverse rate must not be used--TOTAL_GONS is always the numerator and _totalSupply is
        //    always the denominator. (i.e. If you want to convert gons to SATOs instead of
        //    multiplying by the inverse rate, you should divide by the normal rate)
        // 2) Gon balances converted into SATOs are always rounded down (truncated).
        //
        // We make the following guarantees:
        // - If address 'A' transfers x SATOs to address 'B'. A's resulting external balance will
        //   be decreased by precisely x SATOs, and B's external balance will be precisely
        //   increased by x SATOs.
        //
        // We do not guarantee that the sum of all balances equals the result of calling totalSupply().
        // This is because, for any conversion function 'f()' that has non-zero rounding error,
        // f(x0) + f(x1) + ... + f(xn) is not always equal to f(x0 + x1 + ... xn).
        using SafeMath for uint256;
        using SafeMathInt for int256;
    
        event LogRebase(uint256 indexed epoch, uint256 totalSupply);
        event LogRebasePaused(bool paused);
        event LogTokenPaused(bool paused);
        event LogSATOPolicyUpdated(address SATOPolicy);
    
        // Used for authentication
        address public SATOPolicy;
    
        modifier onlySATOPolicy() {
            require(msg.sender == SATOPolicy);
            _;
        }
    
        // Precautionary emergency controls.
        bool public rebasePaused;
        bool public tokenPaused;
    
        modifier whenRebaseNotPaused() {
            require(!rebasePaused);
            _;
        }
    
        modifier whenTokenNotPaused() {
            require(!tokenPaused);
            _;
        }
    
        modifier validRecipient(address to) {
            require(to != address(0x0));
            require(to != address(this));
            _;
        }
    
        uint256 private constant DECIMALS = 18;
        uint256 private constant MAX_UINT256 = ~uint256(0);
        uint256 private constant INITIAL_SATO_SUPPLY = 5000000 * 10**DECIMALS;
    
        // TOTAL_GONS is a multiple of INITIAL_SATO_SUPPLY so that _gonsPerFragment is an integer.
        // Use the highest value that fits in a uint256 for max granularity.
        uint256 private constant TOTAL_GONS = MAX_UINT256 -
            (MAX_UINT256 % INITIAL_SATO_SUPPLY);
    
        // MAX_SUPPLY = maximum integer < (sqrt(4*TOTAL_GONS + 1) - 1) / 2
        uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1
    
        uint256 private _totalSupply;
        uint256 private _gonsPerFragment;
        mapping(address => uint256) private _gonBalances;
    
        // This is denominated in SATOs, because the gons-SATOs conversion might change before
        // it's fully paid.
        mapping(address => mapping(address => uint256)) private _allowedSATOs;
    
        /**
         * @param SATOPolicy_ The address of the SATO policy contract to use for authentication.
         */
        function setSATOPolicy(address SATOPolicy_) external onlyOwner {
            SATOPolicy = SATOPolicy_;
            emit LogSATOPolicyUpdated(SATOPolicy_);
        }
    
        /**
         * @dev Pauses or unpauses the execution of rebase operations.
         * @param paused Pauses rebase operations if this is true.
         */
        function setRebasePaused(bool paused) external onlyOwner {
            rebasePaused = paused;
            emit LogRebasePaused(paused);
        }
    
        /**
         * @dev Pauses or unpauses execution of ERC-20 transactions.
         * @param paused Pauses ERC-20 transactions if this is true.
         */
        function setTokenPaused(bool paused) external onlyOwner {
            tokenPaused = paused;
            emit LogTokenPaused(paused);
        }
    
        /**
         * @dev Notifies SATOs contract about a new rebase cycle.
         * @param supplyDelta The number of new SATO tokens to add into circulation via expansion.
         * @return The total number of SATOs after the supply adjustment.
         */
        function rebase(uint256 epoch, int256 supplyDelta)
            external
            onlySATOPolicy
            whenRebaseNotPaused
            returns (uint256)
        {
            if (supplyDelta == 0) {
                emit LogRebase(epoch, _totalSupply);
                return _totalSupply;
            }
    
            if (supplyDelta < 0) {
                _totalSupply = _totalSupply.sub(uint256(supplyDelta.abs()));
            } else {
                _totalSupply = _totalSupply.add(uint256(supplyDelta));
            }
    
            if (_totalSupply > MAX_SUPPLY) {
                _totalSupply = MAX_SUPPLY;
            }
    
            _gonsPerFragment = TOTAL_GONS.div(_totalSupply);
    
            // From this point forward, _gonsPerFragment is taken as the source of truth.
            // We recalculate a new _totalSupply to be in agreement with the _gonsPerFragment
            // conversion rate.
            // This means our applied supplyDelta can deviate from the requested supplyDelta,
            // but this deviation is guaranteed to be < (_totalSupply^2)/(TOTAL_GONS - _totalSupply).
            //
            // In the case of _totalSupply <= MAX_UINT128 (our current supply cap), this
            // deviation is guaranteed to be < 1, so we can omit this step. If the supply cap is
            // ever increased, it must be re-included.
            // _totalSupply = TOTAL_GONS.div(_gonsPerFragment)
    
            emit LogRebase(epoch, _totalSupply);
            return _totalSupply;
        }
    
        function initialize(address owner_) public initializer {
            ERC20Detailed.initialize("SwapAll Algorithmic Token", "SATO", uint8(DECIMALS));
            Ownable.initialize(owner_);
    
            rebasePaused = false;
            tokenPaused = false;
    
            _totalSupply = INITIAL_SATO_SUPPLY;
            _gonBalances[owner_] = TOTAL_GONS;
            _gonsPerFragment = TOTAL_GONS.div(_totalSupply);
    
            emit Transfer(address(0x0), owner_, _totalSupply);
        }
    
        /**
         * @return The total number of SATOs.
         */
        function totalSupply() public view returns (uint256) {
            return _totalSupply;
        }
    
        /**
         * @param who The address to query.
         * @return The balance of the specified address.
         */
        function balanceOf(address who) public view returns (uint256) {
            return _gonBalances[who].div(_gonsPerFragment);
        }
    
        /**
         * @dev Transfer tokens to a specified address.
         * @param to The address to transfer to.
         * @param value The amount to be transferred.
         * @return True on success, false otherwise.
         */
        function transfer(address to, uint256 value)
            public
            validRecipient(to)
            whenTokenNotPaused
            returns (bool)
        {
            uint256 gonValue = value.mul(_gonsPerFragment);
            _gonBalances[msg.sender] = _gonBalances[msg.sender].sub(gonValue);
            _gonBalances[to] = _gonBalances[to].add(gonValue);
            emit Transfer(msg.sender, to, value);
            return true;
        }
    
        /**
         * @dev Function to check the amount of tokens that an owner has allowed to a spender.
         * @param owner_ The address which owns the funds.
         * @param spender The address which will spend the funds.
         * @return The number of tokens still available for the spender.
         */
        function allowance(address owner_, address spender)
            public
            view
            returns (uint256)
        {
            return _allowedSATOs[owner_][spender];
        }
    
        /**
         * @dev Transfer tokens from one address to another.
         * @param from The address you want to send tokens from.
         * @param to The address you want to transfer to.
         * @param value The amount of tokens to be transferred.
         */
        function transferFrom(
            address from,
            address to,
            uint256 value
        ) public validRecipient(to) whenTokenNotPaused returns (bool) {
            _allowedSATOs[from][msg.sender] = _allowedSATOs[from][msg
                .sender]
                .sub(value);
    
            uint256 gonValue = value.mul(_gonsPerFragment);
            _gonBalances[from] = _gonBalances[from].sub(gonValue);
            _gonBalances[to] = _gonBalances[to].add(gonValue);
            emit Transfer(from, to, value);
    
            return true;
        }
    
        /**
         * @dev Approve the passed address to spend the specified amount of tokens on behalf of
         * msg.sender. This method is included for ERC20 compatibility.
         * increaseAllowance and decreaseAllowance should be used instead.
         * Changing an allowance with this method brings the risk that someone may transfer both
         * the old and the new allowance - if they are both greater than zero - if a transfer
         * transaction is mined before the later approve() call is mined.
         *
         * @param spender The address which will spend the funds.
         * @param value The amount of tokens to be spent.
         */
        function approve(address spender, uint256 value)
            public
            whenTokenNotPaused
            returns (bool)
        {
            _allowedSATOs[msg.sender][spender] = value;
            emit Approval(msg.sender, spender, value);
            return true;
        }
    
        /**
         * @dev Increase the amount of tokens that an owner has allowed to a spender.
         * This method should be used instead of approve() to avoid the double approval vulnerability
         * described above.
         * @param spender The address which will spend the funds.
         * @param addedValue The amount of tokens to increase the allowance by.
         */
        function increaseAllowance(address spender, uint256 addedValue)
            public
            whenTokenNotPaused
            returns (bool)
        {
            _allowedSATOs[msg.sender][spender] = _allowedSATOs[msg
                .sender][spender]
                .add(addedValue);
            emit Approval(
                msg.sender,
                spender,
                _allowedSATOs[msg.sender][spender]
            );
            return true;
        }
    
        /**
         * @dev Decrease the amount of tokens that an owner has allowed to a spender.
         *
         * @param spender The address which will spend the funds.
         * @param subtractedValue The amount of tokens to decrease the allowance by.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue)
            public
            whenTokenNotPaused
            returns (bool)
        {
            uint256 oldValue = _allowedSATOs[msg.sender][spender];
            if (subtractedValue >= oldValue) {
                _allowedSATOs[msg.sender][spender] = 0;
            } else {
                _allowedSATOs[msg.sender][spender] = oldValue.sub(
                    subtractedValue
                );
            }
            emit Approval(
                msg.sender,
                spender,
                _allowedSATOs[msg.sender][spender]
            );
            return true;
        }
    }
/**
 * @title SATO ERC20 token
 * @dev This is part of an implementation of the SATO Ideal Money protocol.
 *      SATO is a normal ERC20 token, but its supply can be adjusted by splitting and
 *      combining tokens proportionally across all wallets.
 *
 *      SATO balances are internally represented with a hidden denomination, 'gons'.
 *      We support splitting the currency in expansion and combining the currency on contraction by
 *      changing the exchange rate between the hidden 'gons' and the public 'SATOs'.
 */
function transferFrom(
    address from,
    address to,
    uint256 value
) public validRecipient(to) whenTokenNotPaused returns (bool) {
    _allowedSATOs[from][msg.sender] = _allowedSATOs[from][msg
        .sender]
        .sub(value);
    
    uint256 gonValue = value.mul(_gonsPerFragment);
    _gonBalances[from] = _gonBalances[from].sub(gonValue);
    _gonBalances[to] = _gonBalances[to].add(gonValue);
    emit Transfer(from, to, value);
    
    return true;
}

/**
 * @dev Transfer tokens from one address to another.
 * @param from The address you want to send tokens from.
 * @param to The address you want to transfer to.
 * @param value The amount of tokens to be transferred.
 */