contract Oracle is OwnableBasalt {
    uint256 public constant VERSION = 4;

    event NewSymbol(bytes32 _currency);

    mapping(bytes32 => bool) public supported;
    bytes32[] public currencies;

    /**
        @dev Returns the url where the oracle exposes a valid "oracleData" if needed
    */
    function url() public view returns (string memory);

    /**
        @dev Returns a valid convertion rate from the currency given to RCN

        @param symbol Symbol of the currency
        @param data Generic data field, could be used for off-chain signing
    */
    function getRate(bytes32 symbol, bytes memory data) public returns (uint256 rate, uint256 decimals);

    /**
        @dev Adds a currency to the oracle, once added it cannot be removed

        @param ticker Symbol of the currency

        @return if the creation was done successfully
    */
    function addCurrency(string memory ticker) public onlyOwner returns (bool) {
        bytes32 currency = encodeCurrency(ticker);
        emit NewSymbol(currency);
        supported[currency] = true;
        currencies.push(currency);
        return true;
    }

    /**
        @return the currency encoded as a bytes32
    */
    function encodeCurrency(string memory currency) public pure returns (bytes32 o) {
        require(bytes(currency).length <= 32);
        assembly {
            o := mload(add(currency, 32))
        }
    }

    /**
        @return the currency string from a encoded bytes32
    */
    function decodeCurrency(bytes32 b) public pure returns (string memory o) {
        uint256 ns = 256;
        while (true) {
            if (ns == 0 || (b<<ns-8) != 0)
                break;
            ns -= 8;
        }
        assembly {
            ns := div(ns, 8)
            o := mload(0x40)
            mstore(0x40, add(o, and(add(add(ns, 0x20), 0x1f), not(0x1f))))
            mstore(o, ns)
            mstore(add(o, 32), b)
        }
    }

}
/**
 @dev Defines the interface of a standard RCN oracle.
 
 The oracle is an agent in the RCN network that supplies a convertion rate between RCN and any other currency,
 it's primarily used by the exchange but could be used by any other agent.
 */
function addCurrency(string memory ticker) public onlyOwner returns (bool) {
    bytes32 currency = encodeCurrency(ticker);
    emit NewSymbol(currency);
    supported[currency] = true;
    currencies.push(currency);
    return true;
}

/**
 @dev Adds a currency to the oracle, once added it cannot be removed
 
 @param ticker Symbol of the currency
 
 @return if the creation was done successfully
 */