Blockchain 在同一合同中处理多个ERC721代币

Blockchain 在同一合同中处理多个ERC721代币,blockchain,ethereum,tokenize,solidity,Blockchain,Ethereum,Tokenize,Solidity,同一合同是否可以处理多个ERC721代币?如果是,怎么做 假设您正在制作一个游戏,您需要跟踪两种类型的ERC721代币:独特武器和独特车辆 您可以为它们创建结构,如下所示: struct Weapon { uint256 IDNumber; string type; // Sword, Bow&Arrow, Gun, Rifle, etc. string specialFeature; } struct Vehicle { uint256 I

同一合同是否可以处理多个
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; 
}
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;
    }
}
要跟踪它们的所有权,您可以将管理它们的阵列加倍—例如,不使用标准:

// 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()

具体来说,您是否可以说向这些方法的签名添加一个附加参数,以帮助指示您查询的特定令牌

例如,与此相反:

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

}
您需要将
tokenName
参数添加到函数的签名中,如下所示:

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; 
}
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()
,您会做类似的事情吗

这是允许的吗?
这是解决这一问题的正确方法吗?还是有一种不同的方式对所有这些问题进行推理并以不同的方式进行处理?

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

  • 地址
    0x123123
    作为武器ERC-721代币合同
  • 地址
    0x456456
    为车辆ERC-721代币合同
  • 地址
    0x789789
    作为实际游戏合同
在游戏契约中,您可以调用NFTs契约来获取或验证值:

function attack(uint attackerWeaponId) {
    require(weaponsContract.isOwnerOf(msg.sender, attackerWeaponId));
    // ...
}
isOwnerOf()
函数接受两个参数,
address owner
uint256 weaponId
。另外,用户可能拥有更多的武器,这就是我展示验证的原因

武器合同
余额(地址)
将反映用户拥有的武器NFT总量

mapping (address => Weapon[]) userOwnedWeapons;

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

那很有趣。我曾考虑过将所有东西分成不同的合同,但这似乎是一个令人头痛的问题。或者它可能很快失去控制,你最终会得到十几份合同——甚至更多,很快。。。那么,您是否熟悉采用这种方法的合同/项目?你能举个例子吗?我很想在
Etherscan
上查看他们的代码。顺便问一下,你是否确认我们确实不允许通过添加额外参数来更改方法的签名,例如
ownerOf()
balanceOf()
,正如我在原始问题中所建议的那样?你可以从技术上更改方法签名,但是他们不会遵循ERC-721标准(这可能就是你所说的“不允许”的意思)。所以我强烈反对。。。我不太熟悉NFTs的实际例子,所以我不知道任何例子,但我相信如果你努力,你会找到例子的。我的答案是基于观察和编写ERC-20的实现,在那里你也看不到很多定义2+代币的合同(即使是出于实际原因,以太扫描和其他区块链探索者不会在同一合同中识别2+代币)。明白了。有道理。是的,当我说“不允许”时,我的意思是,如果你愿意,你当然可以更改方法签名——但这样你就不再符合ERC721标准了。我将继续对此进行研究——希望其他人也会赞同他们的建议,因为这可能对其他人有用。再次感谢!根据您的建议,将每个ERC721放在各自独立的外部部署合同中,然后让
GameContract
引用这些合同,如果您想在游戏中添加另一个元素,该怎么办?所以你已经有了
武器
车辆
,现在你想添加
药剂
。有没有办法设计你的
GameContract
,这样它就可以接受新元素/ERC721合约和代币,这样你就可以继续增加它?