ERC-5528 환불 가능한 토큰 (Refundable Fungible Token)
Final · 토큰 · 2022-08-16 작성
ERC-20 토큰 거래에 에스크로(escrow, 조건부 자금 보관) 기능을 더해, 거래가 완료되지 않으면 구매자가 입금한 토큰을 원래 지갑으로 돌려받을 수 있게 하는 확장 표준입니다.
왜 필요한가
암호화폐는 주소만으로 거래하는 가명 시스템이어서 이미 지불한 자금을 자동으로 되찾을 방법이 없습니다. 판매자에게 토큰을 보냈는데 거래가 약속대로 진행되지 않아도 구매자가 돈을 돌려받을 길이 없는 것입니다. 전통 금융에서는 거래가 끝날 때까지 돈을 맡아 두는 신뢰할 수 있는 에스크로 서비스가 이 문제를 해결합니다. 탈중앙 암호화폐 세계에서는 제3자 중재인 없이도 스마트 컨트랙트로 같은 역할을 구현할 수 있습니다. 이 표준은 에스크로가 완료되지 않으면 토큰을 원래 지갑으로 돌려보내는 기능을 갖춘 에스크로 서비스의 인터페이스를 정의합니다.
구현해야 하는 것
function escrowFund(address _to, uint256 _value) public returns (bool): _value만큼의 토큰을 주소 _to로 에스크로에 입금합니다. 페이어블 컨트랙트가 호출을 받아 에스크로 컨트랙트의 같은 함수로 전달합니다.function escrowRefund(address _from, uint256 _value) public returns (bool): 주소 _from에서 _value만큼의 토큰을 환불합니다. 에스크로 진행 중이거나 실패했을 때 구매자가 자금을 되찾는 데 씁니다.function escrowWithdraw() public returns (bool): 에스크로 계정에서 자금을 인출합니다. 에스크로가 완료되면 판매자와 구매자가 서로의 토큰을 가져갑니다.
심층 설명
두 종류의 컨트랙트
이 표준의 에스크로 과정에는 두 종류의 컨트랙트가 참여합니다. 페이어블 컨트랙트(Payable Contract)는 판매자와 구매자가 에스크로 컨트랙트에 자금을 넣을 때 쓰는 토큰으로, EIP-20 인터페이스를 반드시 오버라이드해야 합니다(MUST). 에스크로 컨트랙트(Escrow Contract)는 에스크로 정책을 정의하고 페이어블 컨트랙트의 토큰을 일정 기간 보관하는 컨트랙트로, EIP-20 인터페이스를 오버라이드할 필요가 없습니다. 즉 토큰 쪽은 기존 EIP-20에 세 함수를 더한 형태이고 에스크로 쪽은 정책과 보관을 맡는 별도 컨트랙트입니다.
constructor: 정책은 배포 때 고정
에스크로 컨트랙트는 에스크로 정책의 세부 내용을 변경할 수 없는 형태로 생성자에서 정의합니다. 반드시 정의해야 하는 정책은 판매자 토큰 컨트랙트 주소와 구매자 토큰 컨트랙트 주소 두 가지입니다(MUST). 그 밖에 에스크로 기간, 투자자의 최대 또는 최소 수, 입금할 토큰의 최대 또는 최소 수량, 판매자와 구매자 토큰의 환율, 사용자의 KYC 검증은 선택적으로 정의할 수 있습니다(MAY). 정책이 생성자에서 고정되므로 참여자는 배포된 컨트랙트에서 조건을 확인하고 참여할 수 있습니다.
escrowFund 동작 규칙
escrowFund는 _value만큼의 토큰을 주소 _to로 입금합니다. 에스크로 컨트랙트 쪽에서는 _to가 사용자 주소여야 하고 msg.sender가 페이어블 컨트랙트 주소여야 하며 정책 검증을 반드시 수행해야 합니다. 페이어블 컨트랙트 쪽에서는 _to가 에스크로 컨트랙트 주소여야 하고 에스크로 컨트랙트 인터페이스의 같은 함수를 반드시 호출해야 합니다. 이때 파라미터 _to에 msg.sender를 넣어, 에스크로 컨트랙트가 토큰을 보낸 실제 사용자 주소를 인식하게 합니다. 에스크로 컨트랙트는 정책에 맞지 않으면 토큰을 거부할 수 있습니다.
escrowRefund 동작 규칙
escrowRefund는 주소 _from에서 _value만큼의 토큰을 환불합니다. 에스크로 컨트랙트 쪽에서는 _from이 사용자 주소여야 하고 msg.sender가 페이어블 컨트랙트 주소여야 하며 정책 검증을 반드시 수행해야 합니다. 페이어블 컨트랙트 쪽에서는 _from이 에스크로 컨트랙트 주소여야 하고 에스크로 컨트랙트의 같은 함수를 호출하면서 파라미터 _from에 msg.sender를 넣어 사용자 주소를 인식시킵니다. 이 함수는 에스크로 과정이 진행되는 중간이나 에스크로가 실패했을 때 호출할 수 있습니다.
escrowWithdraw 동작 규칙
escrowWithdraw는 에스크로 계정에서 자금을 인출합니다. 에스크로 컨트랙트는 에스크로 과정이 완료되었는지 반드시 확인해야 하고 남아 있는 판매자 토큰과 구매자 토큰 잔액을 msg.sender의 판매자·구매자 컨트랙트 지갑으로 반드시 보내야 합니다. 페이어블 컨트랙트에서 이 함수의 구현은 선택 사항입니다. 에스크로 과정이 성공으로 끝나면 판매자는 구매자의 토큰을, 구매자는 판매자의 토큰을 가져갈 수 있습니다.
설계 근거와 하위 호환성
escrowFund, escrowRefund, escrowWithdraw 세 함수는 EIP-20의 transfer 함수를 바탕으로 설계되었습니다. 인터페이스 전체가 에스크로 운영에서 생기는 환불 문제를 다루는 데 초점을 맞춥니다. 이 표준을 구현한 페이어블 컨트랙트는 EIP-20 명세와 완전히 하위 호환되므로, 기존 지갑과 컨트랙트는 평범한 EIP-20 토큰으로 그대로 다룰 수 있습니다. 원문의 테스트 사례는 환율이 1 대 1이고 구매자 수가 2명에 도달하면 에스크로가 성공으로 종료되며 그 전에는 구매자가 입금한 토큰을 환불받을 수 있는 조건을 보여 줍니다. 이 표준은 Final 상태로 확정되었습니다.
쓸 때 주의할 점
- 에스크로 컨트랙트 결함 위험: 에스크로 컨트랙트가 판매자와 구매자의 권리를 모두 통제하므로, 에스크로 컨트랙트 안의 결함은 곧바로 예기치 않은 동작과 자금 손실로 이어질 수 있습니다.