😀 솔리디티 기본 문법 정리
KMOOC 내의 포항공대 '스마트 계약 및 응용' 강의 중 솔리디티 기본 문법 내용을 정리해보았다.
일부 내용은 urclass에서 참조했다.
스마트 컨트랙트에 대한 신뢰를 높이고, 저작권 문제를 해소하기 위해 코드 최상단에 SPDX 라이센스를 주석으로 명시. SPDX 라이센스 리스트
// SPDX-License-Identifier: MIT
컴파일러의 특정 기능을 활성화 하는 데 사용됨.
다른 솔리디티 파일에 있는 코드를 사용할 수 있게 해줌 → 코드의 모듈화가 가능해짐
Contract 내부에서 선언된 변수 중 function 외부에서 선언된 변수
contract storage에 저장됨. → 모든 function이 접근 가능, function이 변경한 값은 계속해서 저장됨.
Storage: 블록체인에 기록되어 영구적으로 값이 유지되는 데이터 영역
Memory: 프로그램이 동작되는 동안에만 값을 기억하고, 종료되면 값을 잃는 데이터 영역. 대체로 임시값들이 저장됨. (예: function 내에서만 쓰는 파라미터 등)
Boolean
true(default)/false
정수(int, uint)
signed integers: 부호 있음
unsigned integer: 부호 없음
8bit ~ 256bit까지 지원 (예: int8: -128 ~ 127, uint16: ~65,535)
Byte
데이터를 바이너리 형태로 저장하기 위해 byte타입을 지원함.
bytes1 ~ bytes32까지 정해져 있음.
크기가 정해져 있기 때문에 fixed-sized byte array라고도 불림.
정해진 바이트 크기와 다르면 에러가 남.
cf.) bytes 타입: dynamically sized byte array - 참조형(reference) 타입임
주소(Address)
20byte 크기의 이더리움 어드레스
balance property를 갖고 있어 이더 잔액을 확인할 수 있음.
이더를 옮기는 transfer, send 메소드 지원(address.transfer(amount)
, address.send(amount)
)
열거형 (Enumerations)
내부적으로는 정수 값으로 구현됨.
Reference 타입은 EVM 내에서 Storage, Memory 중에서 어디에도 저장될 수 있기 때문에, 어디에 저장할 것인지 명시해야 한다. (data location)
데이터를 저장하는 영역에 연속되어 저장되어 있는 값의 첫 번째 메모리의 주소를 값으로 가지는 변수 타입.
배열(Arrays)
동일한 타입의 여러 항목을 저장할 때 사용
Fixed Array: 배열 선언 시 크기가 결정됨
Dynamic Array: 실행 중에 크기가 결정됨
2차원 배열 시 다른 언어의 순서와 반대임 (예: array[1][2] → array[2][1])
문자열(String)
Array의 특별한 형태, bytes array에 기반한 string 타입
Array와 달리 index, push, length, concat 등을 지원하지 않기 때문에 bytes array로 변환해야 함.
구조체(Struct)
서로 다른 타입을 하나로 묶어서 사용.
매핑(Mappings)
key-value pair를 저장할 때 사용되는 데이터 타입.
대부분의 데이터 타입을 key 타입으로 쓸 수 있지만, contract, mapping, struct 타입처럼 복잡한 타입은 key 타입이 될 수 없음. (value로는 사용 가능)
storage 영역에만 저장됨.
함수의 parameter나 return type으로 사용될 수 없음.
key 값 자체가 mapping에 저장되지 않기 때문에, key의 hash 값을 이용해 value에 접근함.
솔리디티에서 현재 이더리움 블록체인 정보(현재 블록정보, 트랜잭션 정보 등)를 제공하는 변수
block
블록 관련 정보를 제공함.
block.coinbase
: 현재 블록을 채굴한 account의 주소를 알려줌block.difficulty
: 현재 블록 작업 증명의 어려운 정도block.gaslimit
: 현재 블록이 사용 가능한 최대 gas값block.number
: 블록 넘버block.timestamp
: 채굴 시 기록된 시간 정보msg
컨트랙트는 외부 컨트랙트에서 호출하거나 다른 컨트랙트에서 message call을 하면 실행하는데, 이때 컨트랙트에게 전달된 메시지 정보를 msg object를 통해서 읽을 수 있음.
msg.sender
: contract를 호출한 account의 주소가 들어있음.msg.value
: 메시지를 통해 전달된 이더가 wei unit으로 담겨있음.msg.data
: contract로 넘겨진 data가 담겨있음.msg.sig
: data의 첫 4바이트 → 어떤 메소드가 불리는지 알 수 있음.tx
트랜잭션 관련 정보를 제공함
tx.price
: 현재 트랜잭션의 gas 비용을 알려줌tx.origin
: 트랜잭션의 시작 외부소유 어카운트의 address를 알려줌Address
address 관련 정보를 제공함
address.balance
: 잔고를 보여줌address.transfer(amount)
: 이더를 해당 어드레스로 보냄address.send(amount)
: 이더를 해당 어드레스로 보냄address.call(payload)
address.callcode(payload)
address.delegatecall()
상태 변수 접근 수준
internal(default)
: 선언된 contract와, 해당 contract 로 부터 상속받은 contract에서만 사용할 수 있음.private
: 선언된 contract에서만 사용 (그럼에도 이더리움 public 블록체인이기 때문에 데이터는 공개되어 있음.)public
: 외부에서도 접근할 수 있음. 특별히 solidity 컴파일러가 getter 메소드를 생성해 줌.constant
: 값에 변화가 없음. 처음에 값을 정하지 않거나, 변경을 하려고 하면 에러가 나게 됨.함수의 구조
이름으로 함수를 호출할 수 있음. 이름이 없는 함수는 fallback or default function이라고 함.
함수에 넘겨질 argument들의 이름과 타입을 선언함.
함수 접근 수준 (Visibility)
Public
: 다른 contract나 외부 계정에서 불릴 수 있음Private
: 현재 contract에서만 불릴 수 있음Internal
: 자신 외에도 자신으로부터 상속받은 contract로 부터 불릴 수 있음.External
: public과 비슷, contract 내로부터 불릴 경우 ‘this’라는 키워드를 붙여야 함.Qualifier ( view, pure, payable )
함수가 contract의 내부 상태(state variable)을 변경할 수 있는 능력 선언, 다른 언어들에서 찾아보기 힘든 개념임.
view
: storage 내의 variable 읽기O, 변경Xpure
: storage 내의 variable 읽기X, 변경Xpayable
: 결제를 처리할 수 있다는 선언. 만약 선언되지 않은 함수에 이더를 보내면 거부됨.returns
반환하는 타입 선언
생성자 함수(constructor)
selfdestruct
Require
: 주어진 조건을 검사해서 이를 만족시키지 못하면 exception을 발생시켜 이전 상태로 되돌림. gas 반환 ORevert
: Require와 유사, control flow가 복잡할 때 (예: 중첩 if) 편리Assert
: 어떤 값을 변경하고 나서 그 값이 조건을 만족하는지, 절대로 발생하면 안되는 상황인지를 검사. gas 반환 X주로 require, revert는 함수 앞쪽에서 pre-condition을 확인하는데 사용, assert는 뒷부분에서 post-conditon을 확인하는데 사용
상속을 통해 두 컨트랙트 간에 parent-child relation을 만들어 줌. parent 컨트랙트에서 선언한 함수와 상태 변수들을 child 컨트랙트에서도 사용할 수 있게 해줌. “is” 키워드를 이용해 상속. 다중 상속(multiple inheritance)도 가능. 이때 parent contract 나열 순서가 중요. 가장 뒤에 명명된 컨트랙트가 더 가까운 parent임.
생성자 함수 선언 시, 컨트랙트가 생성될 때 생성자 함수가 실행되며 컨트랙트 상태를 초기화 함.
selfdestruct: 현재 컨트랙트를 소멸시킴. 남은 이더를 주어진 address로 보냄.
selfdestruct(컨트랙트 생성자의 주소);
- contract가 작업을 수행하는 동안 로그를 남길 수 있게 해주는 기능.
- contract의 메소드가 불렸는지, contract의 내부의 값이 어떻게 변했는지 등을 알 수 있어 디버깅이 수월함.
- 블록체인 밖의 시스템과의 연동을 가능하게 함.
- 트랜잭션이 끝난 후 → 트랜잭션의 결과가 담긴 ‘Transaction Receipt’가 만들어짐
contract coinTransfer {
// event 선언: 이벤트명(파라미터유형1 파라미터1, 파라미터유형2 파라미터2, ...);
// variable의 이름을 명시할 필요는 없음. (타입만 나열해도 ok)
// indexed라고 명시해서 선언 -> hash table에 저장되어 나중에 event를 쉽게 찾을 수 있음
event Transfer(address from, address to, uint256 value);
function transfer(address to, address amount) {
// event가 'emit'을 통해 불려짐, 값들이 블록체인에 저장됨.
// emit 이벤트명(인자1, 인자2 ...)
emit Transfer(msg.sender, to, amount);
}
}
라이브러리 이름.메소드이름()
, using 라이브러리 이름 for 데이터타입