You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NEAR协议批量铸造NFT触发存储费用错误,如何实现铸币成本支付?

问题描述

Rust合约方法

#[payable]
pub fn nft_mint(&mut self, nft_list: Vec<Nft>) -> Vec<Token> {
    let mut t_result: Vec<Token> = Vec::new();
    for nft in nft_list {
        let s = self.tokens.mint(nft.token_id, nft.receiver_id, Some(nft.token_metadata));
        t_result.push(s);
    }
    return t_result;
}

前端调用代码

let token_list = [{
    token_id: nanoid(),
    receiver_id: window.accountId,
    token_metadata: { id: i, title: "test", myNumber: 123, price: 10, url: "http://..."}
}];

window.contract
  .nft_mint({ nft_list: token_list })
  .then((res) => {
    console.log("Success", res);
  }).catch(err => {
    console.log("Error", err);
  });

触发的错误

{
"type": "action",
"error": {
"type": "functionCallError",
"error": {
"type": "executionError",
"error": "Smart contract panicked: panicked at 'Must attach 6290000000000000000000 yoctoNEAR to cover storage',
/home/HideThePainHarold/.cargo/registry/src/github.com-1ecass99db9ec823/near-contract-standards-3.2.0/src/non_fungible_token/utils.rs:33:5"
}
}
}

咨询问题

  1. 如何解决该存储费用错误?
  2. 如何让调用者支付实际铸币费用(而非仅Gas费用)?

解决方案

1. 解决存储费用错误

NEAR链上存储需要支付成本,错误提示已明确要求附加6290000000000000000000 yoctoNEAR(即0.00629 NEAR)覆盖存储。只需在前端调用时指定附加金额即可:

修改前端调用代码,添加attachedDeposit参数:

window.contract
  .nft_mint({ nft_list: token_list }, {
    attachedDeposit: "6290000000000000000000" // 对应错误提示的存储费用金额
  })
  .then((res) => {
    console.log("Success", res);
  }).catch(err => {
    console.log("Error", err);
  });

如果需要支持动态批量铸币,也可以在合约中先计算所需存储费用,再验证调用者附加的存款是否足够:

// 在nft_mint方法内,遍历前先计算总存储成本
let total_storage_cost = nft_list.iter()
    .map(|nft| self.tokens.storage_cost_to_mint(Some(&nft.token_metadata)))
    .sum::<u128>();

assert!(env::attached_deposit() >= total_storage_cost, "Insufficient deposit for storage, need {} yoctoNEAR", total_storage_cost);

2. 让调用者支付实际铸币费用

可以通过两种方式实现,核心是让调用者附加包含铸币费的存款,并在合约中处理费用转移:

方式一:前端直接附加总费用

在调用时,将存储费和预设的铸币费相加后作为附加金额传递。比如铸币费设为0.1 NEAR,总金额为0.1 + 0.00629 = 0.10629 NEAR(即106290000000000000000000 yoctoNEAR):

window.contract
  .nft_mint({ nft_list: token_list }, {
    attachedDeposit: "106290000000000000000000" // 存储费+铸币费总和
  })
  .then((res) => {
    console.log("Success", res);
  }).catch(err => {
    console.log("Error", err);
  });

方式二:合约内强制收取铸币费

在合约中定义铸币单价,验证调用者附加的存款是否覆盖存储费+铸币费,再将铸币费转移到合约所有者账户:

use near_sdk::{env, AccountId, Promise};

#[payable]
pub fn nft_mint(&mut self, nft_list: Vec<Nft>) -> Vec<Token> {
    let mut t_result: Vec<Token> = Vec::new();
    // 定义单个NFT的铸币费(0.1 NEAR)
    let mint_fee_per_nft = 100000000000000000000000;
    let nft_count = nft_list.len() as u128;

    // 计算总费用:铸币费总和 + 存储费总和
    let total_storage_cost = nft_list.iter()
        .map(|nft| self.tokens.storage_cost_to_mint(Some(&nft.token_metadata)))
        .sum::<u128>();
    let total_required = total_storage_cost + (nft_count * mint_fee_per_nft);

    // 验证附加存款是否足够
    assert!(env::attached_deposit() >= total_required, "Must attach {} yoctoNEAR to cover mint and storage fees", total_required);

    // 批量铸币
    for nft in nft_list {
        let s = self.tokens.mint(nft.token_id, nft.receiver_id, Some(nft.token_metadata));
        t_result.push(s);
    }

    // 将铸币费转移到合约所有者账户
    let owner_id: AccountId = "your-owner-account.near".parse().unwrap();
    Promise::new(owner_id).transfer(nft_count * mint_fee_per_nft);

    return t_result;
}

内容的提问来源于stack exchange,提问作者Suisse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 22:50:27