Band Protocol 预言机集成

介绍如何在 TRON 上集成 Band Protocol 去中心化预言机,获取链下价格喂价数据。

Band Protocol 预言机集成

TRON 上的智能合约可以借助 Band Protocol 的去中心化预言机获取现实世界的链下数据。最典型的场景是把各类加密资产的价格喂价接入去中心化金融(DeFi)应用。


桥接合约架构

要把 Band 预言机数据集成进应用,通过 Band Protocol 的**桥接合约(Bridge Contract)**实现。该合约已部署在 TRON 测试网,地址为 TPxsemS7h9rrJPZAPDjP7rmLoA4ErYny69,Solidity 源码可在 BandChain 的 GitHub 仓库获取。

价格数据来自 BandChain 上发起的数据请求。BandChain 验证者节点从 CoinGecko、CryptoCompare、 TRON 网络、Alpha Vantage API 等多个数据源取数,计算中位数(Median)得出价格。每次请求都执行特定的价格聚合预言机脚本,脚本源码可在 BandChain 开发者网络(Devnet)查看。

Band 部署在 TRON 上的桥接合约定期获取这些请求结果,写入合约状态变量,供外界调用。


可用价格喂价数据 (Shasta 测试网)

测试网桥接合约目前存储以下价格对,每 5 分钟自动更新一次,支持列表与数据源如下:

1. 加密货币价格对 (数据源: CoinGecko、CryptoCompare、Binance)

  • BTC/USD
  • ETH/USD
  • TRX/USD
  • BAND/USD

2. 大宗商品价格对 (数据源: Alpha Vantage)

  • XAU/USD (黄金)
  • XAG/USD (白银)

3. 外汇汇率对 (数据源: Alpha Vantage)

  • EUR/USD (欧元)
  • CNY/USD (人民币)
  • JPY/USD (日元)
  • GBP/USD (英镑)
  • KRW/USD (韩元)

除最新价格外,调用方还能从桥接合约获取以下辅助安全参数:

  • 数据精度乘数 (Multiplier):用于放大存储价格精度的十进制乘数。
  • 数据更新时间戳:该特定价格请求在 BandChain 上被解析完成并写入本桥接合约的 Unix 时间戳。
📘

说明

这些参数帮助调用方判断喂价是否在有效期内、数据是否仍然有效,从而防范延迟攻击和过期(stale)数据。


桥接合约数据更新维护

为方便社区开发测试,Band 基金会维护并定期更新上述测试网桥接合约的价格数据。生产环境中,开发者可参考 Band 文档,自行部署桥接合约以订阅所需数据源。


获取并使用价格数据 (Solidity 代码范例)

下面用一个简单的价格库合约 SimplePriceDB 演示如何从已部署的 Band 预言机桥接合约读取最新 BTC/USD 价格:

pragma solidity 0.5.9;
pragma experimental ABIEncoderV2;

import "./Obi.sol";
import {IBridge, IBridgeCache} from "./IBridgeWithCache.sol";
import {ParamsDecoder, ResultDecoder} from "./Decoders.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";

contract SimplePriceDB {
    using SafeMath for uint256;
    using ResultDecoder for bytes;
    using ParamsDecoder for bytes;
    
    IBridgeCache public bridge;
    IBridge.RequestPacket public req;
    
    uint256 public current_price;

    constructor(IBridgeCache bridge_) public {
        bridge = bridge_;
        
        req.clientId = "tron_testnet";
        req.oracleScriptId = 76;
        // OBI 编码后的 {"symbol":"BTC"} 参数:hex"00000003425443"
        req.params = hex"00000003425443";
        req.askCount = 4;
        req.minCount = 3;
    }

    // 从 TRON 上的桥接合约获取最新的 BTC/USD 价格并写入本合约状态变量中
    function setPrice() public {
        IBridge.ResponsePacket memory res = bridge.getLatestResponse(req);
        ResultDecoder.Result memory result = res.result.decodeResult();
        current_price = result.px;
    }
}

1. 引入依赖文件说明

除标准的 SafeMath.sol 外,与 Band 预言机交互还需导入三个专用接口与编码工具文件:

  • Obi.sol:包含一组 OBI(Oracle Binary Encoding)函数,用于对与 BandChain 交互时的二进制数据进行序列化与反序列化。详见 BandChain OBI Wiki
  • Decoders.sol:辅助解码工具类,用于从预言机的响应报文中提取出结构化的价格数据(px)。
  • IBridgeWithCache.sol:Band 预言机部署在 TRON 上的桥接合约接口。

2. 合约初始化参数说明 (Constructor)

构造函数传入桥接合约的部署地址,并初始化结构体 reqRequestPacket)的各项键值。本示例中各配置项含义如下:

  • clientId ("tron_testnet"):由客户端自定义的预言机请求唯一标识符。
  • oracleScriptId (76):该价格聚合脚本在 BandChain 注册时分配的预言机脚本唯一 ID。
  • params (hex"00000003425443"):序列化后的参数,此处表示查询 "BTC"
  • askCount (4):请求指定的验证者节点数量。
  • minCount (3):为了通过去信任化共识,执行本请求所需的最少验证者响应数量。minCount 必须小于或等于 askCount

各可用资产的价格对 Params 参数对照表如下:

价格资产对传入参数的十六进制 (Params Hex)
BTC/USDhex"00000003425443"
ETH/USDhex"00000003455448"
TRX/USDhex"00000003545258"
BAND/USDhex"0000000442414e44"
XAU/USDhex"00000003584155"
XAG/USDhex"00000003584147"
EUR/USDhex"00000003455552"
CNY/USDhex"00000003434e59"
JPY/USDhex"000000034a5059"
GBP/USDhex"00000003474250"
KRW/USDhex"000000034b5257"

3. 数据更新函数说明 (setPrice)

这是与预言机交互的核心方法:内部调用桥接合约的 getLatestResponse(req),传入构造函数中初始化好的请求结构体;再用导入的解码库解析响应数据,把最新 BTC/USD 价格赋给状态变量 current_price