[Ethereum] Solidity 문법 이해(4)

함수 변경자

_;를 만나면 다음에 나열된 함수를 실행하라는 의미이다. 그리고 _; 뒤에 있는 문장은 차곡차곡 스택에 쌓인다. 도대체 이걸 왜 만든 건지 모르겠다. (심지어 책 예시에 myModifier4는 적혀 있지도 않다. 실수인 듯…) 아무튼, 예시는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
contract sample {
int a = 90;

modifier myModifier1(int b) {
int c = b;
_;
c = a;
a = 8;
}
modifier myModifier2 {
int c = a;
_;
}
modifier myModifier3 {
a = 96;
return;
_;
a = 99;
}
modifier myModifier4 {
int c = a;
_;
}

function myFunction() myModifier1(a) myModifier2 myModifier3 myModifier4 returns (int d) {
a = 1;
return a;
}
}

다음과 같은 순서로 실행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// myModifier 1
int c = b;
// myModifier 2
int c = a;
// myModifier 3
a = 96;
return;
// myModifier 4
int c = a;
// myFunction
a = 1;
return a;
// myModifier 2는 _; 이후 명령문이 없어서 skip
// myModifier 3
a = 99;
// myModifier 1
c = a;
a = 8;

폴백(fallback function) 함수

컨트랙트는 한 개의 이름 없는 함수를 가질 수 있다. 이것이 폴백함수이며, 이 함수는 인자를 가질 수도, 리턴 값을 줄 수도 없다.

폴백 함수는 트랜잭션이 컨트랙트에 이더를 송금했으나 메소드를 호출하지 않은 경우에도 실행한다. 이런 경우, 함수를 가능한 싸게 만드는 것이 중요하다.

이더를 받고 싶은 컨트랙트의 경우 폴백 함수를 구현해야 한다. 폴백 함수가 정의되지 않았다면 예외를 발생시키고, 이더를 돌려 보낸다.

1
2
3
4
5
contract sample {
function() payable {
// 누구로부터 얼만큼의 이더가 전송되었는지 기록한다.
}
}

라이브러리

라이브러리는 특정 주소에 한 번 배포되면 다양한 컨트랙트에서 재사용할 수 있다. 라이브러리 함수가 호출되면 코드가 호출한 컨트랙트의 컨텍스트에서 실행된다. 즉, 호출하는 컨트랙트의 저장소에 접근할 수 있다. 라이브러리는 상태 변수를 가질 수 없고, 상속을 지원하지 않으며, 이더를 받을 수도 없다.

1
2
3
4
5
6
7
8
9
10
library math {
function addInt(int a, int b) returns (int c) {
return a + b;
}
}
contract sample {
function data() returns (int d) {
return math.addInt(1, 2);
}
}

for 사용(반복문 X)

using A for B; 지시자는 라이브러리 함수를 attach 하는 데 사용할 수 있다. 이 함수는 첫 번째 매개변수로 호출된 객체를 받는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
library math {
struct myStruct1 {
int a;
}
struct myStruct2 {
int a;
}

// 참조할 수 있도록 's' 위치 저장소를 만들어야 한다.
// 그렇지 않다면 myStruct1 대신 다른 myStruct1 인스턴스에 접근하거나 수정하게 된다.
function addInt(myStruct1 storage s, int b) returns (int c) {
return s.a + b;
}
function subInt(myStruct2 storage s, int b) returns (int c) {
return s.a - b;
}
}
contract sample {
using math for *;
math.myStruct1 s1;
math.myStruct2 s2;

function sample() {
s1 = math.myStruct1(9);
s2 = math.myStruct2(9);
s1.addInt(2);
// addInt의 첫 매개변수가 myStruct1인데, s2는 myStruct2 유형이다.
// 고로, mySturct2에 attach되지 않아 컴파일 오류가 발생한다.
// s2.subInt(1);은 정상 동작한다.
s2.addInt(1);
}
}


이 포스트의 모든 내용은 이더리움을 활용한 블록체인 프로젝트 구축(에이콘) 책을 참고하여 작성되었습니다.


Share