solidity 문법 총정리, 이더리움 네트워크 개발 블록체인 암호화폐

DongJoo Kwak·2022년 8월 9일
0

블록체인 개발

목록 보기
4/4

다양한 암호화폐 증권 퀀트 게시물 -> https://quantpro.co.kr

📌solidity 문법

=>EVM(이더리움 가상 머신)을 대상으로 하는 프로그래밍 언어

=>EVM은 솔리디티로 작성된 스마트 계약을 이해하지 못하기 때문에 솔리디티로 작성된 코드를 솔리디티 컴파일러로 컴파일을 해서 EVM이 인식할 수 있는 바이트 코드를 만들고 EVM은 이 바이트 코드를 실행

솔리디티코드 -> 솔리디티 컴파일러 -> 바이트 코드 -> EVM에 배포하고 실행

🌳특징

=>정적 타입 언어: 메모리 할당을 받기 전에 메모리 할당을 위한 자료형이 먼저 선언되어야 하고 한 번 자료형을 결정하면 중간에 변경할 수 없음
=>객체 지향 언어
=>한번에 실행되어야 하는 문장을 구분하는 기호는 ;
=>확장자는 sol

🌳구성

=>pragma, comment, import, contract, library, interface

1) pragma

=>컴파일러 버전 지정 지시자
pragma solidity 버전
=>가장 상단에 작성하는 것이 관례인데 최근에는 가장 상단에 라이센스를 기재하라고 함
=>라이센스 정보를 기재하지 않으면 경고 발생
=>버전은 3자리로 구성
첫번째 자리는 현재까지 0
두번째 자리가 메이저 빌드 번호
세번째 자리는 마이너 빌드 번호
=>버전 앞에 ^를 추가하면 마이너 빌드 번호를 무시하고 메이저 빌드 번호에서 가장 높은 마이너 빌드를 사용해서 컴파일

2)comment - 주석

=>컴파일러가 해석하지 않는 문장
// : 단일 행 주석
/ ~ /: 여러 줄 주석

