[멋쟁이 사자처럼 블록체인 스쿨 3기] 23-05-17

임형석·2023년 5월 22일
0

Solidity


receive

receive{} external payable{}

위의 코드가 컨트랙트에 들어가 있으면,

이 컨트랙트는 누구에게든 이더리움을 받을 수 있다.

receive 가 없다면, 컨트랙트 내의 함수에 payable 을 넣어서

msg.value 를 통해서만 이더리움을 보낼 수 있다.

다음과 같은 컨트랙트를 적어보았다.

다음의 컨트랙트 C1, C2 에 각각 이더리움을 보내보면 어떻게 될까?

contract C1 {
    function deposit() public payable {}
    receive() external payable{}
}

contract C2 {
    function deposit() public payable {}
}

C1 은 이더리움을 받을 수 있지만, C2 는 이더리움을 받을 수 없다.

왜 receive 함수는 external visibility 와, payable 함수가 붙어야 할까?

코드를 아래 처럼 고쳐서 컴파일 해보았다.

receive();

아래와 같은 에러가 뜬다.

  1. receive 함수는 external visibility 가 정의 되어야 함.
  2. receive 함수는 payable 함수가 사용되어야 함.

기본적으로 정의되는 internal 이나, nonpayable 로는 함수 사용이 불가능하다.


address

이더리움 주소의 특징

CA(contract account) > 개인키가 없음. 거래를 몇번 일으켰는지로 결정됨 , 지갑 안에 코드가 있음.

EOA(externally owned account) > 지갑 안에 키가 있음.

CA 의 경우엔, 로컬 환경에서 똑같이 컨트랙트를 만들어 배포한다면 같은 address 를 갖게 된다. (실제 메인넷 또는 테스트넷에선 사실상 불가능한 일)

이더리움 주소의 특징은 아래의 이미지를 보면 이해하기 쉽다.

1) 개인 지갑에서 개인 지갑으로 전송할 때.
2)3) 개인지갑에서 컨트랙트로 전송할 때.
4) 컨트랙트를 인스턴스화 시켰을 때.(Internal transaction)


And Or 연산자의 혼합 사용

&& || 와 같은 연산자를 혼합해서 사용하면 어떻게 될까?

어떻게 구분이 되는지, 어떤 상황에서 true 인지, false 인지 헷갈릴 것이다.

다음과 같은 코드와 요약으로 알아보면....

   function ABC() public returns(string memory) {
       require(a ==0 && b != 1 || c ==0);
       /*
       a=0 b=2 c=2 <- 앞의 조건 2개 만족, 뒤의 조건 불만족 -> o
       a=0 b=1 c=0 <- 앞의 조건 1개 만족, 뒤의 조건 만족 -> o
       a=0 b=1 c=1 <- 앞의 조건 1개 만족, 뒤의 조건 불만족 -> x
       a=1 b=1 c=0 <- 앞의 조건 0개 만족, 뒤의 조건 만족 -> o
       a=1 b=1 c=1 <- 모두 불만족 -> x
       */
       return "aaa";
   }

   function ABC2() public view returns(string memory) {
       require(a ==0 || b != 1 && c ==0);
       /*
       (a // b,c)
       (a,b // c)
       (a,c // b)
       a=0, b=1, c=1 <- a만 만족 -> o
       a=1, b=2, c=1 <- b만 만족 -> x
       a=1, b=1, c=0 <- c만 만족 -> x
       a=0, b=2, c=1 <- a,b 만족 -> o
       a=0, b=1, c=0 <- a,c 만족 -> o 
       a=1, b=2, c=0 <- b,c 만족 -> o
       */
       return "aaa";
       /*
       0,0,0, -> o
       */
   }

   function ABCD() public view returns(string memory) {
       require(a ==0 || b != 1 && c ==0 || d==0);
       /*
       a=0, b=1, c=1, d=1 <- a만 만족 -> o
       a=1, b=0, c=1, d=1 <- b만 만족 -> x
       a=1, b=1, c=0, d=1 <- c만 만족 -> x
       a=1, b=1, c=1, d=0 <- d만 만족 -> o 
       a=0, b=0, c=1, d=1 <- a,b만 만족 -> o
       a=0, b=1, c=0, d=1 <- a,c만 만족 -> o
       a=0, b=1, c=1, d=0 <- a,d만 만족 -> o
       a=1, b=0, c=0, d=1 <- b,c만 만족 -> o
       a=1, b=0, c=1, d=0 <- b,d만 만족 -> o
       a=1, b=1, c=0, d=0 <- c,d만 만족 -> o
       a=0, b=0, c=0, d=1 <- a,b,c만 만족 -> 
       a=0, b=0, c=1, d=0 <- a,b,d만 만족 -> o
       a=0, b=1, c=0, d=0 <- a,c,d만 만족 -> o
       a=1, b=0, c=0, d=0 <- b,c,d만 만족 -> o
       */

       return "aaa";
  }

위의 코드와 주석으로 보면 어떤 기준으로 만족하는지 알기 힘들다.

하지만, || 연산자를 기준으로 나뉜다고 생각하면 매우 쉽다.

a || b && c || d 라면,

a || b,c || d 로 총 세 그룹이 나뉘어져 있다고 생각하면 쉽다.

그래서 세 그룹중 하나의 그룹만 만족하면 true 가 된다.

어렵고 복잡해 보이지만 생각보다 쉽다.


0개의 댓글