Solidity 문법

Solidity 문법

2024년 3월 31일

완전히 처음보는 언어라 필요한 부분만 정리한다.

Gas #

스마트 컨트랙트 플랫폼에서 컨트랙트 실행, 트랜잭션 처리에 대한 비용을 말한다.
각 스마트 컨트랙트 네트워크는 자체적인 가스 모델을 직접 정의하고 있으며, 가스 비용은 공격자에 의해 네트워크가 악용되는 것을 막고, 네트워크가 과부하 되는것을 막는 역할을 한다.
ether 네트워크에서는 블록체인 수정이 아닌 읽기만 하는 view 함수에 대해 가스비를 부과하지 않고 있다.

  • 네트워크 혼잡도
    네트워크에 처리를 대기하고 있는 트랜잭션이 많을수록 더 높은 가스 가격을 제안해야 빠르게 처리된다.
  • 트랜잭션의 복잡성
    수행하려는 연산이 많은 트랜잭션이라면 가스 비용이 크게 들어간다. 그렇기 때문에 스마트 컨트랙트의 코드 최적화도 가스를 아끼는데 중요한 요소가 된다.

Contract #

하나의 계약에 대한 정의이고 클래스와 비슷하다고 생각하면 된다. 하나의 파일에 하나의 컨트랙트만 정의할 필요는 없다.

6e11bfc6-a627-4b61-8534-3f3f2f4768fa

constructor #

컨트랙트가 배포될때 단 한번만 호출되는 함수이다. 초기 세팅을 할 수 있으며, 상속받은 컨트랙트의 경우 명시적으로 부모의 constructor를 지정해줘야할 수 있다. (생성자에서 인자를 받는 경우도 있기 때문)


접근제어자 #

상태변수나 함수에 명시할 수 있으며, 명시하지 않는 경우 상태변수나 함수는 기본적으로 internal을 갖는다.

  • public : 컨트랙트 외부에서도 접근 가능하다.
  • private : 컨트랙트 내부에서만 접근 가능하다.
  • internal : 상속받은 컨트랙트까지만 접근 가능하다. 완전한 외부는 접근할 수 없음
  • external : 컨트랙트 외부에서 ‘만’ 접근 가능하다. private과 반대로 보면 된다.

Function #

1function functionName(매개변수) public pure returns (uint, uint, bool) {
2    // 코드와 리턴
3}

public은 함수의 가시성을 의미하고, 위에서 소개했던 private, internal, external 모두 사용할 수 있다.
pure는 모디파이어라고 하는데, 함수 로직에 제약을 주는 역할을 한다.

  • pure
    함수 밖에 선언된 변수를 함수 안에서 사용할 수 없도록 제한하는 키워드이다. 순수하게 함수 내부에서 정의되거나 전달받은 매개변수만 사용할 수 있다.
  • view
    외부 변수를 읽을 수 있지만, 값을 변경할 수 없다. const 함수 같은 느낌. 솔리디티의 함수는 여러값을 리턴할 수 있다.

함수 호출 위치 #

  1. 내부 함수
  • 동일한 컨트랙트 안에서 함수를 호출하는것을 의미한다.
  • 함수 호출 시 storage나 memory 영역의 변수를 그대로 사용한다. (컨트랙트 내부에서 호출한 것이기 때문에 이미 접근 가능한 변수가 만들어져 있다)
  1. 외부 함수
  • 다른 컨트랙트의 함수를 호출하는 것을 의미한다.
  • 매개변수는 값이든 참조든 calldata 영역에 저장되어 전달된다.
  • solidity 0.5.0 이상에서는 참조타입을 함수에 전달할때 저장위치를 명시적으로 지정하도록 변경됐다.
    1function externalCallExample(uint[] calldata numbers) external pure returns (uint) {
    2    return numbers.length;
    3}
    

Data Type #

값 타입 #