///: 문서화에서 한 줄 주석
/* ~ /: 문서화에서 여러 줄 주석

3)import

=>다른 솔리디티 파일의 내용을 사용하고자 하는 경우 사용
import 파일명;

4)계약

=>구성 요소
상태 변수
구조체
열거형
함수
수정자
이벤트

🌳 솔리디티 데이터 타입

1)Value Type: 값을 저장

=>bool: true 나 false
=>uint: uint8 ~ uint256
=>int: int8 ~ int256
=>bytes: 고정된 크기의 바이트 배열을 표현하는데 byte1 ~ byte32
=>enum(나열형 상수)
=>address: 이더리움 환경의 계정 주소

2)Reference Type: 데이터의 참조를 저장

=>배열
=>구조체
=>mapping
=>string

🌳Literal

=>이름없는 값 자체로 존재하는 데이터
=>정수: 1, 10, 1000
=>문자열: 작은 따옴표 또는 큰 따옴표를 붙이는데 일반적으로 ""
=>주소 리터럴은 0x를 앞에 붙여서 표현
=>16 진수는 hex 키워드를 붙임

🌳상태 변수

=>데이터를 영구적으로 저장하는 목적의 변수
=>계약 내에 만들어지지만 특정 함수에 속하지 않은 변수
=>한정자(qualifier - 접근 지정자)
internal: 계약 내부 와 상속받은 계약에서 사용하도록 해주는 한정자로 생략하면 internal

private: 선언한 계약 내에서만 사용

public: 계약 내부 나 외부에서 모두 접근이 가능한데 solidity에서는 public 으로 상태 변수를 만들면 getter 함수를 생성해 줌

constant: 데이터를 변경할 수 없도록 생성하고자 하는 경우 사용
Macro 와 유사
constant 는 메모리를 할당하는 시점에 값으로 전부 치환

🌳function

=>이더리움은 상태 변수의 현 상태를 유지하며 거래를 실행해 상태 변수의 값을 변경
=>계약 내의 함수를 호출하면 그 결과로 거래가 생성되는데 함수는 상태 변수를 읽거나 기록
=>함수는 호출을 통해 실행할 수 있는 코드의 단위
=>함수는 파라미터를 받아들여서 로직을 수행하고 호출자에게 값을 반환
=>함수에는 이름이 없어도 되는데 솔리디티에서는 계약 내에 이름없는 단 하나 있을 경우를 위해 fallback 함수를 제공
=>함수 선언에는 function 키워드 와 식별자를 사용하며 콤마로 구분한 파라미터를 만들 수 있고 파라미터 식별자는 선택 사항이나 파라미터 목록에 자료형을 제공해야 함
=>함수는 데이터를 반환할 수 있는데 return 키워드 와 반환되는 파라미터 목록을 사용해서 선언하고 여러 개의 데이터를 반환할 수 있음
=>함수의 동작 및 실행에 영향을 주는 한정자가 2가지 있음

1)가시성 한정자(접근 지정자)

public: 외부 와 내부 모두에서 직접 접근 가능

internal: 현재 계약 및 그것을 상속한 계약 안에서만 접근 가능하고 외부에서는 접근이 불가능

private: 현재 계약 내에서만 접근 가능

external: 계약 외부에서 접근이 가능하지만 계약 내부에서는 접근할 수 없는 함수
이러한 함수를 계약 인터페이스라고 함

2)계약 상태 변수를 변경하는 능력 과 관련한 동작을 지정하는 한정자

=>constant
상태를 변경할 수 없음
상태 변수를 읽고 반환하는 일은 할 수 있지만 변수를 수정하거나 이벤트를 호출거나 다른 계약을 생성하거나 상태를 변경하는 함수를 호출하는 일은 할 수 없음
view 라고도 함

=>pure
상태 변수에 접근하지 않는 함수
외부의 영향을 받지도 않고 외부에 영향을 주지도 않는 함수

=>payable
호출하는 호출자로부터 이더를 받을 수 있음
송금자가 이더를 제공하지 않으면 호출 실패
이더만 받을 수 있음

🌳 enum(열거형 상수, 나열형 상수)

=>enum 키워드를 이용해서 생성
=>열거형 내의 상수는 정수로 변환할 수 있는 각 상수 값은 첫번째가 0이고 다음 부터는 1씩 증가합니다.
=>enum 열거형이름{상수 나열}
=>열거형 이름으로 변수를 선언하면 열거형으로 대입하는 것을 권장
=>열거형을 선언하는 행의 끝에는 ;을 생략
enum gender {male, female}
//male은 0 female은 1

gender _gender = gender.male; //gender.male 대신에 0을 대입해도 됩니다.

constant 나 enum 으로 설정한 것들은 컴파일을 하고 나면 숫자로 변환이 됩니다.

일반 변수는 컴파일을 해도 변수 이름으로 남아있기 때문에 디버깅이 쉽지만 constant 나 enum은 디버깅이 어렵습니다.
일반 변수나 리터럴을 사용하는 것보다는 constant 나 enum을 사용하는 것이 가독성 이나 유지보수 측면에서 좋습니다.

🌳struct(구조체)

=>사용자 정의 자료형
=>여러 종류의 데이터를 하나로 묶고자 할 때 사용
=>변수로만 구성
//구조체 정의
struct 구조체이름{
자료형 변수명;
자료형 변수명;
...
}

//구조체 객체 생성
구조체이름 변수명 = 구조체이름(각 변수에 대입할 데이터 나열);

🌳배열

=>동일한 자료형의 데이터 모임

1)고정 배열 - 배열의 크기가 고정

=>선언
자료형 [데이터 개수] 배열 이름;
int [5] age;

=>초기화
배열이름 = [자료형(값), 값을 나열]
age = [int(10), 20, 30, 40, 50];

=>선언 과 동시에 초기화
int [5] age = [int(10), 20, 30, 40, 50];

2)동적 배열 - 배열의 크기를 동적으로 생성

=>선언
자료형 [] 배열이름
int [] age;

=>메모리 할당
new 자료형[데이터 개수]
age = new int[5];

=>선언 과 동시에 초기화를 하거나 메모리 할당 가능
int [] age = [int(10), 20, 30, 40, 50];
int [] age = new int;

3)bytes 배열

=>여러 개의 bytes를 담을 수 있는 동적 배열
=>byte [] 배열은 각 원소가 32바이트 이지만 bytes 는 모든 byte를 하나로 관리
=>바이트의 초기 길이를 정해서 상태 변수로 선언
bytes localBytes = new bytes(20);

bytes localBytes;
localBytes = new bytes(10);

=>값을 직접 할당
localBytes = "Ritesh Modi";

=>값을 추가하는 방식의 push 제공
localBytes.push(byte(10)); //10이라는 코드

4)string

=>bytes 배열에 기초한 동적 자료형
=>index 나 push를 사용할 수 없고 length 속성도 없음
=>각각의 데이터 접근이 안되도록 설정
=>수정하거나 각각에 접근하고자 경우에는 bytes 로 변환해서 사용
bytes(string) 으로 변환이 가능

5)배열 속성

=>index : [번호]
문자열을 제외한 모든 배열에 존재
고정 크기 byte 배열에서는 쓰기는 지원하지 않음

=>push: 동적 배열에서만 지원

=>length: 길이, 문자열에는 없음

🌳Address

=>이더리움 계정 주소를 저장하기 위해서 설계한 자료형
=>20바이트

1)속성

=>balance: 이더의 총량

2)함수

=>이더를 송금하는 함수: transfer, send
=>계약 함수를 호출하는 함수: Call, DelegateCall, Callcode

🌳Mapping

=>Key 와 Value를 쌍으로 저장하는 자료구조
=>Hash Table 인 Hash Map 또는 Dictionary 라고 불리웁니다.
Mapping(키의 자료형 => 값의 자료형) 이름;

이름[키이름] = 값; //저장
이름[키이름];//읽어오기

=>solidity에는 Mapping을 전체 순회할 수 있는 iteration이 없습니다.
키의 값을 모르면 데이터를 찾을 수 없습니다.

=>Mapping 을 편법을 동원해서 iteration 처럼 동작하도록 할 수 있습니다.
Mapping 의 key 의 자료형을 정수형으로 하고 key 의 값을 일련 번호 형태로 만들면 가능

//저장할 때

counter = counter + 1;
Names[counter] =//순회하고자 할 때
for(uint=1; i<= counter; i++){
	Names[i];
}

Key 의 값을 동적 배열에 추가한 후 동적 배열을 순회하면서 가져오는 방법도 있음

🌳Modifier(수정자)

=>실행 중인 코드의 행위를 변경하는 개체
=>실행 단위가 함수 이므로 목표 함수보다 먼저 실행되는 함수
=>AOP 와 유사
=>수정자는 modifier 키워드 와 수정자의 식별자, 파라미터, 중괄호로 둘러싼 코드 순으로 정의
수정자 내에서 _ 는 목표 함수

//수정자 - msg.sender 와 personIdentifier 의 값이 같으면 목표 함수를 수행

modifier onlyBy(){
	if(msg.sender == personIdentifier){
		_
	}
}

function getAge(address _personIdentifier) onlyBy(){

} 

=>getAge를 호출하면 onlyBy 함수를 실행해서 조건에 맞는 경우에만 getAge를 수행

=>목적은 유효성 검사

🌳event

=>계약에서 특정 이벤트가 발생하면 그것을 포착해서 처리하는 코드를 실행

=>EVM의 로깅 환경을 이용해서 호출 애플리케이션에 계약의 현재 상태에 대한 정보를 알리는데 주로 이용
계약에 변화가 생겼을 대 애플리케이션에 알려주는 이벤트를 주로 사용

🌳데이터 위치

1)EVM 의 데이터 구조

=>Storage: 계약 내의 모든 함수가 사용할 수 있는 전역 메모리 영역으로 환경 내의 모든 노드에 영구적으로 저장

=>Memory: 계약 내의 모든 함수가 사용할 수 있는 로컬 메모리로 이 영역은 함수가 실행을 마칠 때 사라지는 단기 휘발성 메모리

=>CallData: 모든 입력 함수의 인자 와 실행 데이터를 저장하는 곳으로 변경할 수 없는 메모리

=>Stack: EVM은 변수의 적재 와 이더리움 인스트럭션 세트를 가지고 작업하는 중간 값을 저장하기 위해 스택을 유지하는데 EVM의 작업 세트 메모리로 사용하는데 스택의 깊이는 1024 단계이며 그 이상을 저장하면 예외가 발생

2)데이터 위치를 정하는 규칙

=>상태 변수로 선언되는 변수들은 스토리지에 저장

=>함수의 매개변수로 선언되는 변수들은 메모리에 저장

=>함수 내에서 선언되는 변수들은 기본적으로 메모리에 저장 참조 타입 과 매핑은 기본적으로 스토리지에 저장 함수내에서 선언된 참조 타입의 변수들은 상태 변수가 됩니다.

=>호출하는 곳에서 함수 파라미터에 제공한 인자는 항상 CallData 위치에 저장

=>다른 상태 변수로부터 할당을 받게되면 새로운 사본을 만들어서 할당

=>메모리 변수의 데이터를 스토리지 변수에 할당할 때는 사본을 만들어서 할당

=>상태 변수로부터 메모리 변수를 할당할 때는 새로운 사본을 만들어서 할당

=>메모리 변수의 데이터를 다른 메모리 변수에 할당할 때는 사본을 만들지 않음

🌳var 변수

=>함수 내에서만 사용이 가능한 자료형
=>상태 변수에는 사용할 수 없음
=>묵시적인 타입으로 처음 할당되는 값에 따라 자료형이 결정된다는 것을 컴파일러에게 알려주는 것

var unitVar8 = 10; //uintVar8 의 자료형이 uint8(0 ~ 255까지만 저장)
unitVar8 = 254; //에러

🌳Hoisting

=>변수를 사용하기 전에 선언 및 초기화하지 않아도 되는 개념
=>변수 Hoisting이 가능한 경우는 2-pass Compiling 을 하기 때문
1-pass 에서는 선언이나 정의하는 문장만 확인 - 실행하는 문장은 확인하지 않음
2-pass 에서 실행하는 문장들의 문법적인 구조를 확인

contract variablehoisting{
	function hoistingfunc() returns (int){


	}
}

//변수를 선언하는 문장이 뒤에 있고 사용하는 문장들이 앞에 있는데 이렇게 해도 에러가 발생하지 않음

contract variablehoisting{
	function hoistingfunc() returns (int){
		uint firstVar ;
		uint result;

		firstVar = 10;
		result = firstVar + 20;
		return result;
	}
}
profile
즐거운 개발 공간

0개의 댓글