本文共 4087 字,大约阅读时间需要 13 分钟。
看了一些区块链的教程,论文,在网上刚刚找到了一个项目实战,CryptoZombies。
如果你想了解更多有关于机器学习、深度学习、区块链、计算机视觉等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!
我们写的合约可能会需要和其他地方的合约进行会话,这里我们就需要用到接口。
假如区块链有如下的一个合约:
contract LuckyNumber { mapping(address => uint) numbers; function setNum(uint _num) public { numbers[msg.sender] = _num; } function getNum(address _myAddress) public view returns (uint) { return numbers[_myAddress]; }}
我们现在有一个外部合约,想要读取上面合约中的数据。我们定义 LuckyNumber
合约的 interface。
contract NumberInterface { function getNum(address _myAddress) public view returns (uint);}
这个过程虽然看起来像在定义一个合约,但其实内里不同:
1.我们只声明了要与之交互的函数 —— 在本例中为
getNum
—— 在其中我们没有使用到任何其他的函数或状态变量。2.我们并没有使用大括号(
{
和}
)定义函数体,我们单单用分号(;
)结束了函数声明。
编译器就是靠这些特征认出它是一个接口的。
在我们的 app 代码中使用这个接口,合约就知道其他合约的函数是怎样的,应该如何调用,以及可期待什么类型的返回值。
getKitty
的函数返回所有的加密猫的数据,包括它的“基因”(我们的僵尸游戏要用它生成新的僵尸)。
该函数如下所示:
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) { Kitty storage kit = kitties[_id]; // if this variable is 0 then it's not gestating isGestating = (kit.siringWithId != 0); isReady = (kit.cooldownEndBlock <= block.number); cooldownIndex = uint256(kit.cooldownIndex); nextActionAt = uint256(kit.cooldownEndBlock); siringWithId = uint256(kit.siringWithId); birthTime = uint256(kit.birthTime); matronId = uint256(kit.matronId); sireId = uint256(kit.sireId); generation = uint256(kit.generation); genes = kit.genes;}
用这个来创建一个接口:
1.定义一个名为
KittyInterface
的接口。2.在interface里定义了
getKitty
函数。
pragma solidity >=0.5.0 <0.6.0;import "./zombiefactory.sol";// Create KittyInterface herecontract KittyInterface { 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 { function feedAndMultiply(uint _zombieId, uint _targetDna) public { require(msg.sender == zombieToOwner[_zombieId]); Zombie storage myZombie = zombies[_zombieId]; _targetDna = _targetDna % dnaModulus; uint newDna = (myZombie.dna + _targetDna) / 2; _createZombie("NoName", newDna); }}
通过上面的例子,我们将接口定义如下
:
contract NumberInterface { function getNum(address _myAddress) public view returns (uint);}
我们可以在合约中这样使用:
contract MyContract { address NumberInterfaceAddress = 0xab38...; // ^ 这是FavoriteNumber合约在以太坊上的地址 NumberInterface numberContract = NumberInterface(NumberInterfaceAddress); // 现在变量 `numberContract` 指向另一个合约对象 function someFunction() public { // 现在我们可以调用在那个合约中声明的 `getNum`函数: uint num = numberContract.getNum(msg.sender); // ...在这儿使用 `num`变量做些什么 }}
通过这种方式,只要将合约的可见性设置为public
(公共)或external
(外部),它们就可以与以太坊区块链上的任何其他合约进行交互。
我们构建一个自己的合约去读取另一个智能合约 CryptoKitties 的内容。
变量ckAddress
存放的是CryptoKitties 合约的地址,在下一行中,请创建一个名为 kittyContract
的 KittyInterface,并用 ckAddress
为它初始化。
pragma solidity >=0.5.0 <0.6.0;import "./zombiefactory.sol";contract KittyInterface { 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 { address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d; // Initialize kittyContract here using `ckAddress` from above KittyInterface kittyContract = KittyInterface(ckAddress); function feedAndMultiply(uint _zombieId, uint _targetDna) public { require(msg.sender == zombieToOwner[_zombieId]); Zombie storage myZombie = zombies[_zombieId]; _targetDna = _targetDna % dnaModulus; uint newDna = (myZombie.dna + _targetDna) / 2; _createZombie("NoName", newDna); }}
转载地址:http://ozyni.baihongyu.com/