π§ββοΈ https://cryptozombies.io/ko/
νμ¬, μ리λν°λ₯Ό μ΅νκΈ°μ κ°μ₯ μ’μ νμ΅ λꡬ(?)λ ν¬λ¦½ν μ’λΉμΈ κ² κ°λ€. ν¬λ¦½ν μ’λΉμ 첫 λ²μ§Έ μ½μ€μΈ Basic solidity μ½μ€μμ κΈ°μ΅ν΄λμ΄μΌ ν κ°λ λ€μ κΈ°λ‘ν΄λκ°λ €κ³ νλ€.
μν λ³μλ 컨νΈλνΈ μ μ₯μ μ¦, μ΄λ리μ λΈλ‘체μΈμ μꡬμ μΌλ‘ μ μ₯λλ€.
ꡬ쑰체μ λμ λ°°μ΄μ μμ±νμ¬ μν λ³μλ‘ νμ©νλ©΄, λ§μΉ λ°μ΄ν°λ² μ΄μ€μ²λΌ ꡬ쑰νλ λ°μ΄ν°λ₯Ό μ μ₯ν μ μλ€.
Person[] people;
function _myFunc(string _name, uint _age) private { ... }
νλ‘ νΈ μ±μμ νΉμ μ‘μ μ λν μ΄λ²€νΈμ λν΄ κ·λ₯Ό κΈ°μΈμΈλ€. μ΄λ²€νΈκ° μ€νλλ©΄ μ±μ ν¨μκ° μ€νλμμμ μ릴 μ μλ€.
// 컨νΈλνΈμ solidity μ½λ
event IntegersAdded(uint x, uint y, uint result);
function add(uint _x, uint _y) public returns(uint) {
uint result = _x + _y;
IntegersAdded(_x, _y, result) // μ΄λ²€νΈλ₯Ό μ€ννμ¬ add ν¨μμ μ€νμ μλ¦Ό
return result;
// νλ‘ νΈ μ±μ Javascript μ½λ
YourContract.IntegersAdded(function(error, result) {
// μ΄λ²€νΈ(ν¨μ) μ€νκ³Ό κ΄λ ¨λ νλμ λν μ½λ
});
μλ‘ λ€λ₯Έ 컨νΈλνΈ κ°μ μνΈμμ©μ μν¨
μ΄λ€ μΈλΆ 컨νΈλνΈμ μΈν°νμ΄μ€λ₯Ό μ½λμ ν¬ν¨νλ©΄, ν΄λΉ 컨νΈλνΈμ λν΄ μ μ μκ² λλ€. ꡬ체μ μΌλ‘λ ν΄λΉ 컨νΈλνΈμ μ μλ ν¨μμ νΉμ±, νΈμΆ λ°©λ², μμλλ μλ΅ λ΄μ© λ±μ λν΄ μ μ μλ€.
μ¦ μΈλΆ 컨νΈλνΈλ₯Ό νμ©ν μ½λλ₯Ό μμ±ν λμλ, μΈλΆ 컨νΈλνΈμ μ£Όμλ§ κ°μ Έμ€λκ²μ΄ μλλΌ ν΄λΉ 컨νΈλνΈμ (μνΈμμ© νκ³ μ νλ λ΄μ©μ΄ ν¬ν¨λμ΄ μλ) μΈν°νμ΄μ€λ₯Ό κΈ°μ¬ν΄μ£Όμ΄μΌ νλ€λ κ²μ΄λ€. λΈλ‘μ²΄μΈ μμ μ΄μ©νκ³ μ νλ μΈλΆ 컨νΈλνΈμ μ£Όμλ‘ μ κ·Όνκ³ μΈν°νμ΄μ€λ₯Ό μμ μ리λν° μ½λμμ μ΄μ© κ°λ₯ν ννλ‘ μ¬μ©νκ³ μ ν¨μ΄λ€. μ½κ² λ§ν΄ 'λ΄ μ»¨νΈλνΈ' μμ 'μΈλΆ 컨νΈλνΈμ μΈν°νμ΄μ€'λ₯Ό μμ±νλ κ²μ΄λ€.
// zombiefeeding.sol
pragma solidity ^0.4.19;
// λΈλ‘체μΈμ 곡κ°λμ΄ μλ ν¬λ¦½ν ν€ν° μ½λλ₯Ό νμ©νμ¬ μΈν°νμ΄μ€ μμ±
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;
// λ΄ μ½λμμ μ΄μ© κ°λ₯ν kittyContractλ‘ λ§λ€μ΄μ£ΌκΈ°
KittyInterface kittyContract = KittyInterface(ckAddress);
...
}
컨νΈλνΈλ₯Ό λ°°ν¬ν μ€λΉκ° λλ©΄, μ΅μ’ μ μΌλ‘ μμμ λ°λ κ°μ₯ λ§μ§λ§ μμμ ν΄λΉνλ 컨νΈλνΈλ§ μ»΄νμΌνμ¬ λ°°ν¬νλ©΄ μμ μμλ°κ³ μλ 컨νΈλνΈλ€κΉμ§ μ κ·Όμ΄ κ°λ₯νλ€.
컨νΈλνΈκ° μ²μ μμ±λ λ νΉμ μΈμ€ν΄μ€ν λ λ, λ³μμ κ°μ μνλ κ°μΌλ‘ μ΄κΈ°ννκΈ° μν΄ μ¬μ©νλ€. 컨νΈλνΈκ° μμ±λ λ λ¨ νλ² μλνλ€. μμ±μλ₯Ό payableνκ² μμ±νλ©΄ 컨νΈλνΈ μμ±μ 컨νΈλνΈ κ³μ μ μ΄λλ₯Ό λ³΄λΌ μ μλ€.
contract example {
// μν λ³μ μ μΈ
string public name;
uint public age;
// μμ±μλ₯Ό ν΅ν΄ μν λ³μ μ΄κΈ°ν
constructor(string memory _name, uint _age) {
name = _name;
age = _age;
}
}
uintλ uint256 μΈμλ uint8, uint16, uint32 λ±μ νμ νμ λ€μ΄ μμ§λ§ νΉλ³ν μ΄μ κ° μλ ν μ΄λ° νμ νμ μ μ¬μ©νλ κ²μ μλ¬΄λ° μ΄λμ΄ μλ€. μ리λν°μμλ uintμ ν¬κΈ°μ μκ΄μμ΄ 256λΉνΈμ μ μ₯ 곡κ°μ 미리 μ‘μλκΈ° λλ¬Έμ΄λ€. uint256(uint) λμ uint8μ μ¬μ©νλ€κ³ ν΄μ κ°μ€ μλͺ¨λ μ ν μ€μ΄λ€μ§ μλλ€.
νμ§λ§, ꡬ쑰체 μμμλ λ€λ₯΄λ€. ꡬ쑰체 μμ μ¬λ¬ κ°μ uintλ₯Ό λ§λ λ€λ©΄ κ°λ₯ν λ μμ ν¬κΈ°μ uintλ₯Ό μ°λ κ²μ΄ μ’λ€. μ리λν°μμ κ·Έ λ³μλ€μ λ μ μ 곡κ°μ μ°¨μ§νλλ‘ μμΆνκΈ° λλ¬Έμ΄λ€. ꡬ쑰체 μμμλ κ°λ₯ν ν μμ ν¬κΈ°μ μ μ νμ μ μ°λλ‘ νμ. λν λμΌν λ°μ΄ν° νμ μ νλλ‘ λ¬Άμ΄μΌ μ μ₯ 곡κ°μ μ΅μνν μ μλ€.
μλμ μ½λμμ NormalStruct
보λ€λ MiniMe
컨νΈλνΈκ°, MiniMe
보λ€λ MiniMe2
컨νΈλνΈκ° λ μ μ μ μ₯ 곡κ°μ μ°¨μ§νλ€.
struct NormalStruct {
uint a;
uint b;
uint c;
}
struct MiniMe {
uint32 a;
uint b;
uint32 c;
}
struct MiniMe2 {
uint32 a;
uint32 c;
uint b;
}
now
: νμ¬μ μ λμ€ νμ μ€ν¬ν(1970λ 1μ 1μΌλΆν° μ§κΈκΉμ§μ΄ μ΄ λ¨μ ν©)
μ λμ€ νμμ 32λΉνΈ μ«μλ‘ μ μ₯λλ€. μ λμ€ νμ μ€ν¬ν κ°μ΄ 32λΉνΈλ‘ νμκ° λμ§ μμ λ§νΌ 컀μ§λ©΄ "Year 2038" λ¬Έμ κ° λ°μν κ²μ΄λ€. νμ§λ§ now
λ κΈ°λ³Έμ μΌλ‘ uint256μ λ°ννκΈ° λλ¬Έμ λͺ
μμ μΌλ‘ uint32(now)
λ‘ λ³νν νμκ° μλ€.
μ리λν°λ λν seconds, minutes, hours, days, weeks, years
μ κ°μ μκ° λ¨μ λν μ 곡νλ©°, μ΄λ€μ κ·Έμ ν΄λΉνλ κΈΈμ΄ λ§νΌμ μ΄ λ¨μ uint μ«μλ‘ λ³νλλ€. 1 days
λ 86400μ΄λ₯Ό μλ―Ένλ€.
βοΈ νμ¬λ now
λμ block.timestamp
λ‘ λ체λμλ€.
private
λλ internal
λ‘ μ μλ ν¨μμ μΈμλ‘ κ΅¬μ‘°μ²΄μ storage ν¬μΈν°λ₯Ό μ λ¬ν μ μλ€. ꡬ쑰체λ₯Ό μλ³ν id λ±μ μ λ¬νλ κ²μ΄ μλλΌ κ΅¬μ‘°μ²΄μ λν μ°Έμ‘°λ₯Ό μ λ¬νλ κ²μ΄λ€.
contract ZombieFeeding {
// ꡬ쑰체
struct Zombie {
string name;
uint dna;
uint32 level;
uint32 readyTime;
}
// _isReady ν¨μμ μΈμλ‘ Zombie ꡬ쑰체μ storage ν¬μΈν°λ₯Ό μ λ¬νμ¬ μ°Έμ‘°νκ² νλ€.
function _isReady(Zombie storage _zombie) internal view returns(bool) {
return (_zombie.readyTime <= now);
}
function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) internal {
...
// Zombie ꡬ쑰체 storage ν¬μΈν° μ μΈ λ° ν λΉ
Zombie storage myZombie = zombies[_zombieId];
// Zombie ꡬ쑰체λ₯Ό μΈμλ‘ μ λ¬νμ¬ _isReady μ€ν
require(_isReady(myZombie));
...
}
}
view
λ‘ μ μλ ν¨μλ μΈλΆμμ νΈμΆλμμ λ κ°μ€λ₯Ό μ ν μλͺ¨νμ§ μλλ€. λΈλ‘체μΈμ μ΄λ ν νΈλμμ
λ μμ±νμ§ μκ³ λ¨μ§ νμΈμ μν μ§μλ§ λ 리기 λλ¬Έμ΄λ€.
μ£Όμν κ²μ, view
ν¨μκ° μΈλΆκ° μλ λμΌ μ»¨νΈλνΈ λ΄μ λ€λ₯Έ ν¨μμμ λ΄λΆμ μΌλ‘ νΈμΆλ κ²½μ°μλ κ°μ€λ₯Ό μλͺ¨νλ€λ μ μ΄λ€. μ΄κ²μ λ€λ₯Έ ν¨μκ° μ΄λ리μμ νΈλμμ
μ μμ±νκ³ μ΄λ λͺ¨λ κ°λ³ λ
Έλμμ κ²μ¦λμ΄μΌ νκΈ° λλ¬Έμ΄λ€. view
ν¨μλ μΈλΆμμ νΈμΆλμμ λλ§ λ¬΄λ£μ΄λ€.
pure
ν¨μ μμ λ§μ°¬κ°μ§λ‘ μΈλΆμμ νΈμΆλμμ λ κ°μ€λ₯Ό μλͺ¨νμ§ μκ³ , λ΄λΆμμ νΈμΆλμμ λμλ κ°μ€λ₯Ό μλͺ¨νλ€.
storageλ₯Ό μ¬μ©νλ κ²μ λΉμΈλ€. ν¨μκ° μ€νλ λμμλ§ νμν λ°°μ΄μ memoryμ μ μΈν΄μ£Όλ νΈμ΄ λ«λ€. μ΄λ storageμ λ°°μ΄μ μ§μ μ λ°μ΄νΈνλ κ²λ³΄λ€ ν¨μ¬ μ λ ΄νλ€.
memory λ°°μ΄μ λ°λμ κΈΈμ΄ μΈμμ ν¨κ» μμ±λμ΄μΌ νλ€. storage λ°°μ΄μ array.push()λ‘ ν¬κΈ°κ° μλμΌλ‘ μ‘°μ λμ§λ§ memory λ°°μ΄μ κ·Έλ μ§ μλ€.
function getArray() external pure returns(uint[]) {
// λ©λͺ¨λ¦¬μ κΈΈμ΄ 3μ μλ‘μ΄ λ°°μ΄μ μμ±νλ€. μ΄ λ°°μ΄μ ν¨μκ° μ€νλλ λμμλ§ μ‘΄μ¬ν κ²μ΄λ€.
uint[] memory values = new uint[](3);
// μ¬κΈ°μ νΉμ ν κ°λ€μ λ£λλ€.
values.push(1);
values.push(2);
values.push(3);
// ν΄λΉ λ°°μ΄μ λ°ννλ€.
return values;
}
μ리λν°μμ keccak256
μ ν¬κ² λ κ°μ§ λͺ©μ μΌλ‘ νμ©λλ€.
μ리λν°μλ λ¬Έμμ΄μ λΉκ΅νλ ν¨μκ° λ΄μ₯λμ΄ μμ§ μλ€. λ°λΌμ λ¬Έμμ΄μ λΉκ΅νλ κ²μ΄ μλλΌ κ·Έ λ¬Έμμ΄μ ν΄μνν κ°μ λΉκ΅νλ€.
function stringCompare(string _a, string _b) public returns (bool) {
return (keccak256(_a) == keccak256(_b));
}
μμ νκ² λμλ₯Ό μμ±νκΈ° μν΄μλ oracle(μ΄λ리μ μΈλΆμμ λ°μ΄ν°λ₯Ό λ°μμ€λ μμ ν λ°©λ² μ€ νλ)μ μ¬μ©ν μ μλ€.
μλ μμμμλ now
μ νμμ€ν¬ν κ°, msg.sender
, μ¦κ°νλ nonce
λ₯Ό μ
λ ₯λ°μ μμμ ν΄μ κ°μ μ»κ³ μ΄λ₯Ό 100μΌλ‘ λλ λλ¨Έμ§λ₯Ό κ΅¬ν΄ 0~99 μ¬μ΄μ λμλ₯Ό μ»μ μ μλ€.
uint randNonce = 0;
uint random = uint(keccak256(now, msg.sender, randNonce)) % 100;
randNonce++;
uint random2 = uint(keccak256(now, msg.sender, randNonce)) % 100;
λΌμ΄λΈλ¬λ¦¬λ νΉλ³ν μ’
λ₯μ 컨νΈλνΈμ΄λ€. λΌμ΄λΈλ¬λ¦¬λ₯Ό ν΅ν΄ κΈ°λ³Έ λ°μ΄ν° νμ
μ ν¨μλ₯Ό λΆμΌ μ μλ€. using
ꡬ문μΌλ‘ μ¬μ©νλ€. uint λ°μ΄ν°μ μ€λ²νλ‘μ°/μΈλνλ‘μ°λ₯Ό λ§κΈ° μν΄ μ¬μ©νλ SafeMath λΌμ΄λΈλ¬λ¦¬κ° λνμ μ΄λ€.
μ¬λ¬ 컨νΈλνΈμμ μμ£Ό μ¬μ©λλ μ½λλ₯Ό λ°λ‘ λΌμ΄λΈλ¬λ¦¬λ‘ λ°°ν¬νλ©΄ 컨νΈλνΈλ§λ€ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ μ©λ§ νλ©΄ μ½κ² μ½λλ₯Ό μ¬μ©ν μ μμΌλ©° λ§€λ² μ½λλ₯Ό μμ±νλ κ²μ λΉν΄ κ°μ€ μλΉλλ μ μ΄μ§λ€.
λΌμ΄λΈλ¬λ¦¬μλ fallback
ν¨μλ₯Ό μ μν μ μκΈ° λλ¬Έμ, μ΄λλ₯Ό λ°μ μ μκ³ λ΄λΆμ payableν ν¨μλ μ μν μ μλ€. λν μμμ΄ λΆκ°λ₯νλ€. κ³μ½ μνλ₯Ό λ³κ²½νκΈ° μν κ²μ΄ μλ, μ
λ ₯ λ° λ°ν κ²°κ³Όλ₯Ό κΈ°λ°μΌλ‘ κ°λ¨ν μμ
μ μννλ λ° μ¬μ©λλ€.
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
SafeMath λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νκ³ μ νλ 컨νΈλνΈ λ΄λΆμμ, using SafeMath for uint256;
λΌκ³ μ¨μ£Όλ©΄ SafeMath λ΄μ λ©μλλ€μ΄ uint256 λ°μ΄ν° νμ
μ λΆκ² λλ€.
require
νΉμ 쑰건μ λ§μ‘±νμ§ μμΌλ©΄ μλ¬λ₯Ό λ°μμν¨λ€. μλ¬κ° λ°μνμ¬ ν¨μ μ€νμ΄ μ€ν¨νλ©΄ λ¨μ κ°μ€λ₯Ό μ¬μ©μμκ² νλΆν΄μ€λ€.
assert
νΉμ 쑰건μ λ§μ‘±νμ§ μμΌλ©΄ μλ¬λ₯Ό λ°μμν¨λ€. μλ¬κ° λ°μνμ¬ ν¨μ μ€νμ΄ μ€ν¨νλ©΄ κ°μ€λ₯Ό μ¬μ©μμκ² λλ €μ£Όμ§ μκ³ λͺ¨λ μλΉν΄λ²λ¦°λ€. assert
λ uint μ€λ²νλ‘μ°μ κ°μ΄ μΌλ°μ μΌλ‘ μ½λκ° μ¬κ°νκ² μλͺ» μ€νλλ κ²½μ°μ μ¬μ©νλ€.
revert
쑰건 μμ΄ λ¬΄μ‘°κ±΄ μλ¬λ₯Ό λ°μμν€κ³ λ¨μ κ°μ€λ₯Ό μ¬μ©μμκ² νλΆν΄μ€λ€.
/// @title νμ΄ν
/// @author μμ±μ
/// @notice μ¬μ©μμκ² μ»¨νΈλνΈκ° 무μμ νλμ§ μ€λͺ
contract Math {
/// @notice μ¬μ©μμκ² ν¨μκ° λ¬΄μμ νλμ§ μ€λͺ
/// @param x ν¨μμ λ§€κ° λ³μ
/// @param y ν¨μμ λ§€κ° λ³μ
/// @return z ν¨μμ 리ν΄κ°
/// @dev κ°λ°μμκ² μΆκ° μ 보λ₯Ό μ€λͺ
function multiply(uint x, uint y) returns (uint z) {
// μ΄κ²μ μΌλ°μ μΈ μ£ΌμμΌλ‘, natspecμ ν¬ν¨λμ§ μλλ€.
z = x * y;
}
}
@title
, @author
, @notice
, @param
, @return
, @dev
κ° μ¬μ©λ μ μμΌλ©° λͺ¨λ νμλ μλλ€. νμ§λ§ κ° ν¨μμ λν μ€λͺ
μΌλ‘ @dev
λ λ¨κΈ°λ κ²μ΄ κΆμ₯λλ€.
μ€λ§νΈ 컨νΈλνΈμ ν¨μλ₯Ό μ€ννκ³ μ νλ€λ©΄, μ΄λ리μ λ€νΈμν¬ μμ λ Έλ μ€ νλμ μ§μλ₯Ό 보λ΄μΌ νλ€. λ Έλλ€μ μ¬λμ΄ μ½κΈ° λΆνΈν JSON-RPCλ‘λ§ μν΅ν μ μλ€.
web3
JSON-RPCλ₯Ό μ§μ μ΄μ©νμ§ μκ³ μλ°μ€ν¬λ¦½νΈ νλ‘ νΈμλ μΈν°νμ΄μ€λ‘ μ΄λ리μ λ Έλλ€κ³Ό μνΈμμ© ν μ μκ² ν΄μ£Όλ λΌμ΄λΈλ¬λ¦¬
npm install web3
λμ DAppμ μν λ Έλλ₯Ό λ°λ‘ μ΄μν νμκ° μμ΄ Infura, λ©νλ§μ€ν¬μ νλ‘λ°μ΄λλ₯Ό μ¬μ©ν μ μλ€. λ©νλ§μ€ν¬λ web3λΌλ μ μ μλ°μ€ν¬λ¦½νΈ κ°μ²΄λ₯Ό ν΅ν΄ λΈλΌμ°μ μ Web3 νλ‘λ°μ΄λλ₯Ό μ£Όμ νλ€.
window.addEventListener('load', function() {
// Web3κ° λΈλΌμ°μ μ μ£Όμ
λμλμ§ νμΈ(Mist/MetaMask)
if (typeof web3 !== 'undefined') {
// Mist/MetaMaskμ νλ‘λ°μ΄λ μ¬μ©
web3js = new Web3(web3.currentProvider);
} else {
// μ¬μ©μκ° Metamaskλ₯Ό μ€μΉνμ§ μμ κ²½μ°μ λν΄ μ²λ¦¬
// μ¬μ©μλ€μκ² Metamaskλ₯Ό μ€μΉνλΌλ λ±μ λ©μΈμ§λ₯Ό 보μ¬μ€ κ²
}
// μ΄μ μ±μ μμνκ³ web3μ μμ λ‘κ² μ κ·Όν μ μλ€.
startApp()
})
web3κ° μ€λ§νΈ 컨νΈλνΈμ ν΅μ νκΈ° μν΄μλ 컨νΈλνΈμ μ£Όμμ ABIκ° νμνλ€.
ABI (Application Binary Interface)
ν΄λΉ 컨νΈλνΈμ λ©μλλ₯Ό νννλ JSON ννμ μΈν°νμ΄μ€μ΄λ€. ν΄λΉ 컨νΈλνΈκ° μ΄ν΄ν μ μλ λ°©λ²μΌλ‘ web3κ° ν¨μλ₯Ό νΈμΆν μ μκ²λ μλ €μ€λ€.
컨νΈλνΈ μ£Όμμ ABIλ₯Ό μ΄μ©ν΄ μ΄μ©νκ³ μ νλ 컨νΈλνΈλ₯Ό μΈμ€ν΄μ€ν νλ€.
var myContract = new web3js.eth.Contract(myABI, myContractAddress);
web3κ° μ»¨νΈλνΈμ ν¨μλ₯Ό νΈμΆνκΈ° μν΄μ call
, send
λ κ°μ λ©μλλ₯Ό μ¬μ©ν μ μλ€. λ©μλμ νΈμΆ κ²°κ³Όλ Promiseμ΄λ―λ‘(λΉλκΈ°) .then
μ μ΄μ©ν΄ κ²°κ³Όλ₯Ό κ°μ§κ³ μ΄νμ μμ
μ μ²λ¦¬ν΄μ€ μ μλ€.
view
, pure
ν¨μλ₯Ό μν΄ μ¬μ©νλ€. λ‘컬 λ
Έλμμλ§ μ€ννκ³ λΈλ‘체μΈμ νΈλμμ
μ λ§λ€μ§ μλλ€. κ°μ€λ μλͺ¨νμ§ μλλ€.
// μ’λΉ idλ‘ μ’λΉ μ 보λ₯Ό κ°μ Έμ€λ call λ©μλ
function getZombieDetails(id) {
return cryptoZombies.methods.zombies(id).call()
}
// ν¨μλ₯Ό νΈμΆνκ³ κ²°κ³Όλ₯Ό κ°μ§κ³ 무μΈκ°λ₯Ό μ²λ¦¬ν μ μλ€.
getZombieDetails(15)
.then(function(result) {
console.log("Zombie 15: " + JSON.stringify(result));
});
view
, pure
κ° μλ λͺ¨λ ν¨μμ λν΄ send
λ₯Ό μ¬μ©ν΄μΌ νλ€. send
λ νΈλμμ
μ λ§λ€κ³ λΈλ‘μ²΄μΈ μμ λ°μ΄ν°λ₯Ό λ³κ²½νλ€. λ°λΌμ μ¬μ©μλ κ°μ€λ₯Ό μ§λΆν΄μΌ νλ€. νλ‘λ°μ΄λλ‘ λ©νλ§μ€ν¬λ₯Ό μ¬μ©νλ€λ©΄, send()
λ₯Ό νΈμΆνμ λ μλμΌλ‘ λ©νλ§μ€ν¬μμ νΈλμμ
μ μλͺ
νλΌλ μ°½μ λμμ€λ€.
send
λ νΈλμμ
μ μ μ‘ν΄μΌ νκΈ° λλ¬Έμ ν¨μλ₯Ό νΈμΆν μ¬λ(dAppμ μ¬μ©μ)μ from
μ£Όμκ° νμνλ€. λ©νλ§μ€ν¬κ° μ°½μ λμ μ¬μ©μκ° μλͺ
μ νλλ‘ νλ€. νΈλμμ
μλ μ€λ μκ°μ΄ μμλ μ μμΌλ―λ‘ μ΄μ λμν΄μΌ νλ€. (νΈλμμ
μ΄ λ³΄λ΄μ‘λ€λ μλ΄λμ°κΈ°) λν send
λ©μλμλ μ νμ μΌλ‘ gas
μ gasPrice
λ₯Ό μ§μ ν μ μλ€. μ§μ νμ§ μλλ€λ©΄ λ©νλ§μ€ν¬λ μ¬μ©μκ° μ΄ κ°μ μ νν μ μλλ‘ νλ€.
function createRandomZombie(name) {
// μκ°μ΄ κ½€ 걸릴 μ μμΌλ, νΈλμμ
μ΄ λ³΄λ΄μ‘λ€λ κ²μ
// μ μ κ° μ μ μλλ‘ UIλ₯Ό μ
λ°μ΄νΈν΄μΌ ν¨
$("#txStatus").text("Creating new zombie on the blockchain. This may take a while...");
// μ°λ¦¬ 컨νΈλνΈμ μ μ‘νκΈ°: μ
λ ₯λ μ΄λ¦μΌλ‘ μλ‘μ΄ μ’λΉλ₯Ό μμ±νλ send λ©μλ
return CryptoZombies.methods.createRandomZombie(name)
.send({ from: userAccount }) // from μ£Όμκ° νμνλ€.
// μ’λΉκ° μμ±λκ³ νΈλμμ
μ΄ μ±κ³΅μ μΌλ‘ λΈλ‘μ ν¬ν¨λ λ
.on("receipt", function(receipt) {
$("#txStatus").text("Successfully created " + name + "!");
getZombiesByOwner(userAccount).then(displayZombies);
})
// κ°μ€ λΆμ‘± λ±μ μ΄μ λ‘ νΈλμμ
μ΄ μ€ν¨νμ λ
.on("error", function(error) {
$("#txStatus").text(error);
});
}
payable
ν¨μλ₯Ό νΈμΆν λμλ, send
λ©μλμ from
μΈμ value
κΉμ§ ν¨κ» μ€μ ν΄μ€λ€.
CryptoZombies.methods.levelUp(zombieId)
.send({ from: userAccount, value: web3js.utils.toWei("0.001") })
νμ¬ νμ±νλ κ³μ μ κ°μ Έμ¬ μ μλ€.
var userAccount = web3.eth.accounts[0];
νμ±νλ κ³μ μ΄ λ°λκ² λλ©΄ νλ‘ νΈ μΈν°νμ΄μ€μ 보μ¬μ§λ λ°μ΄ν°λ λ°λ κ³μ μ λ§λ λ°μ΄ν°λ‘ λ°λμ΄μΌ νλ―λ‘, setInterval
μ μ¬μ©νμ¬ ν΄λΉ κ³μ μ΄ κ³μ νμ±νλμ΄ μλμ§ νμΈν΄μΌ νλ€.
var accountInterval = setInterval(function() {
// κ³μ μ΄ λ°λμλμ§ νμΈ
if (web3.eth.accounts[0] !== userAccount) {
userAccount = web3.eth.accounts[0];
// μ κ³μ μ λν UIλ‘ μ
λ°μ΄νΈνκΈ° μν ν¨μ νΈμΆ
updateInterface();
}
}, 100);
web3μμ 컨νΈλνΈμ μ΄λ²€νΈλ₯Ό ꡬλ
νμ¬ ν΄λΉ μ΄λ²€νΈκ° λ°μν λλ§λ€ μ΄λ ν λ‘μ§μ μ€νμν€λλ‘ ν μ μλ€. νμ§λ§ dAppμμ ν΄λΉ μ΄λ²€νΈκ° λ°μνλ λͺ¨λ κ²½μ°μ λ‘μ§μ΄ μλν κ²μ΄λ€. μ΄λ²€νΈλ₯Ό νν°λ§νκ³ νμ¬ μ¬μ©μμ μ°κ΄λ μ΄λ²€νΈλ§ μμ νκΈ° μν΄ indexed
ν€μλλ₯Ό μ¬μ©ν μ μλ€.
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
컨νΈλνΈ μ½λμμ μ΄λ²€νΈλ₯Ό μ μν λ _from
, _to
λ₯Ό indexed
λ‘ μ μνμμΌλ―λ‘ μ΄λ₯Ό νμ©νμ¬ νν°λ§λ μ΄λ²€νΈλ§μ ꡬλ
ν μ μλ€.
// `filter`λ₯Ό μ¬μ©ν΄ `_to`κ° `userAccount`μ κ°μ λλ§ μ½λλ₯Ό μ€ν
cryptoZombies.events.Transfer({ filter: { _to: userAccount } })
.on("data", function(event) {
let data = event.returnValues;
// νμ¬ μ¬μ©μκ° λ°©κΈ μ’λΉλ₯Ό λ°μκ³ , ν΄λΉ μ’λΉλ₯Ό 보μ¬μ€ μ μλλ‘ UIλ₯Ό μ
λ°μ΄νΈνλ λ‘μ§ μΆκ°
getZombiesByOwner(userAccount).then(displayZombies);
}).on("error", console.error);
λν getPastEvents
λ₯Ό μ¬μ©νμ¬ μ§λ μ΄λ²€νΈλ€μ λν΄ μ§μν μ μλ€. μ΄ λ fromBlock
κ³Ό toBlock
νν°λ₯Ό μ΄μ©ν΄ κ²μνκ³ μ νλ λΈλ‘ λ²μ(μ΄λ²€νΈ λ‘κ·Έμ λν μκ° λ²μ)λ₯Ό μ§μ ν μ μλ€. μ΄λ¬ν μ μ νμ©νμ¬ μ΄λ²€νΈλ₯Ό μ λ ΄ν ννμ storageλ‘ μ¬μ©ν μλ μλ€. λ°μ΄ν°λ₯Ό λΈλ‘체μΈμ κΈ°λ‘νλ κ²μ λ§€μ° λΉμΌ νΈμ΄μ§λ§ μ΄λ²€νΈλ₯Ό μ΄μ©νλ κ²μ μλμ μΌλ‘ ν¨μ¬ μ λ ΄νλ€. μ΄λ²€νΈ λ°μ΄ν°λ μ€λ§νΈ 컨νΈλνΈ μ체 μμμλ μ½κ±°λ νμ©ν μ μμ§λ§, νλ‘ νΈμλμμ νμ©ν νμ€ν 리 λ°μ΄ν° κΈ°λ‘μ©μΌλ‘λ μ μ©νλ€.
cryptoZombies.getPastEvents("NewZombie", { fromBlock: 0, toBlock: "latest" })
.then(function(events) {
// `events`λ μ°λ¦¬κ° μμμ νλ κ²μ²λΌ λ°λ³΅ μ κ·Όν `event` κ°μ²΄λ€μ λ°°μ΄μ΄λ€.
// μ΄ μ½λλ μμ±λ λͺ¨λ μ’λΉμ λͺ©λ‘μ μ°λ¦¬κ° λ°μ μ μκ² ν κ²μ΄λ€.
});
λΆλͺ ν 2μ£Ό μ μ ν¬λ¦½ν μ’λΉλ₯Ό λ€ νλλ°, λ€μ ν΄λ³΄λ λ μλ‘μ λ€. μ²μ ν λλ μ€λ μ€λ λ¬Έμ λ₯Ό νκ³ λμ΄κ°λλ° μ΄λ²μλ κ΄λ ¨ κ°λ μ νμ€ν λ¨Έλ¦Ώ μμ λ£λλ€ μκ°νκ³ μ 리νλ©° μ§ννλλ solidityλ web3μ λν μ΄ν΄λκ° λ§μ΄ μ¬λΌκ°λ κ² κ°λ€. λ©νλ§μ€ν¬ μ΄ μ’λΉ κ·μ½λ€!