Solidity 깨부수기 정리

빵 반죽·2022년 1월 14일
0

Data types

bool, bytes(1-32), address, int/uint

Ether/GWei/wei and gas

1 ether = 10^9 gwei = 10^18 wei
Gwei = gas 단위
contract 실행마다 가스 사용 -> Ethereum Yellow Paper에 종류별로 정의되어 있음
-> 디도스 공격이 어려워짐

Functions

format: function '이름'() 'public/private/internal/external' 'view/pure' 'returns (type)'{}

  • no parameters and no return values
  • parameters and no return values
  • parameters and return values
    -> returns (type) 여기서 변수 정의 가능(?)
  • public: 모든 곳에서 접근 가능
  • external: 정의된 contract 밖에서만 접근 가능
  • internal: 정의된 contract와 그 contract를 상속한 모든 contract에서 접근 가능
  • private: 오직 정의된 contract에서만 접근 가능
    -> 함수, 변수 다 가능
  • view: function 밖의 변수들을 읽지만 변경하지 않음(no state change)
  • pure: function 밖의 변수들을 읽지도 변경하지도 않음(no state change)
  • 둘 중 하나가 없다면 밖의 변수들을 읽어서 변경하는 함수
  • storage: 블록체인에 저장. 가스비가 많이 나온다.
  • memory: 함수 내에서 저장. parameter, return value, reference type, etc. 가스비가 적다.
    -> string is a reference type(배열, 기본 자료형이 아님): string memory 로 써야 한다.
  • stack: EVM's stack data(1024MB)
  • Calldata: external function's parameter 저장하는 곳, memory와 같이 일시적

Instance

'contract name' 'instance name' = new 'contract name'();
-> 특정 contract의 구조를 가져다 다른 곳에서 instance 만들기

constructor(parameters){}
-> instance를 만들 때 초기값 설정해줌
-> constructor가 있는 contract는 deploy시 parameters 지정해야됨

-> 이렇게 instance를 사용하게 되면 gas 소비가 커짐. contract가 가벼운 경우가 아니라면 다른 방식으로

Inheritance

contract B is A(constructor parameters){}
: B는 A의 허용된 변수나 함수를 이용 가능, A에서 constructor가 있다면 명시된 parameter로 초기 값을 정한다.

  • override: 부모의 함수 자식이 덮어씌우기
    -> 부모 함수에 virtual 붙이기
  • constructor도 상속 가능(parameter도 미리 적어둘 수 있다.)
  • 여러 contract를 상속할 때에는 is 뒤에 ,로 구분한다. 같은 이름을 가진 함수를 두 개 이상의 부모 contract가 가진 경우 반드시 override해야 한다.
  • super: override시 부모 함수가 필요할 때, 부모 contract의 instance처럼 사용하면 된다.
  • 두 부모 contract가 있는 경우 super.(function)은 후자 부모를 따른다.

Event

event 'name'(parameters);

  • 블록에 저장된다.
  • event and emit
  • print parameters
  • indexed: js에서 특정 이벤트 값만 갖고 올 수 있도록 해준다. indexed num과 같이 이벤트 parameter를 설정하면 된다. 해시 값을 저장하므로 gas가 더 많이 든다, 나중에 이벤트 찾아볼 때 용이하다.

Mapping & Array

mapping('key type'=>'value type') 접근자 이름;

  • length 기능 없음
  • 배열보다 선호하는 이유는 블록체인 과부하가 적어서
  • depth 3: (key->value)->value

uint256[] public Array;: 크기 제한 없음
uint256[size] public Array;: 크기 제한 size

  • length 기능 있음 Array.length
  • push item 추가Array.push(item)
  • pop 가장 최신의 값 삭제 Array.pop()
  • delete 인덱스 지정 삭제(0, null, undefined 없음) delete Array[index] 길이는 줄어들진 않음, 그 인덱스를 불러오면 0(no errors)

-> mapping과 array는 값을 변경할 때 함수로 업데이트를 해줘야 한다. 처음 정의됐을 때 값을 캡쳐한 상태로 있으므로

Error Handler

ver 0.4.22 ~ 0.7.x

  • assert(조건문): 거짓일 때 에러 발생. 가스 환불x
  • revert(에러 메시지): 조건없이 에러를 발생하고 가스를 환불, 주로 if문과 함께 사용한다.
  • revert 'error문': 이미 명시한 에러문 발동(?)
  • require(조건문, 에러 메시지): 거짓일 때 에러를 발생하고 가스를 환불

ver 0.8.1 ~

  • assert는 내부적 에러 테스트 또는 불변성 체크 용도 가스 환불o
    -> 에러를 발생시키면 Panic(uint256) 타입의 에러 발생
    -> errorCodes

