欢迎来到系列文章「Cairo学习专题」第十课!在上一课中,我们使用 Protostar 编写了第一个单元测试,今天我们将学习与 Empiric 预言机域间通信。
像往常一样,如果你是中途加入,建议从头开始看我们的文章。
区块链预言机 (Blockchain Oracle)
区块链预言机是个难以理解的概念尤其是那些初次听说的人们,今天就让我们深入了解。
在希腊神话中,预言家是有特殊能力的人,也被称为祭司,他们拥有与神灵或精神境界互动和交流的能力。他们经常被当作神灵的传声筒,作为了解神灵的想法的唯一方式。
当把预言机概念应用于区块链时,我们就得到了区块链预言机,那么能否将其理解为区块链预言机启用跨领域通信呢?
让我们继续深入研究。
区块链是确定性的
区块链被设定为确定性的,区块链被建立成一个独立的系统(想象没有互联网连接的计算机),并就其分类帐中的数据达成共识。
尽管它在某些方面发挥了重要作用,如有助于区块链获得高度的准确性或确定性,从而使其成为无需信任的系统,但它对智能合约的实现提出了很多限制。
大规模采用是我们所期盼的核心目标之一,当我们无法与外界交互时怎么实现这一目标呢?金融智能合约需要市场信息来确定结算,保险智能合约需要物联网 (Internet of Things) 等。
最大的问题是如何在不牺牲区块链确定性的前提下与外界交互?当然不能只依靠一个中心化实体来提供信息,这否定了去中心化的核心原则,因为中心化实体可能遭遇突发停电,或被破坏的情况。
这些正是区块链预言机试图解决的问题,为区块链上的智能合约运行提供去中心化的方式,使其能在不牺牲区块链确定性的前提下与外界有效交互。
阅读 Chainlink 文章深入了解预言机如何工作。
Empiric — 在 StarkNet 上重塑预言机
就像 Chainlink 解决了以太坊预言机难题,Empiric 也在尝试解决 StarkNet 预言机问题。
利用 ZK 技术创建起一个透明公开、可组合、去中心化的架构。
今天我们深入学习预言机,查看其是如何运行的,并利用 Empiric 的喂价功能来构建第一个混合智能合约 (Hybrid Smart Contract)。
准备工作
首先需要用 Protostar 建立本地环境。
项目描述
构建一个利于用户获取 BTC、ETH 和 SOL 代币价格的简易项目。
必要条件
具备编写 StarkNet 合约的基础知识。
项目初始化
Protostar 设置完后,通过以下指令运行新项目:
protostar init
完成后,按照要求输入项目名称和库名称成功创建一个新项目。
编写合约
部署 StarkNet 合约中概述了大部分代码和流程,在此只讲解部分代码。
导入
%lang starknetfrom starkware.cairo.common.cairo_builtins import HashBuiltin
常量
const EMPIRIC_ORACLE_ADDRESS =
0x012fadd18ec1a23a160cc46981400160fbf4a7a5eed156c4669e39807265bcd4;
const ETH_KEY = 28556963469423460;
const BTC_KEY = 27712517064455012;
const SOL_KEY = 32492132765102948;
const AGGREGATION_MODE = 120282243752302; // str_to_felt("median")
定义合约中所需的五个常量:
EMPIRIC_ORACLE_ADDRESS:指定部署 Empiric 合约地址。
ETH_KEY:eth/usd 小写 utf8 编码字符串。作为一个指针来通知预言机你需要什么交易对。
BTC_KEY:btc/usd 小写 utf8 编码字符串
SOL_KEY:sol/usd 小写 utf8 编码字符串。
AGGREGATION_MODE:指定聚合过程获取数据。目前仅支持中值聚合模式 (Median Aggregation Mode),因此我们将字符串 median 转换为 felt,并将其作为参数传输给预言机。
合约接口
@contract_interface
namespace IEmpiricOracle{
func get_value(key : felt, aggregation_mode : felt) -> (
value : felt,
decimals : felt,
last_updated_timestamp : felt,
num_sources_aggregated : felt
){
}
}
用于与外部合约交互的 Cairo 接口。创建一个包含了我们想要交互的 get_value 函数接口 IEmpiricOracle。
该函数接受键(指定期望价格)和聚合模式,可返回值、小数位数、最新时间戳和聚合源数。
获取比特币资产价格
@view
func btc_price{syscall_ptr : felt, pedersen_ptr : HashBuiltin, range_check_ptr}() -> (price: felt){
let (
price,
decimals,
last_updated_timestamp,
num_sources_aggregated
) = IEmpiricOracle.get_value(
EMPIRIC_ORACLE_ADDRESS, BTC_KEY, AGGREGATION_MODE
);
return (price,);
}
在指定了所有常量以及合约接口后,开始创建第一个视图函数,他能返回比特币的美元价格。
上述可见我们使用指定的接口调用 Empiric 预言机的 get_value 函数,传入三个参数并不是预期的两个参数。这是因为当我们使用接口调用外部合约时,必须将该合约的地址作为第一个参数。
然后从 Empiric 返回资产价格。
获取以太坊资产价格
@view
func eth_price{syscall_ptr : felt, pedersen_ptr : HashBuiltin, range_check_ptr}() -> (price: felt){
let (
price,
decimals,
last_updated_timestamp,
num_sources_aggregated
) = IEmpiricOracle.get_value(
EMPIRIC_ORACLE_ADDRESS, ETH_KEY, AGGREGATION_MODE
);
return (price,);
}
这一步要求我们用不同的键重复上述比特币步骤。
获取 Solana 资产价格
@view
func sol_price{syscall_ptr : felt, pedersen_ptr : HashBuiltin, range_check_ptr}() -> (price: felt){
let (
price,
decimals,
last_updated_timestamp,
num_sources_aggregated
) = IEmpiricOracle.get_value(
EMPIRIC_ORACLE_ADDRESS, SOL_KEY, AGGREGATION_MODE
);
return (price,);
}
部署合约
运行 Protostar 部署命令,传入测试网:
protostar deploy ./build/main.json --network testnet
部署完成后,我们可以在屏幕上看到合约地址和交易哈希,可以在 Voyager 上复制并与之交互。
从 Voyager 读取资产价格
完成合约部署后,我们可以通过 Voyager 与其交互。
首先调用 btc_price 函数:
其次是以太坊价格:
最后调用 Solana 价格:
你可以观察到他返回了 BTC、ETH 和 SOL 的价格(为本文撰写时价格)。
注意数字串的长度是 18 位小数。
最后
恭喜你已经完成了区块链预言机的域间通信!阅读 Maksimjeet Chowdhary 文章更深入了解预言机。
此外,Empiric 还提供更多资产价格信息,查看 Empiric 文档尝试构建更多,请注意部署前一定仔细检查预言机地址。
PS: Empiric 新宣布 VRF 功能,保持关注,未来将发布新功能指南文章。如果觉得本教程对你有帮助,转发分享给其他人吧~
本文由 wzabing 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。