本文介绍了如何在以太坊上实现合约间的通信,通过继承和接口,使得 ZombieFeeding 合约能够与 CryptoKitties 合约交互,实现喂养僵尸猫的功能。文章还讨论了合约优化的重要性,包括访问控制和合约地址管理,以及以太坊的可组合性。
欢迎回来,僵尸指挥官们!在我们的第一篇博文中,我们解构了 ZombieFactory
并学习了 Solidity 的基础知识。我们现在已经完成了 CryptoZombies 课程的 22%,并准备好投入到下一个激动人心的阶段:让我们的僵尸进食!
本课介绍了 Web3 开发中一些最强大的概念:合约继承、接口以及与区块链上其他合约的交互。我们还将了解对我们原始工厂所做的关键优化。
这是我们 ZombieFeeding
合约的新代码,它直接建立在我们的工厂之上。
pragma solidity >=0.5.0 <0.6.0;
import "./zombiefactory.sol"; // 导入我们之前的合约
contract KittyInterface { // 1. 定义一个接口
function getKitty(uint256 _id) external view returns (
bool isGestating,
bool isReady,
uint256 cooldownIndex,
uint256 nextActionAt,
uint256 siringWithId,
uint256 birthTime,
uint256 matronId,
uint256 sireId,
uint256 generation,
uint256 genes
);
}
contract ZombieFeeding is ZombieFactory { // 2. 继承的应用
address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
KittyInterface kittyContract = KittyInterface(ckAddress);
function feedAndMultiply(uint _zombieId, uint _targetDna, string memory _species) public {
require(msg.sender == zombieToOwner[_zombieId]); // 3. 访问控制
Zombie storage myZombie = zombies[_zombieId];
_targetDna = _targetDna % dnaModulus;
uint newDna = (myZombie.dna + _targetDna) / 2;
// 4. 特殊的 Kitty 逻辑
if (keccak256(abi.encodePacked(_species)) == keccak256(abi.encodePacked("kitty"))) {
newDna = newDna - newDna % 100 + 99;
}
_createZombie("NoName", newDna);
}
function feedOnKitty(uint _zombieId, uint _kittyId) public {
uint kittyDna;
(,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId); // 5. 调用一个外部合约
feedAndMultiply(_zombieId, kittyDna, "kitty");
}
}
在我们深入研究之前,让我们看一下对我们原始合约所做的关键安全和逻辑优化:
变更 1:private
改为 internal
:
// Before: function _createZombie(string memory _name, uint _dna) private {
// After:
function _createZombie(string memory _name, uint _dna) internal {
变更 2:添加一个 Requirement:
function createRandomZombie(string memory _name) public {
require(ownerZombieCount[msg.sender] == 0); // 新的优化
uint randDna = _generateRandomDna(_name);
randDna = randDna - randDna % 100; // 新的逻辑
_createZombie(_name, randDna);
}
require(ownerZombieCount[msg.sender] == 0)
:这是一个关键的访问控制和安全优化。它可以防止用户通过免费创建无限的僵尸军队来垃圾邮件网络。现在,一个玩家只能创建一个起始僵尸。randDna = randDna - randDna % 100
:此行确保起始僵尸的 DNA 的最后两位数字为 00
。这对于以后创建特殊的僵尸“类”非常重要,并且不会干扰我们接下来将看到的 kitty 逻辑。import "./zombiefactory.sol";
contract ZombieFeeding is ZombieFactory {
import "./zombiefactory.sol";
: 这个指令将我们第一个合约文件中的所有代码拉入这个文件中。它就像 C++ 中的 #include
。is ZombieFactory
: 这是继承。我们的 ZombieFeeding
合约是 ZombieFactory
的子合约。这意味着它可以访问其所有 public 和 internal 函数和变量(zombies
数组,dnaModulus
,_createZombie()
等)。这促进了代码重用和逻辑组织。contract KittyInterface {
function getKitty(uint256 _id) external view returns (...);
}
getKitty
函数。该接口充当承诺或蓝图,告诉我们的合约:“如果你调用一个看起来像这样的函数,外部合约将知道如何响应。”address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
KittyInterface kittyContract = KittyInterface(ckAddress);
kittyContract
变量指向官方 CryptoKitties 合约地址。setKittyContractAddress
),允许合约所有者稍后更新此地址。这是在专业智能合约中常见的优化。function feedAndMultiply(uint _zombieId, uint _targetDna, string memory _species) public {
require(msg.sender == zombieToOwner[_zombieId]);
...
if (keccak256(abi.encodePacked(_species)) == keccak256(abi.encodePacked("kitty"))) {
newDna = newDna - newDna % 100 + 99;
}
_createZombie("NoName", newDna);
}
require(msg.sender == zombieToOwner[_zombieId])
:另一个关键的访问控制检查。它确保只有僵尸的所有者才能喂养它。你不能喂养别人的僵尸!if
语句检查 _species
字符串是否为“kitty”。因为我们无法在 Solidity 中直接比较字符串,所以我们通过比较它们的加密哈希来做到这一点。如果是 kitty,它会修改新的 DNA 以 99
结尾。这创建了一个特殊的“kitty-zombie”,这是一个有趣的功能,它使用了我们优化的工厂中建立的 DNA 规则。function feedOnKitty(uint _zombieId, uint _kittyId) public {
uint kittyDna;
(,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
feedAndMultiply(_zombieId, kittyDna, "kitty");
}
(,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
: 此行调用外部 CryptoKitties 合约。充满逗号的语法允许我们忽略我们不关心的所有返回值(例如 isGestating
,cooldownIndex
等),只捕获最后一个:kitty 的 genes
,我们将其存储为 kittyDna
。本课教授了 Ethereum 的真正超能力:可组合性。你的去中心化应用程序(DApp)不是一个孤立的岛屿。它可以与区块链上的每个其他公共合约进行交互并利用其功能。这种将合约“管道”连接在一起的能力是 Ethereum 经常被称为“世界计算机”的原因。
我们的僵尸不再只是单个合约中的数据;它们是包括 CryptoKitties 以及可能无数其他项目的更大生态系统的一部分。
在我们的下一篇文章中,我们将看到如何赋予我们的僵尸所有权和攻击能力!准备好迎接更多的继承和战斗机制。
你认为区块链可组合性最令人着迷的部分是什么?是安全挑战还是无限创新的潜力?让我们在下面的评论中讨论!
- 原文链接: blog.blockmagnates.com/b...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!