如何解决如何检查NEAR帐户是否已部署智能合约并实现了所需的接口? 解决方法注意:
是否有一种方法可以检查(在Rust中)智能合约内部,是否另一个帐户具有与其关联的智能合约并实现了某些接口?
尤其是在此功能中,我想检查收件人是否是智能合约,以及它是否具有必需的方法:
trait FTReceiver {
fn on_nft_receive(&self,sender: AddressID,token: AddressID) -> bool;
}
pub fn transfer(&mut self,recipient: AccountID,reference: String) {
// note: env::* functions below don't exist!
if env::has_smart_contract(recipient) && env::ctr_implements(recipient,FTReceiver) {
Promise::new(token.clone()).function_call(
"on_ft_receive".into(),&serde_json::to_vec(&json!({
"sender": env::predecessor_account_id() /*...*/
})),);
}
}
解决方法
检查的唯一方法是尝试失败方法:
- 打个电话
- 设计足够的回调/保证处理失败情况。
不幸的是,这很复杂,我们无法处理极端情况。我们无法以可靠的方式检查Promise
失败的原因。该承诺可能由于以下原因而失败:A)一个账户没有智能合约,B)智能合约没有被调用的函数C)函数失败(例如断言失败)。
在Simulation Tests存储库Error messages early in promise execution中描述了此限制。仿真测试使用与区块链完全相同的运行时代码。
解决方法
@ vlad-frolow注意到,我们的智能合约可以使用view
方法来报告其界面。在撰写本文时,此视图方法尚无标准。
一个主意:
pub fn implements_nep(&self,nep String) -> bool {
nep == "21" || nep == ...
}
注意:
正在进行一项工作,以检查NEAR运行时中的外部帐户。
,这是一个非常简单的示例实现:
接收器接口声明:
use near_sdk::{ AccountId,Balance,ext_contract };
use near_sdk::json_types::U128;
/* The smart contract interface for handing incoming token transfers of Advanced Fungible.
*
*/
#[ext_contract(ext_token_receiver)]
pub trait Receiver {
/// Interface check promise to check if the receiver contract is able to handle Advanced Fungible
/// Always return true
fn is_receiver(self) -> PromiseOrValue<bool>;
/// Notified after the balance transfer is complete. Must return true to finalise the transaction.
/// TODO: More advanced error code / return value needed
fn on_token_received(&mut self,sender_id: AccountId,amount_received: U128,amount_total: U128,message: Vec<u8>) -> PromiseOrValue<bool>;
}
然后检查接口是否已实现:
let promise0 = env::promise_create(
new_owner_id.clone(),b"is_receiver",&[],SINGLE_CALL_GAS/3,);
let promise1 = env::promise_then(
promise0,env::current_account_id(),b"handle_receiver",json!({
"old_owner_id": owner_id,"new_owner_id": new_owner_id,"amount_received": amount.to_string(),"amount_total": new_target_balance.to_string(),"message": message,}).to_string().as_bytes(),);
env::promise_return(promise1);
然后根据通话结果采取措施:
/**
* After trying to call receiving smart contract if it reports it can receive tokens.
*
* We gpt the interface test promise back. If the account was not smart contract,finalise the transaction.
* Otherwise trigger the smart contract notifier.
*/
pub fn handle_receiver(&mut self,old_owner_id: AccountId,new_owner_id: AccountId,message: Vec<u8>) {
// Only callable by self
assert_eq!(env::current_account_id(),env::predecessor_account_id());
env::log(b"handle_receiver reached");
let uint_amount_received: u128 = amount_received.into();
let uint_amount_total: u128 = amount_total.into();
if is_promise_success() {
// The send() was destined to a compatible receiver smart contract.
// Build another promise that notifies the smart contract
// that is has received new tokens.
} else {
// Non-code account or incompatible smart contract
// Finalise transaction now.
self.ledger.finalise(new_owner_id,uint_amount_received);
}
}
完整代码:https://github.com/miohtama/advanced-fungible/blob/master/contract/token/src/receiver.rs
最理想的是,NEAR应该在promise链中提供一个分支原语,以便可以从一开始就建立条件链,并且在进行接口检查之后,可以减少往返原始呼叫者合同的时间。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。