bool, uint, int, enum 의 타입은 다른 언어와 비슷하다. (int8 ~ int256) enum은 내부적으로 정수 값으로 구현된 열거형 값이다.

  • address
    20byte 크기의 지갑 주소가 저장되며, 잔액을 확인하거나 transfer, send 메소드가 추가로 구현되어 있다.
  • bytes
    bytes1 ~ bytes32 타입까지 있으며, 고정크기의 바이트 어레이를 저장하기 때문에 fixed-sized byte array 라고도 불린다.

참조 타입 #

배열(string, bytes), 구조체 등의 객체 타입을 말한다.

  • 매핑타입
    키 값 쌍을 저장하는데 사용되며 storage 데이터 위치에서만 사용할 수 있고, 함수 인자로 전달될 수 없다는 특성이 있다.

Data Location #

storage #

스토리지 영역은 블록체인에 영구히 기록되는 변수를 의미한다. 가스비가 많이 들기 때문에 최대한 사용을 자제해야 한다. state variable컨트랙트 안에서 선언된 변수이며, 컨트랙트의 모든 function에서 접근할 수 있고, storage 영역에 저장되어 블록체인에 영구히 기록되기 때문에 가스비가 든다. c08ea087-4ccf-4900-a3c1-6db22aadb8c2

1contract Example {
2    uint[] public numbers;
3
4    function testStorage() public {
5        uint[] storage nums = numbers; // `storage` 참조, `numbers` 배열을 직접 수정합니다.
6        nums.push(1); // `numbers` 배열에 1을 추가합니다.
7    }
8}

함수 안에서 명시적으로 storage라는 키워드를 지정하는 경우가 있는데, 이건 storage 변수 생성이 아니라 storage 변수를 참조하겠다는 의미이고, 함수 사용 중 storage 에 데이터를 반영하기 위해 사용하게 된다.
만약 명시하지 않으면 memory 변수로 사용되며, 데이터를 변경한다 하더라도 memory에만 반영되고 실제 블록체인에는 저장되지 않게 된다.

memory #

함수 실행 중 임시로 저장되는 공간이며, 함수의 지역변수가 저장되는 공간이다.
읽기, 쓰기 모두 가능하지만, 블록체인에 저장되지 않고 함수가 종료되면 사라진다.
가스비가 0인건 아니지만, 영구히 저장되는 storage보단 적게 든다.

calldata #

함수의 인자가 기본적으로 저장되는 공간이며, 함수가 호출되면서 스택으로 복사되고 사용된다.
이 영역은 읽기 전용이고, 함수가 종료될때 사라진다.
읽기 전용 영역이기 때문에 memory 영역보다도 가스비가 적게 든다.


이벤트 #

블록체인에서 트랜잭션이 완료되면, 트랜잭션에 대한 영수증이 발행되면서 블록체인에 영구히 기록된다. 이 영수증에는 트랜잭션이 실행하는 동안 발생했던 로그들이 포함된다.

아래는 스타 아틀라스의 우주선 음식 공급 로그이다. 420ce027-6fa2-4045-9858-1388261ea9ed

event는 로그를 생성하기 위한 객체이며, 아래와 같이 사용한다

1// 이벤트 선언
2event numberTracker(uint256 num, string str);
3
4// 이벤트 발생
5emit numberTracker(1, "hello");

저렴하게 영구적인 데이터를 저장하거나 dApp에서의 알람 인터페이스 역할을 한다.


프론트 엔드에서 컨트랙트 함수 호출 #

web3 또는 ethers 라이브러리를 사용해서 컨트랙트 함수를 호출할 수 있다.

 1import { ethers } from 'ethers';
 2
 3if (window.ethereum) {
 4    const provider = new ethers.providers.Web3Provider(window.ethereum);
 5    const signer = provider.getSigner();
 6}
 7
 8const contract = new ethers.Contract(contractAddress, abi, signer);
 9
10contract.testFunctionName()
11    .then(result => console.log(result));
comments powered by Disqus