블록체인 학습
0 XP

fallback과 receive 함수

지금까지는 deposit 같은 이름 있는 payable 함수를 호출해 Ether 를 보냈습니다. 그런데 이더리움에서는 함수를 전혀 지정하지 않고 컨트랙트 주소로 Ether 만 덜렁 보내는 경우도 있습니다. 예를 들어 사용자가 지갑에서 컨트랙트 주소로 그냥 송금하는 상황입니다. 이때 자동으로 실행되는 두 가지 특수 함수가 receive 와 fallback 입니다. 둘은 직접 호출하는 것이 아니라, 특정 조건이 충족되면 EVM 이 알아서 불러 주는 일종의 "기본 대응 함수"입니다.

receive 함수

receive 는 순수하게 Ether 만 전송되고 calldata(함께 보내는 데이터)가 비어 있을 때 실행됩니다. 반드시 external payable 이어야 하며, 다른 함수와 달리 function 키워드 없이 이름 뒤에 괄호만 옵니다. 또한 인자도 반환값도 가질 수 없습니다.

fallback 함수

fallback 은 두 가지 상황에서 실행됩니다. (1) 호출한 데이터에 일치하는 함수가 없을 때, 또는 (2) Ether 가 들어왔는데 receive 함수가 정의되어 있지 않을 때입니다. fallback 역시 function 키워드 없이 선언하며, Ether 를 받으려면 payable 을 붙여야 합니다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
contract Receiver {
    event Received(address sender, uint256 amount);
    event FallbackCalled(address sender, uint256 amount);
 
    // Ether 만 보내고 데이터가 없을 때 실행
    receive() external payable {
        emit Received(msg.sender, msg.value);
    }
 
    // 일치하는 함수가 없거나, receive 가 없을 때 실행
    fallback() external payable {
        emit FallbackCalled(msg.sender, msg.value);
    }
}

어떤 것이 실행되는가?

둘 중 무엇이 실행될지는 calldata 가 비어 있는가와 receive 가 존재하는가로 결정됩니다.

상황실행되는 함수
calldata 가 비어 있음 + receive 존재receive
calldata 가 비어 있음 + receive 없음fallback
calldata 가 있고 일치 함수 없음fallback

receive 가 없으면 빈 calldata 의 Ether 전송도 fallback 으로 넘어갑니다. 둘 다 없으면 그 Ether 전송은 실패(revert)합니다.

receive 와 fallback 은 transfer/send 로 단 2300 gas 한도에서 호출될 수도 있습니다. 따라서 이 두 함수 안에서는 상태 변경이 많은 무거운 로직을 피하고, 이벤트 기록 정도의 가벼운 작업만 두는 것이 안전합니다.

Ether 를 자유롭게 받고 싶다면 receive 를, 예상치 못한 호출까지 대비하려면 fallback 을 함께 정의해 두면 됩니다.

Code Editor
에디터를 불러오는 중...
실행 결과

Run 버튼을 눌러 코드를 실행하세요.