Solidity 솔리디티 기본 개념 배우기(feat.crypto zombie Lesson 1)
본문 바로가기
Block Chain

Solidity 솔리디티 기본 개념 배우기(feat.crypto zombie Lesson 1)

by 쏠수있어ㅤ 2022. 9. 13.
반응형

 

  1. 기본 구조  

Solidity 는 "contracts" 안에 캡슐화 되어 있다. 하나의 Contract는 하나의 기본 블럭이며 모든 변수들과 함수들은 이 Contract 안에 들어 있다. 

 

contract 작성 전 Pragma version을 작성해주어야 한다. 컴파일러 버전이 업그레이드되며 다르게 적용되는 규칙으로 나오는 에러를 예방할 수 있다. 

 

 

 

  2. 변수   

State variables은 영원히 contract storage에 저장된다. 즉, 이 변수들은 Ethereum blockchain 상에 적히게 된다는 뜻 ! 블록체인에 적힌다는 것이 곧 영원히(?) 유지되기 때문

 

Solidity에서 uint (unsigned integers) 는 256-bit unsigned integer 이다. uint8, uint16, uint32으로 선언할 수 있지만 일반적으로 uint를 사용한다. (특이한 케이스 제외)

 

struct은 여러개의 속성을 가진 데이터 타입을 만들어 낸다. 

    struct Zombie {
        string name;
        utin dna;
    }

 

 

 

  3. 배열  

solidity에는 두 가지의 arrays 종류가 있다. 

- fixed : 요소의 수가 고정된 배열

- dynamic : 요소의 수가 유연한 배열

 

uint[2] fixedArray;   // 2개의 수를 가지는 고정 배열 
string[5] stringArray; // 5개의 string 값을 가지는 고정 배열 
uint[] dynamicArray;   // 고정되지않고 계속해서 값이 커질 수 있는 배열
Zombie[] zombieArray;  // Zombie struct 로도 타입을 지정할 수 있다.

 

public Arrays - "public"이 배열에 붙게 된다면 solidity는 자동적으로 "getter" 매서드를 생성할 것이다. 

 

 

 

  4. 함수  

Functions 

solidity에서 함수는 아래와 같이 선언한다. 

function eatHamburgers(string memory _name, uint _amount) public {

}

함수의 이름 : eatHamburgers

함수 공개 여부 : public 

인자값 2개 

- 첫번째 매개변수 : _name (type = string, _name, 변수가 저장되는 위치 = memory) 

- 두번째 매개변수 : _amount (type = uint, _amount)

 

*  매개변수의 이름 정하는 convention 은 보통 "_" underscore를 앞에 붙이는 것! 

* 변수가 저장되는 위치는 타입이 reference types = arrays, structs, mappings, strings인 경우 정해주어야 한다.  

 

그 이유는.... By value : solidity 컴파일러가 파라미터 값의 새로운 복사본을 만들어 함수에 전달한다. 최초의 파라미터 값이 변할 걱정이 없다. 

By reference : 함수가 기존의 변수를 참조하는 값으로 불려지므로 만약 함수가 이 값을 변경시키는 코드가 있다면 기존 값 또한 달라지게 된다. 

 

 

지금까지의 내용과 위 만든 struct Zombie로 좀비를 생성해서 zombies 배열에 push, 담기 코드 👇👇

pragma solidity >=0.5.0 <0.6.0;

contract ZombieFactory {

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

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;

    function createZombie(string memory _name, uint _dna) public {
        zombies.push(Zombie(_name, _dna));
    }

}

이제 위 코드에 계속해서 배우는 내용을 덧붙일 예정이다 

 

 

Pivate vs Public Functions

public 🗣 어디에 계신 누구나 이 함수를 호출하고 실행시켜도 됩니다~~~ 

private 🗣 이 함수가 포함된 contract 내에 있는 함수들만 Only 호출하고 실행가능입니다~~~ 아 그리고 Private 함수는 함수명 앞에 "_" 붙여주세요~~~오옥 

 

solidity에서 함수는 디폴트값으로 public이어서 누구나 (또는 다른 contract도) 해당 함수를 call하고 실행시킬 수 있다. 오남용을 줄이기위해 습관적으로 함수 작성할 때 private로 하고 대외적으로 만들고 싶은 경우에만 public으로 작성하기 !

 

 

