Lesson 2 좀비가 희생물을 공격하다.
Chapter 1 개요
Chapter 2 Mapping 과 Address
address는 솔리디티에만 있는 독특한 자료형으로서, 지갑주소 등을 저장하는 타입이다.
//cryptozombies 예제코드
mapping (address => uint) public accountBalance;
mapping (uint => string) userIdToName;
매핑은 일종의 객체 비스무리한 녀석인데, 위 코드 중 첫 번째처럼 작성한다면, accountBalance의 address를 포인팅한 후 uint를 할당할 수 있다.
즉, 아래와 같이 사용할 수 있다.
mapping (address => uint) public accountBalance;
accountBalance[ADDRESS] = UINT;
물론, 대문자로 쓴 ADDRESS와 UINT 부분에는 해당 자료형을 갖는 실제 값이나 변수를 써야한다.
Chapter 3 Msg.sender
msg.sender는 스마트컨트랙트를 호출한 대상(사람 혹은 스마트컨트랙트)의 주소를 반환하는 내장 전역 메서드이다.
Solidity에서 스마트컨트랙트는 호출이 있기 전까지 아무것도 하지 않고 있으므로 스마트컨트랙트가 작동했다는 것은 반드시 msg.sender 값의 존재를 담보한다고 볼 수 있다.
//cryptoZombies 예시 코드
mapping (address => uint) favoriteNumber;
function setMyNumber(uint _myNumber) public {
favoriteNumber[msg.sender] = _myNumber;
}
function whatIsMyNumber() public view returns (uint) {
return favoriteNumber[msg.sender];
}
매핑 타입 선언
위 코드의 경우 address 를 key로, uint를 value로 가지는 mapping인 favoriteNumber 라는 녀석을 생성한다. 이는 JS로 보면 일종의 오브젝트로 봐도 무방할 듯하다.
다만 특이한 점은, 이 mapping을 이용할 때이다. JS와는 확실히 다른 모습을 보인다.
매핑의 value 설정
setMyNumber 라는 함수에서 favoriteNumber 매핑을 불러와 작동시키는데, 이 때 msg.sender라는 address를 [ ]안에 집어 넣고, 할당 연산자를 통해 value 값을 전달하는 모습이다.
매핑의 활용
whatIsMyNumber 함수에서는 favoriteNumber에 msg.sender를 전달하여 앞서 setMyNumber에서 할당한 value 값을 리턴한다.
Chapter 4 Require
require는 일종의 조건문이다.
require가 참인 경우 함수는 진행되고, require가 거짓인 경우 함수는 에러메세지를 띄우며 멈춘다.
또한, Solidity에서는 스트링에 대한 일치여부를 비교/확인하는 방법이 없다. 따라서 해시값으로 변환하여 일치하는지 확인하는 것이 관례이다.
if는 만약 이런 경우~ 의 의미라면, require는 이 조건이 있어야만 실행한다는 정도의 뉘앙스 차이가 있다.
다만, 이 챕터에서 주목할만한 점은 === 로 일치 조건을 표현했더니 패스되지 않았다는 점이다. == 만 지원하는건지 확인이 필요했고, 답을 찾았다.
보다시피 === 는 지원하지 않는다. 이는 === 라는 연산자 자체가 자바스크립트의 장점이자 단점인 '타입'에 대한 유연성에서 비롯된 것이기 때문인 듯 하다. 즉, 솔리디티는 자바스크립트에 비해서는 훨씬 타입에 대해 엄격하므로 === 가 있을 이유가 없지 않았나 생각해본다. 어디까지나 뇌피셜.
Chapter 5 Inheritance
스마트컨트랙트는 상속이 가능하다.
contract Dog {
function a() public {}
}
contract Mery is Dog {
function b() public {}
}
is 를 통해 상속을 받는다.
그리고 다른 언어들과 마찬가지로 상속 받은 Mery는 부모 스마트컨트랙트의 함수도 사용할 수 있다.
솔리디티의 상속은 JS보다는 Python이나 자바와 더 유사한 듯 하다. 애초에 JS는 상속 개념이 좀 독특하니..
Chapter 6 Import
import를 통해 다른 파일을 불러 올 수 있다.
Chapter 7 Storage vs Memory
Storage 는 HDD 혹은 SSD 와 같은 영구 저장소이다.
Memory 는 RAM과 같은 임시 저장소이다.
//cryptozombies 예제코드
contract SandwichFactory {
struct Sandwich {
string name;
string status;
}
Sandwich[] sandwiches;
function eatSandwich(uint _index) public {
Sandwich storage mySandwich = sandwiches[_index];
mySandwich.status = "Eaten!";
Sandwich memory anotherSandwich = sandwiches[_index + 1];
anotherSandwich.status = "Eaten!";
sandwiches[_index + 1] = anotherSandwich;
}
}
솔리디티의 기본 문법을 숙지 하지 못했다면, 다소 헷갈릴 수 있는 코드라고 생각한다.
솔리디티는 기본적으로 '변수타입 변수명' 이라는 점을 잊지말자. 그리고 struct는 사용자정의타입을 선언하는 것과 같다.
즉, struct를 통해 만든 사용자정의타입인 Sandwich 타입을 Array로 구성한 것이 sandwiches,
할당된 대상에 대해서 storage상의 데이터를 직접 건드릴 수 있는 권한을 가진 것이 mySandwich 변수,
할당된 대상에 대해서 memory상의 데이터를 직접 건드릴 수 없고, 임시적으로만 건드리는 것이 anotherSandwich 변수이다. cryptozombies 사이트에서는 storage와 memory를 포인터 개념으로 접근하는 듯한데 이런 접근도 좋은듯. 이러한 접근이 일반적인 것인지는 모르겠다.
storage 와 memory는 일종의 admin 권한 내지는 sudo 권한의 부여 여부로 구분지어 생각해도 될 것 같다. 블록체인 특성상 한 번 온체인된 데이터는 수정하기 힘들기 때문에 명시적으로 양 자를 구분하여 선언하도록 언어가 구성되어 있는 듯 하다.
Chapter 8
냉무
Chapter 9 private과 public 이외의 또 다른 함수 접근 제어자로서의 Internal 과 External
Internal은 상속받은 스마트컨트랙트에서도 접근할 수 있는 함수를
External은 오직 해당 스마트컨트랙트 밖에서만 접근할 수 있는 함수를 뜻함.
Chapter 10 다른 컨트랙트와 상호작용하기
일종의 API 연결 내지는 fetch 기능이라고 볼 수 있겠다.
관행적으로 컨트랙트의 이름에 Interface라는 것을 포함하여 정의하는데, 어쨌거나 이것도 선언자는 contract이므로, 당연히 구조도 유사하다. 다만 이미 다른 컨트랙트에 존재하는 함수 따위를 가져와서 뼈대만 남겨 정리하는 것에 가까우므로 구체적인 함수 내용은 쓰지 않는다. 즉 { } 부분이 없다. 함수 내용이 없는 함수가 존재할 때 컴파일러가 인터페이스로 인식하는 듯 하다.
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
) {
Kitty storage kit = kitties[_id];
// if this variable is 0 then it's not gestating
isGestating = (kit.siringWithId != 0);
isReady = (kit.cooldownEndBlock <= block.number);
cooldownIndex = uint256(kit.cooldownIndex);
nextActionAt = uint256(kit.cooldownEndBlock);
siringWithId = uint256(kit.siringWithId);
birthTime = uint256(kit.birthTime);
matronId = uint256(kit.matronId);
sireId = uint256(kit.sireId);
generation = uint256(kit.generation);
genes = kit.genes;
}
즉, 위와 같은 형태의 크립토키티의 getKitty 함수를 가져와서 연결 및 사용하고 싶다면 아래와 같이 써야한다.
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
);
}
Chapter 11
하지만 구체적인 contract의 주소까지 전달해줘야한다. 왜냐하면 같은 이름의 인터페이스가 무궁무진하게 존재할 것이기 때문
address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
KittyInterface kittyContract = KittyInterface(ckAddress);
따라서 KittyInterface 형태의 kittyContract 라는 것을 선언한 뒤, 이 KittyInterface에 크립토키티의 스마트컨트랙트 주소를 전달해주면, 비로소 솔리디티 컴파일러가 해당 스마트컨트랙트 주소에서 KittyInterface에 선언된 내용을 참조하여 getKitty를 우리 컨트랙트에서 활용할 수 있게 해준다. 그리고 그 때 우리는 kittyContract로 받아와야하고, 그 타입 형태는 역시 KittyInterface이기 때문에 코드가 위와 같이 요구된다.
Chapter 12 다수의 리턴값 핸들링
//cryptozombies 예제코드
function multipleReturns() internal returns(uint a, uint b, uint c) {
return (1, 2, 3);
}
function processMultipleReturns() external {
uint a;
uint b;
uint c;
// 다음과 같이 다수 값을 할당한다:
(a, b, c) = multipleReturns();
}
// 혹은 단 하나의 값에만 관심이 있을 경우:
function getLastReturnValue() external {
uint c;
// 다른 필드는 빈칸으로 놓기만 하면 된다:
(,,c) = multipleReturns();
}
특이하게도 솔리디티는 다수의 리턴값을 가지기도 한다. 이 경우 processMultipleReturns 함수에서처럼 1:1대응관계로 할당하거나 getLastReturnValue에서처럼 어느 특정 값만을 할당할 수도 있다.
특히 위처럼 함수를 각각 internal함수와 external 함수로 구분하는 경우, internal 함수의 중간 프로세싱을 블랙박스처리하고 결과값만 접근가능하게 할 수 있다.
Chapter 13 if문
js의 if문과 동일하다.
Chapter 14
Chapter 15
'Learning-Log > Computer Science' 카테고리의 다른 글
[Ubuntu] 압축파일(zip, rar) 풀기 (0) | 2023.04.01 |
---|---|
[Solidity] CryptoZombies : Lesson 3 정리 (3) | 2023.04.01 |
[Ethereum] 이더리움 입문자를 위한 사이트, CryptoZombies (0) | 2023.03.25 |
[Express.js] Cookie와 Session - BackEnd와 FrontEnd의 통신 수단 (0) | 2023.01.20 |
[Express] res.sendFile(path.join(__dirname, '~~'));에 대하여 (0) | 2023.01.12 |