본문 바로가기
Ethereum/Solidity

CrytoZombies_Lesson1_기본문법

by rooney-l3 2019. 8. 16.

1. 컨트랙트

pragma solidity ^0.4.19;

contract ZombieFactory {

}

 

모든 Solidity 소스 코드는 "version pragma"로 시작하게 됩니다. 이는 해당 코드가 이용해야 하는 솔리디티 버전을 선언함으로써, 이후에 새로운 컴파일러 버전이 나와도 기존 코드가 깨지지 않도록 예방하는 것입니다. 

 

솔리디티 코드는 컨트랙트 안에 싸여 있습니다. 컨트랙트는 이더리룸 애플리케이션의 기본적인 구성 요소로, 모든 변수와 함수는 어느 한 컨트랙트 안에 속하게 됩니다.

 

2. 상태 변수 & 정수

pragma solidity ^0.4.19;

contract ZombieFactory {
	uint dnaDigits = 16;
}

 

상태 변수는 컨트랙트 저장소에 영구적으로 저장되는 변수를 말합니다. 다시말해, 이더리움 블록체인에 기록되는것입니다. 

 

uint는 부호없는 정수(0 과 양의 정수)를 의미하는 자료형 입니다. 

int는 부호있는 정수를 의미하는 자료형 입니다. 

string는 문자를 의미하는 자료형입니다. 

 

*참고*

솔리디티에서 uint는 실제로 uint256, 즉 256비트 부호 없는 정수의 다른 표현입니다. uint8, uint16, uint32 등과 같이 uint를 더 적은 비트로 선언할 수도 있습니다. 

 

3. Solidity에서 수학연산

 

덧셈 : x + y

뺄셈 : x - y

곱셈 : x * y

나눗셈 : x/y

나머지 : x%y

제곱 : x**y(x^y)

 

4.구조체

 

(1)구조체 만들기

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

}

복잡한 자료형을 필요로 할때 구조체를 사용할 수 있습니다. 

 

(2)구조체에 값 넣기 

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }
    Zombie firstZombie = Zombie("kkk",111222333444555666);

}

 

Zombie라는 이름을 갖은 구조체에 값을 추가합니다. 추가할 값 모음의 이름은 firstZombie입니다. 추가할 값은 "kkk",111222333444555666 이라는 값을 구조체 안의 name과 dna에 추가합니다. 

 

5. 배열

 

어떤것의 모음집이 필요할 때 '배열'을 사용할 수 있습니다. 솔리디티에서는 정적배열과 동적배열 두 종류의 배열이 존재하고, 구조체의 배열을 생성 할 수도 있습니다. 

 

(1) 정적배열 :  배열의 크기가 2로 고정되어있어 2개의 원소까지만 담을 수 있습니다.

uint[2] fixedArray;

(2) 동적배열 : 배열의 크기가 고정되어있지 않아 배열의 크기가 계속 커질 수 있습니다.

uint[] fixedArray;

(3) 구조체의 배열 : 구조체 Person의 동적배열을 만들고 그 배열의 이름은 people라는 의미입니다.

contract ABCDE{
	struct Person {
  		uint age;
  		string name;
		}
    Person[] people;
 }

(4) public 배열 : public로 배열을 선언하게 되면 다른 컨트랙트들이 이 배열을 읽을 수 있게 됩니다. 배열을 쓸 수는 없습니다.  단지 읽기만 하는것이므로 공개 데이터를 저장할 때 유용하게 사용할 수 있습니다. 

Person[] public people;

-----------------------------------------------------------------------------------------------------------------------------------

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;

}

Zombie라는 이름을 갖은 구조체의 배열을 public로 만듭니다. 이 배열의 이름은 zombies 입니다.

 

(5) 배열에 값 추가하기

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;
    zombies.push(Zombie("AAA",111222333444555666));

}

 

Zombie라는 이름을 갖은 구조체의 배열의 이름은 zombies입니다. 배열이름.push(구조체이름(값1,값2)); 형식을 사용하여 구조체의 배열에 값을 추가합니다. zombies[0] =("AAA",111222333444555666)이 되게 됩니다. 

 

6. 함수 선언

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;

    function createZombie(string _name, uint _dna){

    }

}

 

솔리디티에서 함수 선언은 function 함수이름(매개변수) 의 형태로 하게 됩니다. createZombie라는 이름의 함수는 string 형 name이라는 이름을 갖는 인자와 uint형 dna이라는 이름을 갖는 총 2개의 인자를 전달받고 있습니다. 인자의 이름은 _(언더바)를 앞에 써주는것이 관례입니다. 

 

7.Private/Public함수

 

public함수는 누구나 해당 함수가 선언된 컨트랙트로부터 해당 함수를 호출하고 코드를 실행 할 수 있다는 의미입니다. 솔리디티에서 함수는 기본적으로 public으로 선언되게 됩니다. 

