谁是 nft_transfer_call 中的接收者?

Posted

技术标签:

【中文标题】谁是 nft_transfer_call 中的接收者?【英文标题】:Who is the receiver in a nft_transfer_call? 【发布时间】:2021-10-08 15:06:46 【问题描述】:

我有一个NFT 合约和一个Market 部署它。 我没有使用nft_transfer_call 接受出价,但现在将其添加。 在NFT/Media 所有者接受投标的情况下,当前实施的流程是:

    调用 [nft-contract].accept_bid(token_id, bidder) 开始跨合约调用 [market-contract].xcc_market_accept_bid(token_id, bidder, design.creator, design.owner_id, design.prev_owner) 市场负责支付股票、取消出价和回调NFT [nft-contract].xcc_media_nft_transfer(token_id, receiver_id) 将招式NFT/Media 转让给新的所有者和结局!

我知道这不是正确的方法,因为我应该使用 nft_transfer_call,根据标准,这就是我理解的上述调用的方式:

[nft-contract].nft_transfer_call(
  "receiver_id": $market_address, ? or $bidder
  "token_id": $token_id,
  "msg": "$token_id $bidder $creator $owner_id $prev_owner"
)

应该在内部传输令牌然后触发:

[market-contract].nft_on_transfer(
  "sender_id": $sender_of_nft_transfer_call,
  "previous_owner_id": $get_media_prev_owner_from_store,
  "token_id": $token_id_passed_by_front_end,
  "msg": "$token_id $bidder $creator $owner_id $prev_owner", // parameters for Market contract
)

分配支出、更新新股并最终回调:

[nft-contract].nft_resolve_transfer(
  "sender_id": $sender_of_nft_transfer_call,
  "receiver_id":  $market_address, ? or $bidder,
  "token_id": $token_id,
)

问题是在这种情况下receiver_id 是谁(市场还是新所有者)?我知道审批管理标准在这里可能是更好的解决方案,但我试图保持简单并通过转接电话解决它。


Market interface

【问题讨论】:

【参考方案1】:

如果我正确阅读了您的代码,bidder 是两个函数中receiver_id 的值。来自 [docs][1]:

// * `receiver_id`: the valid NEAR account receiving the token
// Arguments:
// * `receiver_id`: the valid NEAR account receiving the token.
// * `token_id`: the token to send.
// * `approval_id`: expected approval ID. A number smaller than
//    2^53, and therefore representable as JSON. See Approval Management
//    standard for full explanation.
// * `memo` (optional): for use cases that may benefit from indexing or
//    providing information for a transfer.
// * `msg`: specifies information needed by the receiving contract in
//    order to properly handle the transfer. Can indicate both a function to
//    call and the parameters to pass to that function.
function nft_transfer_call(
  receiver_id: string,
  token_id: string,
  approval_id: number|null,
  memo: string|null,
  msg: string,
): Promise 

应该匹配nft_resolve_transfer()中的参数

// * `receiver_id`: the `receiver_id` argument given to `nft_transfer_call`
    // Arguments:
// * `sender_id`: the sender of `ft_transfer_call`
// * `receiver_id`: the `receiver_id` argument given to `nft_transfer_call`
// * `token_id`: the `token_id` argument given to `ft_transfer_call`
// * `approved_token_ids`: if using Approval Management, contract MUST provide
//   set of original approved accounts in this argument, and restore these
//   approved accounts in case of revert.
//
// Returns true if token was successfully transferred to `receiver_id`.
function nft_resolve_transfer(
  owner_id: string,
  receiver_id: string,
  token_id: string,
  approved_account_ids: null|string[],
): boolean 


  [1]: https://nomicon.io/Standards/NonFungibleToken/Core.html

【讨论】:

这是正确的。我注意到在这些 cmets 中阅读代码并不容易,因此我将在单独的答案中进行扩展。对于可能会发现这一点的人,请注意 BenTheHumanMan 在这里引用了 Nomicon 规范文档:nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface【参考方案2】:

正如 BenTheHumanMan 所说,receiver_id 将是相同的。

这是来自 Rust 示例的 sn-p:

fn nft_transfer_call(
    &mut self,
    receiver_id: AccountId,
    token_id: TokenId,
    approval_id: Option<u64>,
    memo: Option<String>,
    msg: String,
) -> PromiseOrValue<bool> 
    assert_one_yocto();
    let sender_id = env::predecessor_account_id();
    let (old_owner, old_approvals) =
        self.internal_transfer(&sender_id, &receiver_id, &token_id, approval_id, memo);
    // Initiating receiver's call and the callback
    ext_receiver::nft_on_transfer(
        sender_id.clone(),
        old_owner.clone(),
        token_id.clone(),
        msg,
        &receiver_id,
        NO_DEPOSIT,
        env::prepaid_gas() - GAS_FOR_FT_TRANSFER_CALL,
    )
    .then(ext_self::nft_resolve_transfer(
        old_owner,
        receiver_id,
        token_id,
        old_approvals,
        &env::current_account_id(),
        NO_DEPOSIT,
        GAS_FOR_RESOLVE_TRANSFER,
    ))
    .into()

请注意,我们使用的是最初提供给函数的 receiver_id,然后将其传递给回调 (nft_resolve_transfer)。

但也许为了更直接地回答您的问题……如果您让人们对 NFT 进行投标,则可能不需要使用转接和呼叫功能。在不了解出价如何运作的详细信息的情况下,我认为您说得对,批准更合适。

有一个示例in Nomicon 可能会有所帮助。请注意,这链接到可替代令牌而不是不可替代令牌,因为我相信这更容易理解。链接页面涉及以下场景:

Alice 需要发出 1 笔交易,而典型的托管工作流程则需要 2 笔。

简而言之……假设我想为一项服务支付 5 个可替代代币,比如说一个预言机。我向一个预言机合约支付了 5 个可替代代币,作为回报,他们会存储我的请求,这可能会被链下服务接收并响应。

为了:

    发送我的链下服务请求 发送可替代代币

使用审批系统的典型工作流程是:

    我允许预言机从我这里拿走 5 个可替代代币。 我发送了一个请求,预言机试图从我这里拿走这 5 个可替代令牌。 如果成功,则存储请求,如果不成功,则显示“您需要允许我从您那里取 5 个令牌”

这不是很好,需要多次交易。在这种情况下,我可以使用转接和呼叫功能来简化它。它基本上会说,“嘿,可替代代币合约,将 5 个代币转移到预言机,然后根据我在 msg 参数中提供的额外信息发送它们。” (也许msg 包含诸如我有什么类型的请求、请求详细信息、我不再需要链下响应等多长时间等信息。)


退出可替代令牌示例,同样的事情也适用于不可替代令牌。转接呼叫的用例不太简单,可能无法满足所有需求。

请参阅NFT Approval Management standard spec 了解有关该方法的更多详细信息,这可能是您想要的拍卖方式。

【讨论】:

以上是关于谁是 nft_transfer_call 中的接收者?的主要内容,如果未能解决你的问题,请参考以下文章

谁是面向对象设计中的霸主?(中)

如何悲观锁然后无限期地持有以跟踪谁是集群中的主人?

1. 谁是照片picture VS photograph?

Spark PK Hadoop 谁是赢家?

谁是你的创业竞争对手?

QT:QActionGroup加入QMenu后,谁是QActionGroup成员的父母?