【CryptoZombies - 1 Solidity 教程】010 msg.sender
一、前言
看了一些区块链的教程,论文,在网上刚刚找到了一个项目实战,CryptoZombies。
如果你想了解更多有关于机器学习、深度学习、区块链、计算机视觉等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!
二、msg.sender
当我们有了一套映射来记录僵尸的所有权时,我们可以用msg.sender来运用他们。并且,msg.sender可以被所有函数调用。msg.sender指的是当前调用者(或智能合约)的 address。
注意:
在 Solidity 中,功能执行始终需要从外部调用者开始。 如果没有人调用合约中的函数,合约只会在区块链上什么也不做。所以msg.sender总是存在的。
下面是使用 msg.sender 来更新 mapping 的例子,更新我们定义的映射`favoriteNumber` 来将 `_myNumber`存储在 `msg.sender`下。存储数据至映射的方法和将数据存储在数组相似。然后我们可以返回存储在调用者地址名下的值,若调用者还没调用 setMyNumber, 则值为 `0`。
mapping (address => uint) favoriteNumber;
function setMyNumber(uint _myNumber) public {
// Update our `favoriteNumber` mapping to store `_myNumber` under `msg.sender`
favoriteNumber[msg.sender] = _myNumber;
// ^ The syntax for storing data in a mapping is just like with arrays
}
function whatIsMyNumber() public view returns (uint) {
// Retrieve the value stored in the sender's address
// Will be `0` if the sender hasn't called `setMyNumber` yet
return favoriteNumber[msg.sender];
}
在这个小小的例子中,任何人都可以调用 setMyNumber 在我们的合约中存下一个 uint 并且与他们的地址相绑定。 然后,他们调用 whatIsMyNumber 就会返回他们存储的 uint。使用 msg.sender 很安全,因为它具有以太坊区块链的安全保障 —— 除非窃取与以太坊地址相关联的私钥,否则是没有办法修改其他人的数据的。
四、实战
1、要求
修改 _createZombie
方法,将僵尸分配给函数调用者。
1.首先,在得到新的僵尸 id
后,更新 zombieToOwner
映射,在 id
下面存入 msg.sender
。
2.然后,为这个 msg.sender
名下的 ownerZombieCount
加 1。
注:跟在 JavaScript 中一样, 在 Solidity 中也可以用 ++
使 uint
递增。
2、代码
pragma solidity >=0.5.0 <0.6.0;
contract ZombieFactory {
event NewZombie(uint zombieId, string name, uint dna);
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies;
mapping (uint => address) public zombieToOwner;
mapping (address => uint) ownerZombieCount;
function _createZombie(string memory _name, uint _dna) private {
uint id = zombies.push(Zombie(_name, _dna)) - 1;
// start here
zombieToOwner[id] = msg.sender;
ownerZombieCount[msg.sender]++;
emit NewZombie(id, _name, _dna);
}
function _generateRandomDna(string memory _str) private view returns (uint) {
uint rand = uint(keccak256(abi.encodePacked(_str)));
return rand % dnaModulus;
}
function createRandomZombie(string memory _name) public {
uint randDna = _generateRandomDna(_name);
_createZombie(_name, randDna);
}
}