본문 바로가기

블록체인

solidity 언어 정리 - cryptozombies beginner

https://cryptozombies.io/ko/solidity

 

#1 Solidity Tutorial & Ethereum Blockchain Programming Course | CryptoZombies

CryptoZombies is The Most Popular, Interactive Solidity Tutorial That Will Help You Learn Blockchain Programming on Ethereum by Building Your Own Fun Game with Zombies — Master Blockchain Development with Web3, Infura, Metamask & Ethereum Smart Contracts

cryptozombies.io

 

cryptozombies [Solidity: Beginner to Intermediate Smart Contracts] 코스 완료.

여기서는 변수 선언부터 시작한 solidity의 간단한 내용들에 대해 배웠다.

c 언어, python 언어, javascript 언어 등 기본 내용은 안다고 가정하고 추가적인 특별한 내용들을 정리해본다.

 


기본 구조

solidity 기본 구조

 

1번 줄. pragma solidity ^0.4.19의 의미는 다음 코드의 버전을 의미한다. 가장 먼저 버전을 정의하고 감으로써 컴파일러 상의 충돌을 방지한다. 버전 내용은 ">= 0.7.0 < 0.9.0" 처럼 범위 형식으로 지정할 수도 있다.

 

3번 줄. import이다. 다른 언어와 비슷하다.

 

5번 줄. solidity는 class 대신 contract를 사용한다. contract 안에서 여러 함수를 정의하는 방식으로 코딩한다.

is는 상속이며 다중 상속이 가능하다.

 

6번 줄. 함수의 정의는 사진과 같은 방식으로 이루어진다. 저 사이에 있는 internal이라는 옵션이 특이해보인다. solidity는 여러 개의 반환값을 가질 수 있어서 returns(~~~)의 형식으로 반환 형태를 정의한다. 


함수 옵션

  • 접근 제어자
    • public : 자신이거나 상속받은 contract의 다른 함수에서 사용 가능 + 외부 계정에서 호출 가능
    • external : 자신이거나 상속받은 contract의 다른 함수에서 사용 불가능 + 외부 계정에서 호출 가능
    • internal : 자신이거나 상속받은  contract의 다른 함수에서 사용 가능 + 외부 계정에서 호출 불가능
    • private : 자신의 contract에서만 호출 가능

접근 제어자는 함수 뿐만 아니라 변수에서도 사용할 수 있다.

 

  • 권한 구분자
    • view : storage의 변수 읽기만 가능
    • pure : storage의 변수 읽기, 쓰기 권한 둘 다 없음
    • payable: 결제 가능

view나 pure의 경우 외부 계정에서 이 함수를 호출할 경우 gas가 무료다!!

이 때문에 코딩의 양상이 변하기도 한다고 언급되어 있다.

 


 

가스, 저장공간

solidity에서는 네트워크를 사람들이 악용하는 것을 방지하기 위해 (dos 공격처럼) gas라는 자원을 만들어 냈다. 공간을 차지하는 변수를 사용하거나 opcode가 실행되면, 돈이 나가는 식이다. 이를 통해 코드 작성자는 가스 최적화된 코드를 만들어야 한다. 

 

그만큼 solidity에는 메모리 자원이 중요하다. 그러한 이유로 관련된 선언도 따로 있는데, storage랑 memory가 있다. 함수 내에서 정의되는 기본적인 변수는 memory로 함수가 끝나면 지워지지만, 전역변수나 storage라고 처음에 선언한 변수는 solidity 자신 contract 내에 영원히 공간이 할당된다.

 

 


 

에러 핸들링

함수를 외부에서 실행할 수 있으니, 들어오는 매개변수가 의도치 않은 경우가 많다. 그러한 이유로 solidity에서는 에어 핸드링을 자주 이용해야 한다.

 

cryptozombies에서는 require와 assert를 언급했다. 주로 require를 사용하고 긴급할 때 assert를 사용한다.

둘의 큰 차이는 assert가 가스 비용을 소모한다는 것이다.

 

require(a==1); 처럼 사용하면 된다.


 

변수

최소 메모리 할당 단위가 256비트이다. 

기본 변수가 uint인데 이것은 uin256와 동일하다. uint16, uint32 등도 사용할 수 있지만 단독으로 사용하는 것은 가스만 아까울 뿐이고, 구조체 내에 사용해주면 좋다.

 

string이라는 변수는 유명하고, address라는 특이한 변수가 있다. 각자의 주소를 나타내는 변수.

msg.sender로 이 코드를 실행하는 주체의 address를 확인할 수 있다.

 

mapping(address => uint) public balances; 

이런 식으로 정의가능한 mapping이라는 변수도 있다. 다른 언어의 딕셔너리 혹은 맵과 동일한 기능을 한다.

위 변수에서 balances[msg.sender]이라는 코드를 이어서 작성하면, 자신만 접근이 가능한 공간 하나가 만들어진다. 이런 식으로 개인을 구분한다.

 

uint[] public hellos;

hellos.push(1);

위의 코드는 리스트이다. 다른 언어랑 유사하므로 넘어간다.


 

modifier / event

  • modifier
modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

 

위 코드는 라이브러리 ownable.sol의 내용 중 하나다.

function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) internal ownerOf(_zombieId) {

 

modifier은 위의 ownerOf처럼 함수에 붙여 사용이 가능하다. 그렇게 한다면 modifier의 '_'부분이 함수의 내용으로 대체되어 실행된다.

 

  • event
event NewZombie(uint zombieId, string name, uint dna);

NewZombie(id, _name, _dna);

 

event는 contract 내에 정의 후, 함수 내에서 사용할 수 있다. 사용한다면 외부에서 이 컨트렉트를 이용할 때 자바스크립트의 event listener처럼 이용 가능하다.

event가 너무 많이 일어난다면, uint indexed zombieId처럼 indexed를 앞에 설정한 후 이용할 때 필터링 하면 된다.


 

불변, 블록 등 블록체인만의 특이한 요소

  • 불변 : contract가 공식적으로 발행이 되면, 그 내용은 영원히 박제된다. 수정할 수도 없고 폐기할 수도 없다. 그러니 코드들을 신중하게 만들어야 한다. 이용한 라이브러리의 취약점이 발견되어 문제가 생길 수 있음과 시간이 지남에 따라 오류가 나타나 수 있음을 인지해야한다.
  • 투명성 : 블록체인은 모든 내용을 투명하게 공개한다. 코드를 몰라서 나타나는 은둔 보안을 없앤다. 코드 뿐만 아니라, 변수들의 내용까지 공개되니 관련해서 보안을 잘 설계해야 한다.
  • 노드들 : solidity의 코드가 업로드되면, 전세계의 노드들이 자신의 EVM으로 코드를 실행하고 결과를 공유한다. 이러한 방식 때문에 random 값을 조작하거나, 다른 사람보다 먼저 프로그램 실행 결과를 받는 등 신기한 취약점들이 나타난다.