contract Aqo {
    /// @notice maximum total supply 100 aqo
    /// @dev erc20
    /// @return total amount of tokens, aqo*1e-18
    uint256 public totalSupply;

    /// @dev erc20
    /// @return number of tokens of the address, aqo*1e-18
    mapping(address => uint256) public balanceOf;

    /// @notice allowance(owner, spender)
    /// @dev erc20
    /// @return number of tokens allowed to be sent using transferFrom, aqo*1e-18
    mapping(address => mapping(address => uint256)) public allowance;

    /// @dev erc20
    uint8 public constant decimals = 18;

    /// @dev erc20
    string public constant name = "aqoleg";

    /// @dev erc20
    string public constant symbol = "aqo";

    /// @notice logs each token transfer
    /// @dev erc20
    /// @param _from sender address or zero for minted tokens
    /// @param _to recipient address or zero for burned tokens
    /// @param _value number of tokens, aqo*1e-18
    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    /// @notice logs each change of the allowance for transferFrom by the owner
    /// @dev erc20
    /// @param _value number of tokens, aqo*1e-18
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);

    /// @notice logs a new price after each change
    /// @param _price token price, wei/aqo
    event Price(uint256 _price);

    constructor() {
        emit Price(price());
    }

    /// @notice if something is unrecognized, buys tokens
    fallback () external payable {
        buy();
    }

    /// @notice buys tokens with incoming eth
    receive () external payable {
        buy();
    }

    /// @notice minimum price 1 eth/aqo
    /// @return current price, wei/aqo
    function price() public view returns (uint256) {
        return 1e58 / (1e20 - totalSupply) ** 2;
    }

    /// @notice sends tokens to the sender in exchange for all incoming eth
    /// @return number of tokens purchased, aqo*1-18
    function buy() public payable returns (uint256) {
        uint256 newTotalSupply = 1e20 - 1e40 / (address(this).balance + 1e20);
        uint256 tokens = newTotalSupply - totalSupply;
        totalSupply = newTotalSupply;
        balanceOf[msg.sender] += tokens;
        emit Transfer(address(0), msg.sender, tokens);
        emit Price(price());
        return tokens;
    }

    /// @notice sends eth to the sender in exchange for tokens
    /// @param _tokens number of tokens to sell, aqo*1-18
    /// @return number of wei from sale
    function sell(uint256 _tokens) external returns (uint256) {
        require(balanceOf[msg.sender] >= _tokens, "incufficient token balance");
        totalSupply -= _tokens;
        balanceOf[msg.sender] -= _tokens;
        uint256 value = address(this).balance - (1e40 / (1e20 - totalSupply) - 1e20);
        payable(msg.sender).transfer(value);
        emit Transfer(msg.sender, address(0), _tokens);
        emit Price(price());
        return value;
    }

    /// @notice transfers sender tokens
    /// @dev erc20
    /// @param _to recipient address
    /// @param _value number of tokens to transfer, aqo*1-18
    /// @return true on success
    function transfer(address _to, uint256 _value) public returns (bool) {
        return _transfer(msg.sender, _to, _value);
    }

    /// @notice transfers tokens of other address
    /// @dev erc20
    /// @param _from token owner address
    /// @param _to recipient address
    /// @param _value number of tokens to transfer, aqo*1-18
    /// @return true on success
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(allowance[_from][msg.sender] >= _value, "not allowed");
        allowance[_from][msg.sender] -= _value;
        return _transfer(_from, _to, _value);
    }

    function _transfer(address _from, address _to, uint256 _value) private returns (bool) {
        require(_to != address(0), "zero recipient");
        require(balanceOf[_from] >= _value, "insufficient token balance");
        balanceOf[_from] -= _value;
        balanceOf[_to] += _value;
        emit Transfer(_from, _to, _value);
        return true;
    }

    /// @notice changes allowance for transferFrom
    /// @dev erc20
    /// @param _spender token spender address
    /// @param _value number of tokens allowed to spend, aqo*1-18
    /// @return true on success
    function approve(address _spender, uint256 _value) public returns (bool) {
        require(_spender != address(0), "zero spender");
        allowance[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);
        return true;
    }

    /// @notice anyone can get spam tokens
    /// @param _token spam token address
    /// @param _value number of tokens to get
    function clean(address _token, uint256 _value) external {
        Erc20(_token).transfer(msg.sender, _value);
    }
}
/// @title erc20 token with built-in exchange
/// @author aqoleg
/// @dev checked for overflow, tested for deposit with 'selfdistruct'
function transfer(address _to, uint256 _value) public returns (bool) {
    return _transfer(msg.sender, _to, _value);
}

/// @notice transfers sender tokens
/// @dev erc20
/// @param _to recipient address
/// @param _value number of tokens to transfer, aqo*1-18
/// @return true on success