CryptoZombiesのコードを解説します。コントラクトの関係全体を見たい方はこちらへ。
contract ZombieAttack
あるゾンビが他のゾンビに攻撃を仕掛け、勝敗を決するための関数が格納されているコントラクトです。
関連するレッスン、チャプター
ソースコード・解説
pragma solidity ^0.4.19;
import "./zombiehelper.sol";
contract ZombieAttack is ZombieHelper {
uint randNonce = 0;
uint attackVictoryProbability = 70;
// ランダムな数値を返す関数。
// ここではハッシュ関数が返す値が入力に対して十分にランダムであるとみなして、
// 時刻とnonceを用い、ランダムな値を生成している。
function randMod(uint _modulus) internal returns(uint) {
randNonce++;
return uint(keccak256(now, msg.sender, randNonce)) % _modulus;
}
function attack(uint _zombieId, uint _targetId) external onlyOwnerOf(_zombieId) {
Zombie storage myZombie = zombies[_zombieId];
Zombie storage enemyZombie = zombies[_targetId];
// 関数内でランダム値を発生して、その値の大小で勝敗を決めている。
// このアルゴリズムは、自分が抱えているノードで何度でも勝敗の計算が可能であるため、不誠実なノードの攻撃に対して脆弱である。
// https://cryptozombies.io/jp/lesson/4/chapter/4 参照のこと。
uint rand = randMod(100);
if (rand <= attackVictoryProbability) {
myZombie.winCount++;
myZombie.level++;
enemyZombie.lossCount++;
feedAndMultiply(_zombieId, enemyZombie.dna, "zombie");
} else {
myZombie.lossCount++;
enemyZombie.winCount++;
_triggerCooldown(myZombie);
}
}
}