값을 return 하는 함수

solidity에서 함수는 return하는 값의 타입도 함께 표시해준다. 

string greeting = "What's up dog";

function sayHello() public returns (string memory) {
  return greeting;
}

 

 

Function modifiers

view & pure

greeting을 return하는 위의 sayHello 함수는 in the app, 앱 안에서 어떠한 데이터에 변화를 주지 않는다. 접근하고 읽기는 하되 Update Or Delete, 수정 또는 삭제는 없다. 이런 경우 위의 함수를 view (그냥 보는) modifier 로 표시할 수 있다. 

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

하지만 다른 곳 In the app 에서 데이터를 읽어오지도, 접근조차하지 않는 함수라면 ? pure modifier로 표시를 해준다. 

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

위의 _multiply 함수는 private 함수여서 함수명 앞에 "_"가 붙었다. 이 함수의 매개변수 a, b 를 받고 둘을 곱한 값을 return한다. 이 함수는 본인이 받는 매개변수로만 값을 리턴하고 다른 함수를 호출하거나 데이터를 읽어오거나 하지 않으므로 pure 이다. 

 

 

 

 

  5. keccak256   

Ethereum은 "keccak256"이라는 (SHA3 버전의) 해시 함수가 빌트인으로 있는데 이 함수는 input값을 랜덤한 256bit의 16진수의 수로 변환시킨다. Input값의 아~주 작은 차이라도 결과값은 180도 달라진다. keccak256은 input값으로 bytes타입의 단 하나의 매개변수를 필요로 하기 때문에 우리가 매개변수를 pack 시켜서 주어야한다. 

//6e91ec6b618bb462a4a6ee5aa2cb0e9cf30f7a052bb467b0ba58b8748c00d2e5
keccak256(abi.encodePacked("aaaab"));
//b1f078126895a1424524de5321b339ab00408010b7cf0e6ed451514981e58aa9
keccak256(abi.encodePacked("aaaac"));

"b" / "c" 만 다른데 결과값은 아예 다르다. 

 

 

 

 

 

  6. typecasting   

데이터 타입을 변경시키는 기능이다. 

uint8 a = 5;
uint b = 6;

uint8 c = a * b;
// throws an error because a * b returns a uint, not uint8

uint8 c = a * uint8(b);
// we have to typecast b as a uint8 to make it work

a는 uint8이고 b는 아무것도 안쓴 디폴트값으로 256으로 설정되어 있다. unit8 타입인 c에 a * b를 하려니 에러가 난다. b의 값이 uint256이기 때문이다. 이 경우 uint8(b) 로 데이터의 타입을 맞춰주면 에러가 나지 않는다. 

 

 

 

 

  7. Events  

event란 contract를 작성해서 배포한 Blockchain 상에서 일어난 일을 app front-end에게 어떤 "이벤트"가 생겼다고 알려주는 것입니다. 무언가 일이 생기면 프론트엔드가 해당 사건 "듣고" 바로 "take actions" 어떤 액션을 취할 수 있도록!

 

example ) solidity smartcontract 

// declare the event
event IntegersAdded(uint x, uint y, uint result);

function add(uint _x, uint _y) public returns (uint) {
  uint result = _x + _y;
  // fire an event to let the app know the function was called:
  emit IntegersAdded(_x, _y, result);
  return result;
}

코드를 보면 emit IntegersAdded(_x,_y,result); 는 그냥 위에 event를 emit 시키는 것뿐이다. 블록체인 상에서는 어떤 변화가 생기는 것이 아니고 프론트엔드에게 알려 해당 이벤트에 맞는 변화를 주라고 알려주는... 존재 

 

frontend 코드

YourContract.IntegersAdded(function(error, result) {
  // do something with result
})

 

 

 


 

 

크립토 좀비 Lesson 1 최종 코드

pragma solidity >=0.5.0 <0.6.0;

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;

    function _createZombie(string memory _name, uint _dna) private {
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        
        emit NewZombie(id, _name, _dna);
    }

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

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

}

 

위의 전체코드 해석은

이전에 자세하게 뜯어보고 공부한 여정(?)을 담은 글을 참조하시면 좋을 것 같습니다! 

=> 크립토좀비 lesson1 해설보기

반응형

댓글