CryptoZombies #2 비망록

안녕하세요. 사토미입니다.
평소에는 dapps 개발, 블록체인 리서치 등을 하고 있습니다.
블록체인만 트위트하는 계정을 최근에 만들었습니다.
dapps, 해외 블록 체인 뉴스 ... etc => @ 사토민 _에서 v

이 항목은 CryptoZombies 비망록입니다.

CryptoZombies #1은 여기



좀비가 인간을 공격한다





레슨 2는 좀비에게 먹이를줍니다.

Mapping/Address



- Address



Address는 은행 계좌 번호와 같습니다. 계정별로 고유한 값입니다.

- Mapping



데이터 저장 및 참조를 위한 키 가치 저장소.
mapping (address => uint) public accountBalance;

※ accountBalance라고 하는 데이터 격납고에, Key가 address , Value가 uint 라고 하는 견해.
pragma solidity ^0.4.19;

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 _name, uint _dna) private {
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        NewZombie(id, _name, _dna);
    } 

    function _generateRandomDna(string _str) private view returns (uint) {
        uint rand = uint(keccak256(_str));
        return rand % dnaModulus;
    }

    function createRandomZombie(string _name) public {
        uint randDna = _generateRandomDna(_name);
        _createZombie(_name, randDna);
    }

}


여기서, 이하의 mapping을 작성한다.
zombieToOwner : 누가 어떤 좀비를 보유하고 있는지ownerZombieCount : 누가 어떤 좀비를 보유하고 있는지

Msg.sender



- Msg.sender



그 함수를 호출한 유저(또는 스마트 컨트랙트)의 address를 참조할 수 있다.
pragma solidity ^0.4.19;

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 _name, uint _dna) private {
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        ////////////////////////////////////////////////////////
        zombieToOwner[id] = msg.sender;
        ownerZombieCount[msg.sender]++;
        ////////////////////////////////////////////////////////
        NewZombie(id, _name, _dna);
    }

    function _generateRandomDna(string _str) private view returns (uint) {
        uint rand = uint(keccak256(_str));
        return rand % dnaModulus;
    }

    function createRandomZombie(string _name) public {
        uint randDna = _generateRandomDna(_name);
        _createZombie(_name, randDna);
    }

}


여기에서 좀비가 만들어지면 zombieToOwner 에 작성자의 address를 좀비의 id에 묶어 저장.
그런 다음 ownerZombieCount를 늘립니다.

Require



- Require



조건이 충족되지 않으면 오류를 던져 실행을 중지합니다.
pragma solidity ^0.4.19;

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 _name, uint _dna) private {
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        zombieToOwner[id] = msg.sender;
        ownerZombieCount[msg.sender]++;
        NewZombie(id, _name, _dna);
    }

    function _generateRandomDna(string _str) private view returns (uint) {
        uint rand = uint(keccak256(_str));
        return rand % dnaModulus;
    }

    function createRandomZombie(string _name) public {
        //該当箇所
        require(ownerZombieCount[msg.sender] == 0);
        uint randDna = _generateRandomDna(_name);
        _createZombie(_name, randDna);
    }

}


좀비를 부담없이 아무것도 만들 수 없도록 주소마다 하나만이라는 조건을 붙인다.

상속 / Import


contract 子のコントラクト is 親のコントラクト {

}

부모의 계약에 액세스할 수 있습니다.

import도 잊지 않고.
import './親のコントラクト.sol'

스토리지/메모리



- 스토리지



블록체인에 데이터 쓰기

- Memory



블록체인에 데이터를 쓰지 않고 임시 저장
Gas가 걸리지 않는다.
pragma solidity ^0.4.19;

import "./zombiefactory.sol";

contract ZombieFeeding is ZombieFactory {

  function feedAndMultiply(uint _zombieId, uint _targetDna) public {
    //該当箇所
    require(msg.sender == zombieToOwner[_zombieId]);
    Zombie storage myZombie = zombies[_zombieId];
  }

}

여기서는 feedAndMultiply 함수 내에서 myZombie 라는 Storage에 부모의 계약으로 작성한 zombies 배열을 저장한다.

내부/외부



- 내부


private + 상속 된 계약에도 액세스 할 수 있습니다.

- External



외부에서만 호출할 수 있다.

상속자인 ZombieFactory_createZombie 함수는 private 이었으므로,feedAndMultiply 함수 내에서도 호출할 수 있도록 Internal 로 변경한다.

좀비에게 Crypto Kitties를 포식시킨다.



충격이 달린다.

- 인터페이스



다른 계약과 상호 작용할 때 정의합니다.

여기에 Crypto Kitties getKitty 함수를 가자.ckAddress 는 Crypto Kitties의 계약 주소입니다.
ckAddress를 사용하여 kittyContract를 초기화합니다.
pragma solidity ^0.4.19;

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;
 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);
  }

}


포식시에 원하는 정보는 getKitty 함수 내의 10번째 uint256 genes_kittyId 에서 kittyContract.getKitty 를 호출하고 genes 에 저장.
마지막으로 feedAndMultiply 에 'kitty'를 파라미터로 설정한다.
pragma solidity ^0.4.19;

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;
    KittyInterface kittyContract = KittyInterface(ckAddress);

    // 該当箇所
    function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) public {
        require(msg.sender == zombieToOwner[_zombieId]);
        Zombie storage myZombie = zombies[_zombieId];
        _targetDna = _targetDna % dnaModulus;
        uint newDna = (myZombie.dna + _targetDna) / 2;
        // ifで最後の2桁を99にして、kittyを判別。
        if (keccak256(_species) == keccak256("kitty")) { 
            newDna = newDna - newDna % 100 + 99;
        }
        _createZombie("NoName", newDna);
    }

    function feedOnKitty(uint _zombieId, uint _kittyId) public {
        uint kittyDna;
        (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
        // 該当箇所
        feedAndMultiply(_zombieId, kittyDna, "kitty");
    }

}

DONE입니다, 고마워요.



다음 번 : "Solidity의 고급 개념"



bportal



좋은 웹페이지 즐겨찾기