private함수는 해당 함수가 선언된 컨트랙트 내의 다른 함수들만이 해당 함수를 호출하고 코드를 실행 할 수 있다는 의미입니다. private함수를 선언할때는 함수인자의 이름과 마찬가지로 _(언더바)를 함수명 앞에 붙이는것이 관례입니다.

 

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;

    function _createZombie(string _name, uint _dna) private {
        zombies.push(Zombie(_name, _dna));
    }

}

_createZombie 라는 함수는 private함수로 선언되었습니다. 따라서 누구나 이 함수를 호출할 수 없고, 해당함수가 선언된 컨트랙트내의 다른 함수들만이 _createZombie함수를 호출하고 실행할 수 있습니다. 해당 함수는 구조체 배열에 함수의 매개변수를 값으로 추가하는 함수입니다. 즉, _createZombie("AAA",111222333444555666)이라고 함수를 호출하게 되면 구조체 배열에 해당 값이 추가되게 됩니다. 

 

8. 함수에서 값 반환받기

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;

    function _createZombie(string _name, uint _dna) private {
        zombies.push(Zombie(_name, _dna));
    } 

    function _generateRandomDna(string _str) private view returns (uint) {

    }

}

솔리디티의 함수에서 어떤 값을 반환받기 위해서는 반환값의 자료형을 선언해야 합니다. 또한 함수를 제어하기위해 함수 제어자라는 것을 이용할 수있습니다. view 제어자는 함수가 데이터를 보기만 하고 변경하지 않는다는 의미입니다.

 

_generateRandomDna라는 private 함수는 _str(string)을 인자로 전달받고 , uint형으로 값을 반환합니다. 이 함수는 view로 선언되었으므로 컨트랙트 변수를 볼수는 있지만 변경은 할 수 없습니다. 

 

9. Keccak256과 형변환

 

(1) Keccak256

이더리움은 SHA3의 한 버전인 Keccak256를 내장 해시 함수로 가지고 있습니다. 해시 함수는 입력 스트링을 랜덤 256비트 16진수로 변환시켜줍니다. 스트링에 약간의 변화라도 생긴다면 그 해시 값은 완전히 달라지게 됩니다.  

keccak256("aaaab");
//6e91ec6b618bb462a4a6ee5aa2cb0e9cf30f7a052bb467b0ba58b8748c00d2e5

keccak256("aaaac");
//b1f078126895a1424524de5321b339ab00408010b7cf0e6ed451514981e58aa9

 

끝의 문자가 b에서 c로 변환되었는데 해시 값이 완전히 달라진것을 볼 수 있습니다. 

 

(2) 형변환

uint8 a = 5;
uint b = 6;
uint8 c = a * b; 
// b가 uint8이 아닌 uint를 반환하기 때문에 에러 메시지가 난다:

uint8 c = a * uint8(b); 
// b를 uint8으로 형 변환해서 코드가 제대로 작동하도록 해야 한다:

 

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;

    function _createZombie(string _name, uint _dna) private {
        zombies.push(Zombie(_name, _dna));
    } 

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


}

_generateRandomDna  함수는 _str을 받아서 이를 keccak256 함수를 통해 해시 값으로 변환시킵니다. 이 변환된 값을 uint로 형변환을 시키고 rand라는 uint형 변수에 저장시킵니다. 우리가 원하는 것은 16자리의 숫자이므로 10^16으로 나눈 나머지값만을 반환하게되면 16자리의 숫자만 반환 할 수 있게 됩니다.(xxxxxxxxxxxx1234567890ABCDEF라는 숫자가 있으면 이를 10^16으로 나누면 xxxxxxxxxxxx . 1234567890ABCDEF이 되므로 나머지는 1234567890ABCDEF인 16자리 숫자가 된다)

 

10. CyptoZombies Lesson 1 종합

 


pragma solidity ^0.4.19;

contract ZombieFactory {



    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;

    function _createZombie(string _name, uint _dna) private {
        zombies.push(Zombie(_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);
    }

}

createRandomZombie("AAA")로 함수를 호출합니다. 해당 함수는 첫번째로 _generateRandomDna 함수를 호출하여 "AAA"값을 16자리의 숫자로 변환시켜주고 이를 randDna 변수에 저장시킵니다.  두번째로 _createZombie함수를 호출하고 zombies라는 구조체배열에 값("AAA", 변환된 16자리 숫자)을 저장하는 일을 하게 됩니다.

 

 

'Ethereum > Solidity' 카테고리의 다른 글

CrytoZombies_Lesson3_고급 솔리디티 개념  (0) 2019.08.16
CrytoZombies_Lesson2_심화문법  (0) 2019.08.16

댓글