본문 바로가기
Study/Solidity

Solidity - 크립토 좀비(2)

이더리움 블록체인은 은행 계좌와 같은 계정들로 이루어져 있다. 계정은 이더리움 블록체인상의 통화인 _이더_의 잔액을 가진다. 송금을 통해 돈을 주고받듯이, 계정을 통해 다른 계정과 이더를 주고받을 수 있다. 각 계정은 ID와 같은 특정 주소를 가지고 있다. Java에도 고유 ID와 같은 개념이 있기 때문에 비슷하다고 생각하면 된다. 

 

매핑은 솔리디티에서 구조화된 데이터를 저장하는 또 다른 방법이다. 매핑은 기본적으로 키-값(key-value) 저장소로, 데이터를 저장하고 검색하는 데 이용된다. 일반적인 프로그래밍 언어에서는 해시테이블이나 파이썬의 Dict와 유사하다고 보면 된다. 

mapping (uint => address) public zombieToOwner;
mapping (address => uint) ownerZombieCount;

함수처럼 mapping을 위와 같이 선언해줄 수 있다. mapping 뒤에 오는 자료형들은 key의 자료형이 uint라는 것을 의미하고, value의 자료형이 address라는 것을 뜻한다.

 

매핑값을 읽고 쓰기 위해서는 (매핑 이름)[키]의 형태로 접근할 수 있다. 

 

솔리디티에서 함수 실행은 항상 외부 호출자가 시작한다. 컨트랙트는 누군가가 컨트랙트의 함수를 호출할 때까지 블록체인 상에서 아무것도 안 하고 있다. 그렇기 때문에 전역 변수인 msg.sender를 통해 함수를 호출해 주어야 한다. msg.sender는 현재 함수를 호출한 사람의 주소를 가리키는 전역 변수이다. msg.sender를 활용하면 이더리움 블록체인의 보안성을 이용할 수 있게 된다. 누군가 다른 사람의 데이터를 변경하려면 해당 이더리움 주소와 관련된 개인키를 훔치는 것밖에는 방법이 없다.

function _createZombie(string _name, uint _dna) private {
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        zombieToOwner[id] = msg.sender;
        ownerZombieCount[msg.sender]++;
        NewZombie(id, _name, _dna);
    }

생성해준 매핑은 위 함수 처럼 사용해줄 수 있다. 새로운 좀비의 id가 반환되면 해당 id로 zombieToOwner 매핑을 업데이트하여 id에 대하여 msg.sender가 저장된다. 그다음, 저장된 msg.sender를 활용하여 ownerZombieCount를 증가시킬 수 있게 된다. 

 

Require를 사용하여 함수에서 특정 조건이 참이 아닐 때 에러 메시지를 띄우게 할 수 있다. if문과 비슷하다고 생각해주면 된다.

 

Java의 대표적인 기능 중 하나인 상속도 제공을 해준다. is를 통해 상속을 받을 수 있다. 

contract ZombieFeeding is ZombieFactory{

}

ZombieFactory를 상속받는 ZombieFeeding contract를 만들어줄 수 있다. 

 

솔리디티에는 변수를 저장할 수 있는 공간으로 storage와 memory 두 가지가 존재한다. 

 

Storage는 블록체인 상에 영구적으로 저장되는 변수를 의미한다. Memoryt는 임시적으로 저장되는 변수로, 컨트랙트 함수에 대한 외부 호출들이 일어나는 사이에 지워지게 된다. 하드 디스크와 RAM을 떠올리면 된다. 대부분의 경우 솔리 디티가 알아서 처리해주기 때문에 상관이 없지만, 함수 내의 구조체와 배열을 처리할 때는 이 키워드들을 사용해야 한다.

 

Internal과 External

 

public과 private 이외에도 솔리디티에는 internal과 external이라는 함수 접근 제어자가 있다. internal은 함수가 정의된 컨트랙트를 상속하는 컨트랙트에서도 접근이 가능하다는 점을 제외하면 private과 동일하다. external은 함수가 컨트랙트 바깥에서만 호출될 수 있고 컨트랙트 내의 다른 함수에 의해 호출될 수 없다는 점을 제외하면 Public과 동일하다. internal과 external 함수를 선언하는 것은 Private과 public함수를 선언하는 구문과 동일하다.

 

Interface

블록체인 상에 있으면서 우리가 소유하지 않은 컨트랙트와 상호작용을 하려면 interface를 정의해 주어야 한다. 인터페이스는 컨트랙트를 정의하는 것과 유사하다. 하지만, 다른 컨트랙트와 상호작용하고자 하는 함수만을 선언할 뿐 다른 함수나 상태 변수를 언급하지는 않는다. 또한, 함수 몸체를 정의하지 않아 중괄호를 쓰지 않고 함수 선언을 세미콜론으로 간단하게 끝낸다.

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
  );
}

getKitty라는 컨트랙트를 사용하기 위해 위와 같이 interface를 선언해 주었다. 여기서 놀라운점은 return값에 여러개의 값이 들어갈 수 있다는 점이다. 다른 언어 였다면 이렇게 여러개를 반환할 거면 객체로 둘러싸서 보내야 했는데, 솔리디티는 여러개의 값을 반환할 수 있께 해준다.

KittyInterface kittyContract = KittyInterface(ckAddress);

 

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

Solidity - 크립토 좀비(1)  (0) 2022.09.16