[Ethereum] Solidity 문법 이해(1)

솔리디티 소스 파일

솔리디티 소스 파일의 확장자는 .sol이다. 파일 내에서 pragma solidity를 사용, 컴파일러 버전을 지정할 수 있다.

1
pragma solidity ^0.4.21

스마트 컨트랙트 구조

컨트랙트는 클래스와 비슷하여 상태 변수, 함수, 함수 변경자, 이벤트, 구조체, 열거형을 포함한다. 상속과 다형성 또한 지원한다.

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
// 1. 컨트랙트 선언
contract Sample {
// 2. 상태 변수 선언
uint256 data;
address owner;

// 3. 이벤트 정의
event logData(uint256 dataToLog);

// 4. 함수 변경자 정의
modifier onlyOwner() {
if(msg.sender != owner) throw;
_;
}

// 5. 생성자
function Sample(uint256 initData, address initOwner) {
data = initData;
onwer = initOwner;
}

// 6. 함수(메소드) 정의
function getData() returns (uint256 returned) {
return data;
}
function setData(uint256 newData) onlyOwner {
logData(newData);
data = newData;
}
}

데이터 위치

솔리디티의 변수는 컨텍스트에 따라 메모리 또는 파일시스템에 저장된다. 그러나 문자열, 배열, 구조체와 같은 복합 유형의 경우 이더 스토리지 또는 메모리를 유형에 추가해 재정의할 수 있다. 함수 매개 변수(리턴 매개 변수 포함)의 기본 위치는 메모리이고, 로컬 변수의 기본 위치는 스토리지이며 상태 변수의 경우 강제로 스토리지에 저장된다.

  • 상태 변수
    contract 최상위단에 선언된 변수(스토리지에 저장)
  • 로컬 변수
    함수 아래에 선언된 변수(스토리지에 저장 / memory 키워드로 메모리 저장 가능)

다른 데이터 유형은 무엇인가?

솔리디티는 정적(static) 유형의 언어이다. 변수의 데이터 유형은 미리 정의되어 있어야 한다. 솔리디티에서 변수의 범위는 함수이다. 즉, 변수 선언 위치와 상관없이 함수 안 어디에서든 사용할 수 있다. 데이터 유형은 다음과 같다.

  • bool(true or false)
  • uint8, uint16, uint24, …, uint256(부호 없는 8, 16, 24, … 비트의 정수)
  • ufixed0x8, ufixed0x16, …, ufixed0x256(부호 없는 실수)
  • fixed0x8, fixed0x16, …, fixed0x256(부호 있는 실수)
  • address(16진수 할당, 최대 20바이트 저장. 이더리움의 주소 제공.)
    • balancesend 속성 제공. balance는 계정의 잔액을 확인하고, send는 주소로 이더를 송금하는 데에 사용한다.

배열

솔리디티는 일반 및 바이트 배열을 모두 지원하며, 정적 배열 및 동적 배열, 다차원 배열을 지원한다. 일반 배열은 다음과 같이 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
contract sample {
// 동적 배열
// 배열 리터럴이 보일 때마다 새로운 배열 생성
// 배열 리터럴이 명시되어 있으면 스토리지에 저장되고, 함수 내부에서 발견되면 메모리에 저장된다.
int[] myArray = [0, 0];
function sample(uint index, int value) {
myArray[index] = value;

// myArray2는 myArray의 포인터를 저장!
int[] myArray2 = myArray;
// 메모리 내 고정된 크기의 배열
uint24[3] memory myArray3 = [1, 2, 99999];
// myArray4에 메모리에 있는 값을 스토리지에 할당할 수 없으므로 예외가 발생한다.
// memory를 이용, 메모리에 할당해 주어야 에러가 없다.
uint8[2] myArray4 = [1, 2];
}
}

책에 오류와 이해되지 않는 부분이 많아 이 블로그를 참고했다.


문자열

문자열의 길이는 언제나 동적으로 할당된다.

  • bytes
    원시 문자열(raw string)을 만드는 데 사용된다.
  • string
    UTF-8 문자열을 만드는 데 사용된다.
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
contract sample {
// 문자열 리터럴이 있으므로 스토리지에 저장
string myString = "";
// 문자열 리터럴이 없어서 myRawString은 memory에 있다.
bytes myRawString;

function sample(string initString, bytes rawStringInit) {
// 스토리지
myString = initString;

// myString2에 myString의 포인터를 저장
string myString2 = myString

// myString3은 메모리 내의 문자열
string memory myString3 = "ABCDE";

// 길이 및 내용 변경
// myString3은 메모리에 위치해서 에러 X
myString3 = "XYZ";
myRawString = rawStringInit;

// myRawString의 길이 증가
myRawString.length++;

// 메모리에 있는 "Example"을 스토리지의 myString에 저장하려 해서 에러 발생
string myString4 = "Example";
// 메모리에 있는 매개 변수(initString)을 스토리지의 myString5에 저장하려 해서 에러 발생
string myString5 = initString;
}
}


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



Share