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

Flow Cadence交易报错:Transaction的accessory字段未失效

Flow Cadence交易报错:资源未失效问题解决

问题背景

我正在开发一款游戏,定义了存储Accessory NFT的Avatar资源,其中包含equip函数,可返回该插槽中已存在的配饰:

pub resource Avatar {
        pub let id: UInt64
        pub let accessories: @{String: Accessory}

        init() {
            self.id = Avatar.totalMinted + 1
            self.accessories <- {}

            Avatar.totalMinted = Avatar.totalMinted + 1
        }

        destroy () {
            Avatar.totalAvatars = Avatar.totalAvatars - 1
            destroy self.accessories
        }

        pub fun equip(accessory: @Accessory): @Accessory? {
            // Shift accessory into accessories dictionary and return old accessory
            let oldAccessory <- self.accessories[accessory.getAccessoryData().slot] <- accessory
            return <- oldAccessory

        }
}

随后在交易中从藏品取出配饰并装备到Avatar,同时存入插槽中可能存在的原有配饰,交易代码如下:

import Avatar from 0x03
import NonFungibleToken from 0x01
transaction(avatarId: UInt64, accessoryId: UInt64) {
    
    let collection: &Avatar.Collection
    let avatar: auth &Avatar.Avatar
    let accessory: @Avatar.Accessory

    prepare(signer: AuthAccount) {
        self.collection = signer.borrow<&Avatar.Collection>(from: Avatar.CollectionStoragePath) ?? panic("could not borrow collection")
        self.avatar = self.collection.borrowAuth(id: avatarId) as? auth &Avatar.Avatar ?? panic("problem")
        self.accessory <- self.collection.withdraw(withdrawID: accessoryId) as! @Avatar.Accessory
    }

    execute {
        if let oldAccessory <- self.avatar.equip(accessory: <- self.accessory) {
            self.collection.deposit(token: <- oldAccessory)
        }

    }
}

运行后出现报错:
field accessory of type Transaction is not invalidated (moved or destroyed). not invalidated - flow cadence

猜测类型检查器未识别到资源已移交至Avatar,请问遗漏了什么关键点?

问题原因与解决方法

报错的核心原因是Flow的类型检查器要求交易中声明的所有资源字段必须被明确移动或销毁,即使你在equip函数中已经转移了资源,但当前代码的写法让检查器无法确认这一点。

具体问题点

在execute区块的if let语句中,只有当equip函数返回非空的旧配饰时,self.accessory才会被移动;但如果equip返回nil(即该插槽原本没有配饰),self.accessory就没有被移动,导致交易结束时这个资源字段仍未失效,触发报错。

修复方案

修改execute区块的代码,确保无论equip是否返回旧配饰,self.accessory都会被明确移动:

execute {
    // 先执行equip,强制移动self.accessory
    let oldAccessory <- self.avatar.equip(accessory: <- self.accessory)
    // 再处理返回的旧配饰
    if let oldAccessory = oldAccessory {
        self.collection.deposit(token: <- oldAccessory)
    }
}

原理说明

把equip的调用和条件判断分开后,不管返回值是否为nil,self.accessory都会被移动到equip函数中,类型检查器能明确识别到这个资源已经被移交,不会再触发未失效的报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:51:34