Solidity

CryptoZombies 1 (좀비 공장 만들기) 정리

dlwltn98 2023. 2. 6. 14:56

Contract

 - 이더리움 애플리케이션의 기본적인 구성요소

 - 모든 프로젝트의 시작 지점

 - 모든 변수와 함수는 어느 한 컨트랙트에 속함

 - 솔리디티 코드는 컨트랙트 안에 있음

 

Version Pragma

 - 해당 코드가 이용해야하는 솔리디티 버전 선언

 - 이를 통해 이후에 새로운 컴파일러 버전이 나와도 기존 코드가 깨지지 않도록 예방

pragma solidity ^0.4.19;   // 솔리디티 버전

// 컨트렉트 생성
contract ZombieFactory{ 

}

 

상태 변수

 - 컨트랙트 저장소에 영구적으로 저장됨 ( = 이더리움 블록체인에 기록됨)

 - DB에 쓰는 것과 비슷

pragma solidity ^0.4.19;

contract ZombieFactory{ 
    uint myUnsignedInteger = 100;
}
uint (= uint256)  - 부호 없는 정수 (값이 음이면 안, 됨)
 - 더 작은 비트로 선언 가능 ( uint8, uint16 ... )
int  - 부호 있는 정수

 

수학 연산

 - 대부분의 프로그래밍 언어의 수학 연산과 동일

x + y   // 덧셈
x - y   // 뺄셈
x * y   // 곱셈
x / y   // 나눗셈
x % y   // 나머지

// 지수연산, 5^2 = 25
uint x = 5 ** 2;

 

구조체 

 - 구조체를 통해 여러 특성을 가진 복잡한 자료형 생성 가능

struct Person {
  uint age;
  string name;
}
string 임의의 길이를 가진 UTF-8  데이터를 위해 활용

 

배열

정적 배열

uint[2] fixedArray;       // 2개의 원소를 담을 수 있는 고정 길이의 배열
string[5] stringArray;    // 또다른 고정 배열로 5개의 스트링을 담을 수 있음

동적 배열

 - 결정된 크가 없으며 크기가 계속 커질 수 있음

 - 컨트랙트에 구조화된 데이터를 저장하는데 유용

uint[] dynamicArray;
Person[] people;  // 구조체 배열도 생성 가능

public 배열

 - 다른 컨트랙트들이 이 배열을 읽을 수 있음  (쓸 수는 없음)

 - 컨트랙트에 공개 데이터를 저장할때 유용

 - Getter 메소드를 자동으로 생성

Person[] public people;

 

함수 선언

 - 함수 인자를 _로 시작해서 전역변수와 구별할 수 있게 하는게 관례임

// 함수 선언
function eatHamburgers( string _name, uint _amount ) {
    ...
}

// 함수 호출
eatHamburgers("vitalik", 100);

 

구조체와 배열 활용

 - array.push() : 새로운 원소를 배열의 끝에 추가

// 구조체 생성
struct Person {
    uint age;
    string name;
}

// 구조체를 이용한 public 배열 선언
Person[] public people;

Person leejisu = Person(26, "leejisu");  // 새로운 사람 생성
people.push( leejisu );   // 배열에 추가

// 아래와 같이 쓸 수도 있음
people.push( Person(26, "leejisu") );

 

Private / Public 함수

 - 함수는 기본적으로 public으로 선언됨 → 공격에 취약

 - 기본적으로 함수를 private으로 선언하고 공개할 함수만 public으로 선언하는 것이 바람짐

 - private 함수도 _로 시작하는게 관례임

uint numbers[];

function _addToArray(uinnt _number) private {
    numbers.push(_number);
}

 

함수 반환값

 - 함수 선언은 반환값 종류를 포함

string greeting = "What's up dog";

// 함수 반환값 종류 : string
function sayHello() public returns (String) {
    return greeting ;
}

 

함수 제어자

View  함수

 - 함수가 데이터를 변경하지 않고 보기만 할때 사용

function sayHello() public view returns (string) {}

Pure 함수

 - 함수가 앱에서 어떠한 데이터에도 접근하지 않을때 사용

 - 앱에서 읽는것도 하지않고, 반환값이 전달된 인자값에 따라 달라짐

function _multiply(uint a, uint b) private pure returns (uint) {
    return a*b;
}

 

keccak256

 - 이더리움은 SHA3의 한 버전인 keccak256를 내장 해시 함수로 가지고 있음

keccak256("aaaab");  
//6e91ec6b618bb462a4a6ee5aa2cb0e9cf30f7a052bb467b0ba58b8748c00d2e5

keccak256("aaaac");
//b1f078126895a1424524de5321b339ab00408010b7cf0e6ed451514981e58aa9

 

형 변환

 - 자료형 간에 형변환 가능

uint8 a = 5;
uint b = 6;   // uint = uint256

uint8 c = a*b;  // Error
uint8 c = a*uint8(b);  // 정상 작동

 

이벤트

 - 컨트랙트가 블록체인상에서 앱의 사용자단에 무언가 액션이 발생했을때 의사소통하는 방법

 - 특정 이벤트가 일어나는지 확인하고 그 이벤트가 일어나면 행동을 함

// 이벤트 선언
event IntegersAdded(uint x, uint y, uint result);

function add(uint _x, uint _y) public {
  uint result = _x + _y;
  // 이벤트를 실행하여 앱에게 add 함수가 실행되었음을 알린다:
  IntegersAdded(_x, _y, result);
  return result;
}

// js로 구현하면 다음과 같음
YourContract.IntegersAdded(function(error, result) {
  // 결과와 관련된 행동을 취한다
})

 

전체 코드

pragma solidity ^0.4.19;

contract ZombieFactory {

    // event 선언
    event NewZombie(uint zombieId , string name, uint dna);

    // dnaModulus라는 uint형 변수를 생성하고 10의 dnaDigits승을 배정
    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    // Zombie 라는 구조체 생성
    struct Zombie {
        string name;
        uint dna;
    }

    // Zombie 구조체의 public 배열 생성
    Zombie[] public zombies;

    // 좀비 생성 private 함수 선언
    function _createZombie(string _name, uint _dna) private {

        // 새로운 좀비를 zombies 배열에 추가
        // 배열의 첫 원소가 0이라는 인덱스를 갖기 때문에, array.push() - 1은 막 추가된 좀비의 인덱스가 됨
        uint id = zombies.push(Zombie(_name, _dna)) - 1;

        // 새로운 좀비가 배열에 추가되면 이벤트 실행
        NewZombie(id, _name, _dna);
    }

    // uint를 반환하는 view 함수 선언
    function _generateRandomDna(string _str) private view returns (uint) {

        uint rand = uint(keccak256(_str));

        // 좀비 DNA가 16자리 숫자이기만을 원하므로 연산 후 값 반환
        return rand % dnaModulus;
    }

    // public 함수 선언
    function createRandomZombie(string _name) public {
        // 좀비 dna 생성
        uint randDna = _generateRandomDna(_name);
        // 새로운 좀비 배열에 추가 
        _createZombie(_name, randDna);
    }

}

 

github : https://github.com/dlwltn98/studyCryptoZombies

cryptoZombies: https://cryptozombies.io/ko/course