솔리디티 1일차
- 계약 지향 프로그래밍 언어로, 다양한 블록체인 플랫폼의 스마트 계약 로직을 작성할 때 사용됩니다.
- 기본적으로 이더(ETH)를 보내고 받는 데 필요한 데이터 타입, 함수 등을 제공하며 다음과 같은 특징을 갖는다.
솔리디티 git 사이트 : https://github.com/ethereum/solidity
솔리디티 개발 환경
- remix, IntelliJ IDEA Plugin, VSCode Extension, Etheratom 등
- • 코드를 컴파일, 배포, 테스트, 디버깅해 주는 Truffle이나 Hardhat, 그리고 로컬 환경에 블록체인 테스트넷을 사용할 수 있게 해 주는 Ganache를 함께 사용해야 함. 별도의 서버 없이 컴파일러와 런타임 환경을 제공하는 브라우저 기반의 IDE인 Remix가 편리함
리믹스 Local 사용하는 방법
- 노드를 설치한다(https://nodejs.org/ko)
- 터미널에서 다운을 받는다 명령어 : npm install -g @remix-project/remixd
- 다운이 잘 되었는지 확인을 한다. 명령어 : remixd -v
- 폴더 생성한다. 명령어 : window ⇒ md 파일명, Mac ⇒ mkdir 파일명
- 터미널에서 폴더위치로 이동한다. 명령어 : cd 파일명
- 그리고 그 위치로 이동한다. 명령어 : remixd
- 위에를 다하면 로컬에 접속이 가능
변수 선언법
- 솔리디티 자료형: 값 타입(value type) / 참조 타입(Reference type)
- 값타입: 값이할당되거나함수의인자로활용이되면해당값자체가복사됨
- 참조 타입: 현재 해당하는 값의 주소만 복사됨. ⇒ 배열(array), 매핑(mapping), 구조체(Struct)로 구성되어 있음.
- 변수 정의 방법
- 가시성 지정자
변수의 종류
- 상태 변수(State Variable) : 값이 계약 저장소에 영구적으로 저장되는 변수
pragma solidity ^0.8.7; // 솔리디티 버전을 0.8.7이상을 쓰겠다고 정의해 놓음
contract MyStorage {
uint storageData; //State Variable
}
- 지역변수(Local Variables) : 함수가 실행될 때까지 값이 존 재하는 변수.
pragma solidity ^0.8.7; // 솔리디티 버전을 0.8.7이상을 쓰겠다고 정의해 놓음
contract MyStorage {
function getResult() public pure returns(uint){
// Defining function to show the declaration and
// scope of local variables
uint local_var1 = 1;
uint local_var2 = 2;
uint result = local_var1 + local_var2;
// Access the local variables
return result;
}
}
- 전역변수(Global Variables) : 블록체인에대한정보를얻는데사 용되는전역특수변수
pragma solidity ^0.8.7; // 솔리디티 버전을 0.8.7이상을 쓰겠다고 정의해 놓음
contract MyStorage {
function getResult() public pure returns(uint){
// Defining function to show the declaration and
// scope of local variables
uint local_var1 = 1;
uint local_var2 = 2;
uint result = local_var1 + local_var2;
// Access the local variables
return result;
}
}
연산자
함수의 기본형태
공부할 때 참고하면 좋은 사이트 : https://github.com/wikibook/solidity
오늘은 예제2번 살펴보기(기초)
- 예제 2-1
pragma solidity ^0.8.7; // 솔리디티 버전을 0.8.7이상을 쓰겠다고 정의해 놓음
contract Ex2_1 {
//행 단위 주석
/*
블록 단위 주석
*/
}
- 예제 2-2
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 < 0.9.0;
contract Ex2_2 {
string a = 'Hello';
uint b = 5;
uint c = 5;
uint d = 5;
uint e = 5;
uint f = 5;
function assignment() public returns(string memory, uint, uint, uint, uint, uint) {
a = 'Hello Solidity';
b += 2; // b = b + 2
c -= 2; // c = c - 2
d *= 2; // d = d * 2
e /= 2; // e = e / 2
f %= 2; // f = f % 2
return(a, b, c, d, e, f);
}
}
결과값 :
"0": "string: Hello Solidity",
"1": "uint256: 9",
"2": "uint256: 1",
"3": "uint256: 20",
"4": "uint256: 1",
"5": "uint256: 1"
- 예제 2-3
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 < 0.9.0;
contract Ex2_3 {
int a;
uint b;
bool c;
bytes d;
string e;
address f;
function assignment() public view returns(int, uint, bool, bytes memory, string memory, address) {
return(a, b, c, d, e, f);
}
}
결과값 : 솔리디티의 초기값은 0이다 그러므로 전부 0과 관련값이 반환된다.
- 예제 2-4
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 < 0.9.0;
contract Ex2_4 {
uint a = 5+2;
uint b = 5-2;
uint c = 5*2;
uint d = 5/5;
uint e = 5%2;
uint f = 5**2;
function arithmetic() public view returns(uint, uint, uint, uint, uint, uint) {
return(a, b, c, d, e, f);
}
}
결과 값 :
0:uint256: 7
1:uint256: 3
2:uint256: 10
3:uint256: 1
4:uint256: 1
5:uint256: 25
매핑과 배열
- 매핑은 배열 및 구조체로서의 참조 유형입니다. 다음은 매핑 유형을 선언하는 구문입니다.
mapping(_KeyType => _ValueType)
_KeyType : 내장 유형과 바이트 및 문자열이 될 수 있습니다.
참조 유형 또는 복합 개체는 허용되지 않습니다.
_ValueType : 모든 유형이 될 수 있습니다.
고려 사항
- 매핑은 저장 유형만 가질 수 있으며 일반적으로 상태 변수에 사용됩니다.
- 매핑을 공개로 표시할 수 있습니다. Solidity는 자동으로 getter를 생성합니다.
맵핑(Mapping) 기본 사용법
- 매핑은 일반적인 프로그래밍 언어에서는 해시테이블이나 사전과 유사합니다.
- 키(Key) - 값(value) 형태로 쌍으로 저장되고 제공된 키(Key)를 가지고 값(value)을 얻어낼 수 있습니다.
예제)
pragma solidity ^0.8.0;
contract MyContract{
mapping(uint => string) public names;
constructor() public{
names[1] = "Kim";
names[2] = "Park";
names[3] = "Lee";
}
}
위 코드에서는, unit 자료형이 키(Key)이며, string 자료형이 값을 저장하는데 사용됩니다.
names는 매핑의 식별자로 사용되었습니다.
배열
- 배열은 데이터를 저장하는 장소와 같다 표현방식 : '배열명[주소값] = 데이터' 이다.
- 배열명은 변수명처럼 단순히 이름이고
- 주소값은 0부터 시작한다.
- length(길이) 있음
- 배열의 삭제
- [1] Pop를 사용하여 가장 마지막의 index값을 제거 (공간도 제거됨)
- [2] Delete를 사용하면 공간은 남게 되며 자료값만 삭제됨
pragma solidity ^0.8.0;
contract MyContract{
mapping(uint => string) public names;
constructor() public{
names[0] = "Han"
names[1] = "Kim";
names[2] = "Park";
names[3] = "Lee";
}
}
설명 : 배열명 names는 주소값 0~3까지가지고 있다.
names = ["Han", "Kim", "Park", "Lee"]의 값이다.
Stack : 맨마지막에 들어간 자료가 맨 처음으로 나온다. ⇒ 재밌게 말하자면 먹고 토하는것과 같다.
Queue: 맨 처음으로 들어온 것이 맨 처음으로 나온다. ⇒ 먹고 싸는것과 같다.
구조체
- 말그대로 저희만의 구조 즉 타입을 만드는 것
- 선언 방식
struct 구조체명 { 타입 변수명, 타입 변수명, ..... } 예제) pragma solidity ^0.8.0; contract MyContract{ mapping(uint => string) public names; mapping(uint => string) public books; struct Book{ string title; string Author; } constructor() public{ names[0] = "Han" names[1] = "Kim"; names[2] = "Park"; names[3] = "Lee"; } function addBook(uint _id, string memory _title, string memory _author) public { books[_id] = Book(_title, _author); } }
- 예제 : Book이라는 구조체를 만들고 addBook이라는 함수를 추가합니다.
해쉬코드와 해쉬테이블이란?
해쉬코드
- 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수
- 원하는 데이터를 빠르게 찾기 위해서 사용됨
해쉬테이블
- 해시 테이블은 (Key, Value)식으로 데이터를 저장하는 자료구조 중 하나로 key를 통해 평균 O(1)에 value를 검색할 수 있는 자료구조이다.
- 해시 테이블은 Key 값을 해시함수(Hash Function)를 사용하여 변환한 값을 색인(index)으로 삼는다.
- 해시 함수(Hash Function)를 사용해 Key 값을 색인(index)으로 변환하는 과정을 해싱(Hashing)이라고 한다
해쉬테이블을 쓰면 장단점은?
장점
- 검색 속도가 매우 빠르다
- 배열을 예시로 들자면 인덱스 값으로 데이터를 찾아내는 방식이다.
단점
- 해시 충돌 : 해시 함수를 통해 나온 해시 코드가 중복되는 경우
- 해시코드는 정수개로 한정이라서 중복을 가질 수 밖에 없다.
- 하나의 인덱스에 모든 키값이 저장되어 시간복잡도가 늘어나는 경우
Storage, Memory란?
Storage
- storage는 블록체인에 영구적인 상태를 저장하는 영역
Memory
- 함수가 실행되는 동안에만 사용할 수 있는 가상 메모리 영역
- 함수 실행이 완료되면 자동으로 이 공간은 삭제(임시공간이라서)