ver 0.6 ~

  • try/catch: 에러가 났을 때 종료하지 않고 대처 가능
  1. catch Error(string memory reason){}: revert나 require 에러, 사용자 지정 에러
  2. catch Panic(uint errorCode){}: assert, errorCode는 명시되어 있음, 컴파일러가 받지 못하는 것
  3. catch(byteMemoryLowLevelData){}: low level 에러 담당, 에러를 구분할 필요가 없을 때 위 에러들 생략하고 이것만 써도 됨
  • Why?
    외부 contract의 함수를 부를 때 에러 발생 소지가 있는 경우, 새로운 함수로 에러 잡아주기
    외부 contract의 instance를 만드는 경우 try new exampleContract(){ ... } catch{ ... }
    contract 내에서 this로 함수를 부르는 경우(리턴값이 잇으면 try에서 적어줌)

  • panic error codes:
    0x00: Used for generic compiler inserted panics.
    0x01: If you call assert with an argument that evaluates to false.
    0x11: If an arithmetic operation results in underflow or overflow outside of an unchecked { ... } block.
    0x12; If you divide or modulo by zero (e.g. 5 / 0 or 23 % 0).
    0x21: If you convert a value that is too big or negative into an enum type.
    0x22: If you access a storage byte array that is incorrectly encoded.
    0x31: If you call .pop() on an empty array.
    0x32: If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x.length or i < 0).
    0x41: If you allocate too much memory or create an array that is too large.
    0x51: If you call a zero-initialized variable of internal function type.

Modifier

modifier example(param){ ... _; }
modifier: 같은 조건문을 많은 함수에서 필요로 할 때
_: modifier가 적용된 함수가 실행되는 부분. 아무 곳에나 둘 수 있다.

Sending Ether

payable: 이더나 토큰과 상호 작용하는(send, transfer, call 사용) 함수, 주소, 생성자에 붙는다.

  • send: 2300 gas 소비, true/false 반환, re-entrancy attack에 취약
  • transfer: 2300 gas 소비, 실패시 에러 발생
  • call: 가변적인 gas 소비, gas 값 급등에 따라 권장됨. true/false 반환, 마찬가지로 re-entrancy attack에 취약. 패턴(?)으로 방지한다. 또한 다른 컨트렉트의 함수를 부를 수 있다(그 함수가 없으면 fallback 실행)
    -> 0.7 이전: (bool sent, ) = _to.call.gas(1000).value(msg.value)("")
    0.7 이후: {value: msg.value, gas: 1000}("")
    -> 외부 contract 함수 부르기: (bool success, bytes memory outputFromCalledFunction) = _contractAddr.call(abi.encodedWithSigniture("addNumber(uint256, uint256)", _num1, _num2));
    -> deployed된 contract이어야 가능하다.
    ->

주소.balance: 주소의 이더 잔액
msg.sender: contract를 사용하는 주체
msg.value: 보낸 코인 값

  • 생성자에 payable 붙이면 contract가 이더를 받을 수 있음.

fallback: 이름이 없는 함수이며 바드시 external, payable 명시

  • contract가 이더를 받을 수 있음
  • 그 후에 특정 행동을 취할 수 있음
  • 다른 contract에서 여기 없는 함수를 call할 때 행동을 취할 수 있음
  • ~ ver 0.6
  • function() external payable { ... }
  • ver 0.6 ~
  • receive: 순수하게 이더만 받을 때
  • fallback: 함수를 실행하면서 이더를 보낼 때 그 함수가 없으면 작동한다.
  • fallback() external { ... } -> 불러진 함수가 없을 때
  • fallback() external payable { ... } receive() external payable { ... } -> 이더를 받고 나서도 fallback 발동

call vs delegate call

  • msg.sender 가 본래의 contract 사용자 나타냄
  • delegate call이 정의된 contract가 외부 contract의 함수가 자신인 것처럼 값을 업데이트함. 같은 변수를 가지고 있어야 함.
  • upgradable smart contract를 위해서 사용


Interface

interface: contract 내에서 정의되어야할 필요한 것들(template)

  • external이어야 함
  • enum, structs 가능
  • virtual 필요없음
  • 변수, 생성자 불가능
  • is로 적용, 모든 아이템이 구현되어야함

Library

library: 다른 형태의 스마트 컨트렉트

  • 블록체인에 배포되면 다른 스마트 컨드렉트들이 재사용 가능, 가스 소비 줄임(중복 코드 줄임)
  • 데이터 타입에 적용 가능(예시)
uint8 a; uint8 num1; uint8 num2;
a = num1.add(num2);	// SafeMath.add(num1, num2)
  • fallback, payable 함수 정의 불가, 상속 불가

ver 0.8 이후로는 overflow revert

Import

import "./lec41_1.sol";

  • 다른 파일을 불러옴
  • 외부 라이브러리 사용 시에도 필요

0개의 댓글

관련 채용 정보