同一个合约是否可以处理多个 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()
?
具体来说,您是否可以说在这些方法的签名中添加一个额外的参数来帮助指明您要查询的特定令牌?
例如,而不是这个:
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()
做类似的事情吗?
这是允许的吗? 这是否是解决这个问题的正确方法 - 或者是否有不同的方法来推理所有这些并以不同的方式处理它?</p>
答案 0 :(得分:1)
我的方法是在 3 个单独的地址上定义 3 个单独的合约:
0x123123
作为武器 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;
}