solidityhedera-hashgraphhashgraphhedera

How to get an exchange rate between USD and HBAR for use in Hedera application or smart contract?


How can my smart contract or application access USD/HBAR exchange rate info from a file on the Hedera network (Hedera File Service)?

The file I'm interested in is 0.0.112. I tried doing a query with the SDK from my application and it seems to get me the info, but how can I use this in a contract and how real-time is this price info?

async function main() {
    const fileQuery = new FileContentsQuery().setFileId("0.0.112");
    const contents = await fileQuery.execute(client);
    console.log(contents.toString());
}
main();

Solution

  • You’re moving in the right direction. A few points:

    As you found out, an external app can access that exchange rate in 0.0.112 by just doing a FileContentsQuery() with the SDK. You could also use this mirror REST API call (https://mainnet-public.mirrornode.hedera.com/api/v1/network/exchangerate), which also exposes the exchange rate info in the HFS file.

    If you need to access that exchange rate info from 0.0.112 in a smart contract, then I’d suggest checking out HIP-475 (https://hips.hedera.com/hip/hip-475), so you may end up with something like:

    import "./IExchangeRate.sol";
    
    abstract contract SelfFunding {
        uint256 constant TINY_PARTS_PER_WHOLE = 100_000_000;
        address constant PRECOMPILE_ADDRESS = address(0x168);
    
        function tinycentsToTinybars(uint256 tinycents) internal returns (uint256 tinybars) {
            (bool success, bytes memory result) = PRECOMPILE_ADDRESS.call(
                abi.encodeWithSelector(IExchangeRate.tinycentsToTinybars.selector, tinycents));
            require(success);
            tinybars = abi.decode(result, (uint256));
        }
    
        modifier costsCents(uint256 cents) {
            uint256 tinycents = cents * TINY_PARTS_PER_WHOLE;
            uint256 requiredTinybars = tinycentsToTinybars(tinycents);
            require(msg.value >= requiredTinybars);
            _;
        } 
    }
    

    Note that the exchange rate in 0.0.112 is NOT a live price oracle from exchanges. Instead, it’s a weighted median of the recent HBAR-USD exchange rate on major exchanges. So if you need live pricing data, the info from 0.0.112 won’t work.

    You’ll likely have to use APIs from crypto exchanges (preferably average from a few exchanges). This query can not be executed from a smart contract. This is typically executed in an external app and then that app can invoke a smart contract if the smart contract logic needs to have this information.