카카오페이에서는 페이를 송금받는 측이 “돈 받기” 를 눌러야 돈이 받아지는데 ERC20은 왜 이런 구조가 아닐까?
먼저 트랜잭션이 토큰 관련인지 아닌지는 바이트 코드(abi decoding or 휴리스틱하게 분석..)를 직접 읽어야 알 수 있기 때문에 일반적으로 트랜잭션의 맥락을 파악하기 어렵습니다.
그러나 트랜잭션이 발생한 후에야 해당 트랜잭션이 토큰과 관련이 있는지 확인할 수 있습니다.
그리고 ERC20 당시 레딧 토론 쓰레드 등을 살펴보면 토큰 수신 여부를 설정한 후 토큰을 송/수신하는 과정에서 발생할 수 있는 레이스 컨디션 문제가 많이 논의됨을 알 수 있습니다 (참고: https://www.bookstack.cn/read/ethereumbook-en/spilt.12.c2a6b48ca6e1e33c.md)
예를 들어, 토큰이 전송되는 중간에 수신 여부가 변경되면 해당 트랜잭션은 실패할 수 있습니다. 블록체인과 같은 비동기 시스템에서는 레이스 컨디션 문제를 최소화하려는 설계가 중요했던 것으로 보입니다.
그리고 이미 잘 아시다시피 토큰 컨트랙트의 mapping 정보는 이더리움에서도 컨트랙트 마다 할당되는 슬롯 (내부) 에 저장이 되므로, 전역적으로 저장이 되는 것이 아니고, 그래서 토큰이 가지고 있는 데이터는 토큰 컨트랙트를 조회해야 합니다.
따라서 해당 토큰의 스마트 컨트랙트 정보를 모르는 경우, 토큰을 받았는지 알 수 없습니다. 잘 쓰이는 것 같지는 않지만 ERC20을 계승한 ERC777은 “Receive Hook”라는 기능을 제공합니다.
이 기능을 통해 토큰을 받는 계정이 토큰을 수신할지 여부를 결정할 수 있습니다.
ERC777 표준의 인터페이스 IERC777Recipient는 토큰이 수신될 때 호출되는 tokensReceived 함수를 포함하고 있습니다.
이 함수는 토큰의 이동 또는 생성이 발생할 때 호출되며, 이를 통해 토큰 수신을 제어할 수 있습니다.
이 표준은 ERC20에서 발생하는 문제를 해결하기 위해 도입되었습니다. ERC20 토큰을 다른 컨트랙트로 전송할 때, 해당 컨트랙트가 토큰을 받을 수 있는지 (혹은 받을지?) 확인할 방법이 없었기 때문입니다.
IERC777Recipient 인터페이스는 ERC777 토큰 수신 시 호출되는 함수인 tokensReceived를 정의하고 있습니다.
interface IERC777Recipient {
function tokensReceived(
address operator,
address from,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external;
}
ERC20을 컨트랙트에 보내고 빼낼 방법을 찾지 못해서 만든 것이 저 명세였다는 것을 생각하면 수발신의 표현에 집중한 내용은 아닙니다.
하지만 특정 토큰을 수신하고 나서 그 다음의 hook 액션이 필요하다는 니즈는 EOA건 Contract건 동일하기 때문에 결국 EOA와 Contract 간의 차이를 없애버리고자 하는 Account Abstraction이 유연한 상호작용을 보장해줄 것이고 여러 부가 기능을 자연스럽게 녹일 수 있는 방법이 될 것입니다.