[solidity] require : 가스비 최적화 위해 함수 실행 조건 설정

Yurright·2023년 12월 30일
0

solidity

목록 보기
3/6
post-thumbnail
post-custom-banner

require는 솔리디티 함수를 실행하거나 실행하지 않을 조건을 설정할 때 사용한다.


[등장배경]

  • 보통 조건문은 if를 사용하지만 if문은 의미 없는 경우의 수까지 함수를 실행시켜 가스비가 의미 없이 소비되는 경우가 발생한다.

  • 솔리디티 코드를 작성할 때에는 가스비가 최소한으로 들도록 설계해야 한다.

  • 따라서, 특정 경우 아예 함수를 실행시키지 않도록 할 필요성이 존재하여 require 문이 탄생하게 되었다.


[용법]


function A() {
require([실행 조건], "[false일 경우 띄울 메시지]");
rest of code;
}
  • require문 실행 조건이 true 이면 함수가 실행된다.
  • require문 조건이 false이면 require가 위치한 함수 내의 위치에 상관없이(return 전에 존재하는 한 - [예시2] 참고) 함수를 실행하기 전의 상태로 되돌린다. 이때, 가스비가 발생하는 transaction이 실행되지 않는다.

> 아래 [예시] 를 통해 require문이 가진 여러 특성을 살펴본다.

[예시 1] : require 조건이 false이면, 상태를 변화시키지 않아 가스비가 발생하지 않는다. (에러 메시지 확인)
[예시 2] : require 조건이 false이면, require문의 위치에 상관없이 전체 함수를 실행하기 전의 상태로 돌아간다.
[예시3] : require문을 return 뒤에 쓰지 않도록 주의할 것
[예시4] : require문이 존재하는 경우, 함수 속의 함수도 실행되기 전으로 돌아간다.


[예시 1] :

require 조건이 false이면, 상태를 변화시키지 않아 가스비가 발생하지 않는다. (에러 메시지 확인)

function require_2(uint _n) public returns(string memory) {


       require(_n <= 10, "_n should not be higher than 10. ");


       a = _n;
       if(0 <= a && a <= 2) {
           return "A";
       } else if(3 <= a && a <= 5) {
           return "B";
       } else if(6 <= a && a <= 8) {
           return "c";
       } else {
           return "D";
       }
   }
  • [예시 1]의 코드에서, require_2(11)을 입력해 require 조건을 만족하지 않을 경우, 다음과 같은 에러 메시지가 등장한다:

    "the transation has been reverted to the initial state"

  • 에러 메시지의 의미를 생각해보면, 원 상태로 복구되었다는 의미가 된다. 원 상태로 보구되었다는 의미는 곧 "상태(변수)가 변하지 않았다"가 되기 때문에 결국 가스비를 쓰지 않는 것이다.


[예시 2] :

require 조건이 false이면, require문의 위치에 상관없이 전체 함수를 실행하기 전의 상태로 돌아간다.

     function require_3(uint _n) public returns(string memory) {
       a = _n;
       require(_n <= 10, "_n should not be higher than 10. ");

       if(0 <= a && a <= 2) {
           return "A";
       } else if(3 <= a && a <= 5) {
           return "B";
       } else if(6 <= a && a <= 8) {
           return "c";
       } else {
           return "D";
       }
   }


   function getA() public view returns(uint) {
       return a;
   }
  • 위 코드를 보면, require문 전에 'a = _n;' 코드가 존재하는 것을 볼 수 있다. 이 경우, require문에 반하는 경우, a=_n;이 실행될까? 즉, require문은 require 문이 작성되기 전의 줄까지의 상태로 되돌리는 것일까? 아니면 function require_3()을 실행하기 전의 상태로 되돌리는 것일까? 실행해보면 결과를 통해 확인할 수 있다.

  • 실행 결과, require 조건을 만족하지 않는 경우, a에 _n이 입력되지 않은 것을 볼 수 있다. (바로 전 줄로 돌아가서 a에 _n이 들어가는 게 아님!)

  • 즉, require문은 아예 함수를 누르기 전으로 되돌린다.


[예시3] :

require문을 return 뒤에 쓰지 않도록 주의할 것

  • [require문이 return 전에 존재하는 경우]:
function require2_1() public pure returns(uint) {
       uint a = 1;
       bool b;


       require(b, "go back");
       return a;
   }
  • a가 반환되지 않는다. 즉, require 조건에 걸려, uint a = 1;을 하기 전의 상태로 되돌아간다.

  • [require문이 return 뒤에 존재하는 경우]:

function require2_2() public pure returns(uint) {
       uint a = 1;
       bool b;
       return a;
       require(b, "go back");
      
   }
  • 얘는 a = 1 나옴. require 까지 못 감
    return 뒤에 쓰지 않도록 주의할 것

[예시4] :

require문이 존재하는 경우, 함수 속의 함수도 실행되기 전으로 돌아간다.

contract Require3 {
   uint a;


   function setAasFive() public {
       a = 5;
   }


   function getInput(uint _n) public {
       setAasFive();
       require(_n >= 10, "go back");
   }






   function getA() public view returns(uint) {
       return a;
   }
}
  • getinput(7) 실행 시, require 조건이 false되어 getInput() 함수 내부에 있던 setAsFive() 함수조차 실행되기 전으로 돌아가 a가 0 으로 반환된다.
profile
블록체인 개발자 - 개발 정보 기록 및 공유
post-custom-banner

0개의 댓글