【问题标题】:Handling multiple ERC721 Tokens in the same Contract在同一个合约中处理多个 ERC721 代币
【发布时间】:2021-02-18 23:53:38
【问题描述】:

同一个合约可以处理多个ERC721 代币吗?如果有,怎么做?

假设您正在制作一款游戏,您需要跟踪两种类型的ERC721 令牌:独特的武器和独特的车辆。

您可以为它们创建结构体,如下所示:

struct Weapon { 
    uint256 IDNumber;
    string type; // Sword, Bow&Arrow, Gun, Rifle, etc.  
    string specialFeature; 
}


struct Vehicle { 
    uint256 IDNumber;
    string type;  // Car, Airplane, Boat, Spaceship, etc.  
    uint256 damageFactor; 
}

要跟踪它们的所有权,您可以将管理它们的数组加倍 - 例如,而不是使用标准:

// Enumerable mapping from token ids to their owners
EnumerableMap.UintToAddressMap private _tokenOwners;

你会这样做:

// Enumerable mapping from token ids to their owners
EnumerableMap.UintToAddressMap private _weaponTokenOwners;
EnumerableMap.UintToAddressMap private _vehicleTtokenOwners;

(这可能不是最优雅的方式,但它是一个开始。)

但真正的问题是:您将如何处理属于ERC721 标准的强制函数,例如balanceOf() 和ownerOf()?

具体来说,您是否可以说在这些方法的签名中添加一个额外的参数,以帮助指示您查询的是哪个特定的 Token?

例如,而不是这个:

function balanceOf(address owner) public view override returns (uint256) {

}

您需要在函数的签名中添加一个tokenName 参数,如下所示:

function balanceOf(address owner, string tokenName) public view override returns (uint256) {
    if(tokenName == “weapon”) {
       return ownerAndHisWeaponTokensDictionary[owner].length;
    }
    else if(tokenName == “vehicle”) {
       return ownerAndHisVehicleTokensDictionary[owner].length;
    }
}

你会为ownerOf()做类似的事情吗?

这是允许的吗? 这甚至是解决这个问题的正确方法 - 还是有不同的方法来推理所有这些并以不同的方式处理它?

【问题讨论】:

    标签: blockchain ethereum tokenize solidity


    【解决方案1】:

    我的方法是在 3 个单独的地址上定义 3 个单独的合约:

    • 地址 0x123123 作为 Weapons ERC-721 代币合约
    • 地址 0x456456 作为 Vehicles ERC-721 代币合约
    • 地址0x789789作为实际游戏合约

    在游戏合约中,你可以调用 NFTs 合约来获取或验证值:

    function attack(uint attackerWeaponId) {
        require(weaponsContract.isOwnerOf(msg.sender, attackerWeaponId));
        // ...
    }
    

    isOwnerOf() 函数有 2 个参数,address owner 和 uint256 weaponId。此外,用户可能拥有更多武器,这就是我展示验证的原因。

    武器合约balanceOf(address) 将反映用户拥有的武器 NFT 总量。

    mapping (address => Weapon[]) userOwnedWeapons;
    
    function balanceOf(address owner) external view returns (uint256) {
        return userOwnedWeapons[msg.sender].length;
    }
    

    【讨论】:

    • 这很有趣。我考虑过将所有内容拆分为不同合同的选项,但似乎很头疼。或者它可能会很快失控,你最终会得到十几个合同——甚至更多,很快……那么你熟悉采用这种方法的合同/项目吗?你能举个例子吗?我很想在Etherscan 上查找他们的代码。
    • 顺便说一句,您是否确认我们确实不允许通过添加其他参数来更改 ownerOf() 和 balanceOf() 等方法的签名,正如我在原始问题中所建议的那样?
    • 您可以在技术上更改方法签名,但是它们不会遵循 ERC-721 标准(这可能就是您所说的“不允许”的意思)。所以我强烈反对...我的回答是基于观察和编写 ERC-20 的实现,你也看不到很多定义 2+ 代币的合约(即使出于实际原因,Etherscan 和其他区块链浏览器不会在同一个合约中识别 2+ 代币) .
    • 好的,知道了。说得通。是的,当我说“不允许”时,我的意思是,如果您愿意,您当然可以 更改方法签名——但是您将不再符合 ERC721 标准。我将继续研究这一点——希望其他人能提出他们的建议,因为它可能对其他人有用。再次感谢!
    • 您建议将每个 ERC721 放在自己单独的外部部署合约中,然后让 GameContract 引用这些合约,如果您想在游戏中添加另一个元素怎么办?所以你已经有了Weapons和Vehicles,现在你想添加Potions。有没有办法设计您的GameContract,使其能够接受新元素/ERC721 合同和代币,以便您继续发展?
    猜你喜欢
    • 2019-01-15
    • 2022-12-05
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    相关资源
    最近更新 更多