我的智能合约或应用程序如何从 Hedera 网络(Hedera 文件服务)上的文件访问 USD/HBAR 汇率信息?
我感兴趣的文件是0.0.112。我尝试从我的应用程序中使用 SDK 进行查询,它似乎为我提供了信息,但我如何在合同中使用它以及该价格信息的实时性如何?
async function main() {
const fileQuery = new FileContentsQuery().setFileId("0.0.112");
const contents = await fileQuery.execute(client);
console.log(contents.toString());
}
main();
您正朝着正确的方向前进。几点:
正如您所发现的,外部应用程序只需使用 SDK 执行 FileContentsQuery() 即可访问 0.0.112 的汇率。您还可以使用此镜像 REST API 调用 (https://mainnet-public.mirrornode.hedera.com/api/v1/network/exchangerate),它还会公开 HFS 文件中的汇率信息。
如果您需要在智能合约中访问 0.0.112 的汇率信息,那么我建议查看 HIP-475 (https://hips.hedera.com/hip/hip-475),所以你可能会得到类似的结果:
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);
_;
}
}
请注意,0.0.112 中的汇率不是来自交易所的实时价格预言机。相反,它是主要交易所近期 HBAR 兑美元汇率的加权中位数。因此,如果您需要实时定价数据,0.0.112 中的信息将不起作用。
您可能需要使用加密货币交易所的 API(最好是几个交易所的平均值)。该查询无法从智能合约执行。这通常在外部应用程序中执行,然后如果智能合约逻辑需要此信息,则该应用程序可以调用智能合约。
更新的答案,对于较新的 Solidity 版本,还使用 HIP-475 的汇率系统合约, 可以在
0x168
获得,界面如下:
interface IExchangeRate {
function tinycentsToTinybars(uint256 tinycents) external returns (uint256);
function tinybarsToTinycents(uint256 tinybars) external returns (uint256);
}
只要您的用例确实需要高度的准确性或“活跃度”, 这可以很好地完成转换。
以下示例演示如何使用汇率系统合约 从 USD 美分转换为 HBAR 美分。
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;
interface IExchangeRate {
// Given a value in tinycents (1e-8 US cents or 1e-10 USD), returns the
// equivalent value in tinybars (1e-8 HBAR) at the current exchange rate
// stored in system file 0.0.112.
//
// This rate is a weighted median of the the recent" HBAR-USD exchange
// rate on major exchanges, but should _not_ be treated as a live price
// oracle! It is important primarily because the network will use it to
// compute the tinybar fees for the active transaction.
//
// So a "self-funding" contract can use this rate to compute how much
// tinybar its users must send to cover the Hedera fees for the transaction.
function tinycentsToTinybars(uint256 tinycents) external returns (uint256);
// Given a value in tinybars (1e-8 HBAR), returns the equivalent value in
// tinycents (1e-8 US cents or 1e-10 USD) at the current exchange rate
// stored in system file 0.0.112.
//
// This rate tracks the the HBAR-USD rate on public exchanges, but
// should _not_ be treated as a live price oracle! This conversion is
// less likely to be needed than the above conversion from tinycent to
// tinybars, but we include it for completeness.
function tinybarsToTinycents(uint256 tinybars) external returns (uint256);
}
contract Exchange {
IExchangeRate constant ExchangeRate =
IExchangeRate(address(0x168));
event ConversionResult(uint256 inAmount, uint256 outAmount);
function convert(uint256 usdCents) external returns (uint256 hbarCents) {
hbarCents = ExchangeRate.tinycentsToTinybars(usdCents * 100_000_000) / 1_000_000;
emit ConversionResult(usdCents, hbarCents);
}
}
请注意,截至撰写本文时,1,000.00 美元等于 19,584.80 HBAR。
但是,输入 100,000 (
usdCents
) 会返回 1,969,667 (hbarCents
) 的输出,
大约是实时价值的 0.6% 折扣。
所以不要在 DEX 或类似的东西中使用它。
const fileQuery = new FileContentsQuery().setFileId("0.0.112");
const contents = await fileQuery.execute(client);
const exchangeRate = ExchangeRates.fromBytes(contents);
console.log('Exchange rate is ', exchangeRate);