Solidity : 이더리움에서 나온, 스마트 컨트랙트 개발과 발급에 특화된 객체 지향 언어.
스마트 컨트랙트 : 미리 정의된 조건이 충족이 될 경우 블록체인 안에 저장된 프로그램이 작동하는 것. (별도의 인증기관 없이 개인간의 계약이 이루어질 수 있도록 하는 기술)
보통 IDE는 Truffle을 사용하지만, 처음이니까 가볍게 시작하기 위해 Online IDE인 Remix 사용
solidity는 맨 윗줄에 라이센스를 명시해 주어야 에러가 나지 않음.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Hello{
string public hi = "Hello solidity";
}
SPDX-License-Identifier: GPL-3.0 : 이 라이센스는 무조건 맨위에 명시 해주어야 함
pragma solidity >=0.7.0 <0.9.0; : 솔리디티의 컴파일 버전 명시 ( 즉 0.7 ~0.9 의 버전을 사용)
contract Hello{ : 스마트 컨트랙트 명시
string public hi = "Hello solidity"; : hi 라는 public 함수에 hello solidity 를 넣음( 타입/접근제한/변수명)
}
컴파일
deploy를 눌러서 배포
배포한 컨트랙트
hi를 누르면 Hello solidity가 출력됨
boolean, string, bytes,Integer ,address
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 < 0.9.0;
/*
data type
boolean, bytes, address, uint
reference type
string, Arrays, struct
mapping type
*/
contract lec2{
// bolean : true/false
bool public b = false;
// ! || == != &&
bool public b1 = !false; //true
bool public b2 = false || true; // true
bool public b3 = false == true; //false
bool public b4 = false != false; // false
bool public b5 = false && true; // false
//bytes 1~32
bytes4 public bt = 0x12345678;
bytes public bt2 = "STRING";
//address
address public addr = 0xd9145CCE52D386f254917e481eB44e9943F39138;
// int(음수 포함) Vs uint (음수 안 포함)
//int8 : -2^7 ~ (2^7)-1
int8 public it = -4;
//uint8 : 0 ~ 2^8-1
uint8 public it2 = 123;
//uint256 : 0 ~ 2^256-1
uint256 public it3 = 123;
}
1. boolean : true , false
2. string : string을 쓸 땐 ""를 붙여서 쓰기
솔리디티 입장에서 string을 받아서 다시 byte화 시켜서 이해를 합니다. string과 byte를 왔다갔다 변경하여 가스를 소비하는것보단, 솔리디티입장에서 편하게 byte를 받는것이 더 이득!
3. bytes : 솔리디티는 byte1 ~ byte32 까지 존재
뒤에 숫자에따라 byte의 크기 가 정해진다. e.g) byte32 로 쓰면 길이가 32 개.
byte의 크기를 안다면 크기에 맞게 지정해주시는 편이 낫다.
4. Integer : int, unit
int : 기호있는 integer
int8 : -2^7 ~ 2^7-1
int16: -2^15~2^15-1
int32: -2^31~2^31-1
int64: -2^63~2^63-1
int128 : -2^127~2^127-1
int256 (=int): -2^255~2^255-1
uint: 기호없는 integer
uint8 : 0~2^8-1
uint16: -0~2^16-1
uint32: -0~2^32-1
uint64: -0~2^64-1
uint128 : -0~2^128-1
uint256 (=uint): 0~2^256-1
5. address : address는 20 bytes 의 길이
여기서 address를 확인 가능
컴파일 해서 새롭게 배포 하면 스마트 컨트랙트 주소와 달라짐.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 < 0.9.0;
/*
1 ether = 10^9 gwei = 10^18wei
0.000000000000000001 = 1^-18 =1wei
0.01 ether = 10^16 gwei
*/
contract lec2{
uint256 public value = 1 ether;
uint256 public value2 = 1 wei;
uint256 public value3 = 1 gwei;
}
1 ether = 10^9 Gwei = 10^18 wei 입니다.
다시 말하자면 1^18 wei 는 1 이더를 나타냅니다.
Gwei는 주로 가스를 소비했을때, 사용되는 단위
가스는 왜 만들었을까?
이더리움에 의하면, 가스를 만든이유는 DDoS(Distributed Denial of Service) 공격에서 좀 더 자유로워 지기 위해서
만들었다고 합니다. 예를 들어, 해커가 고의적으로 블록체인 네트워크를 다운 시킬려고, 스마트 컨트랙을 지속적으로 작동하게 반복 시켜 과부화를 준다고 가정 했을때, 해커는 작동을 반복시킬때마다 Gas 비용을 지불해야하죠.
function 함수이름() 접근제한 읽기/쓰기 returns(리턴 타입) { // 함수 내용 정의 }
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 < 0.9.0;
contract lec4{
/*
function 이름() public { // (public,private,internal,external) 변경가능
// 내용
}
*/
uint256 public a = 3;
//1. parameter 와 return 값이 없는 function
function changeA1() public{
a = 5;
}
//2. parameter 값이 있는 function
function changeA2(uint256 _value) public{
a = _value;
}
//3. return 값이 있는 function
function changeA3() public view returns(uint256){
return a;
}
//4. parameter 와 return 값이 있는 function
function changeA4(uint256 _value) public returns(uint256){
a = _value;
return a;
}
}
Public: 모든 컨트랙트 및 계정에서 호출 가능
Private : 오직 컨트랙트 안에 정의된 함수에서만 사용 가능 (private이 정의된 현재 이 컨트랙트를 상속받은 자식 컨트랙트도 접근 불가)
Internal : internal 함수를 상속받은 컨트랙트 안에서 사용 가능(private에서 한가지 기능(상속받은 자식 접근 가능)이 더 추가)
External : 오직 다른 컨트랙트나 계정에 의해서만 호출 가능
상태변수는 public, private, internal에서 선언 가능(external에서는 불가)
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 < 0.9.0;
contract lec5{
//1.public
uint256 public a = 3;
//2.private
uint256 private a2 = 5;
}
contract Public_example {
uint256 public a = 3;
function changeA(uint256 _value) public {
a =_value;
}
function get_a() view public returns (uint256) {
return a;
}
}
contract Public_example_2 {
Public_example instance = new Public_example();
function changeA_2(uint256 _value) public{
instance.changeA(_value);
}
function use_public_example_a() view public returns (uint256) {
return instance.get_a();
}
}
contract private_example {
uint256 private a = 3;
function get_a() view public returns (uint256) {
return a;
}
}
contract external_example {
uint256 private a = 3;
function get_a() view external returns (uint256) {
return a;
}
}
contract external_example_2 {
external_example instance = new external_example();
function external_example_get_a() view public returns (uint256) {
return instance.get_a();
}
}
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 < 0.9.0;
/*
view : function 밖의 변수들을 읽을수 있으나 변경 불가능
pure : function 밖의 변수들을 읽지 못하고, 변경도 불가능
viwe 와 pure 둘다 명시 안할때: function 밖의 변수들을 읽어서, 변경을 해야함.이 정의된 현재 이 컨트랙을 상속받은 자식 컨트랙도 접근가능)
*/
contract lec6{
uint256 public a = 1;
function viewExample() public view returns(uint256){
return a+2;
}
function readAndChangeA() public returns(uint256){
a = 3;
return a+2;
}
function pureExample() pure public returns(uint256){
uint256 a2 = 3;
return a2+2;
}
}
view : storage state 를 읽을 수 있지만, 그 state 값을 변경할 수 없다.
function의 밖에 있는 것들은 storate에 저장이 되니까 이 예제에서는 a가 storage state.
read_a()라는 간단히 a값을 리턴하는 함수를 만들었으니, storage state를 읽었다고 볼 수 있다. 그렇기 때문에 view를 넣어야 함.
pure : storage state 를 읽으면 안되고, 그 state값을 변경할 수 도 없다.
pure는 storage state를 읽지 못하고, 변경도 불가하니 함수 밖의 외부의 값을 가져온다.
그러니 함수 내에 정의된 로컬변수들과 논다.
solidity 는 storage, memory, calldata ,stack 이렇게 4개의 저장 영역으로 나뉘어 있다.
storage : 대부분의 변수, 함수들이 저장되며, 영구적으로 저장이되어 가스 비용이 비싸다.
memory: 함수의 파라미터, 리턴값, 레퍼런스 타입이 주로 저장이 된다. 함수가 실행을 마칠 때 사라지는 단기 휘발성 메모리.
Calldata : 주로 external function 의 파라메터에서 사용 된다. 예를 들어 함수를 실행할 때 파라메터의 값 자체를 calldata로 받을 수 있습니다. calldata로 받게 된다면, 값은 변경할 수 없고 읽기만 가능합니다. (모든 입력 함수의 인자와 실행 데이터를 저장하는 곳)
stack: EVM (Ethereum Virtual Machine) 에서 stack data를 관리할때 쓰는 영역인데 1024Mb 1024개의 data를 제한적으로 저장해 사용할 수 있다. 예를 들어, 함수를 실행할 때 로컬 변수와 같은것들을 잠시 기억할 때 EVM이 사용된다.
CallData와 memory라는 접두사는 오직 Solidity에만 존재하는 접두사이다.