본문으로 건너뛰기
전체 글

토큰은 있는데 가스비가 없다면: BXB의 거래 대납 시나리오

· 약 8분
Bankware Global Engineering

고객 A에게 토큰 100개가 있다. B에게 10개를 보내려는데, 지갑에는 네트워크 수수료를 낼 기본 코인이 없다. 토큰을 보낼 권리와 잔액이 있어도 거래를 시작하는 데 필요한 다른 자산이 빠져 있는 상황이다.

서비스가 수수료를 대신 내면 고객에게 기본 코인을 먼저 구하도록 요구하지 않을 수 있다. 그렇다면 비용을 내는 서비스가 A의 토큰도 마음대로 보낼 수 있게 되는 것일까? 누가 비용을 내는지와 누가 A의 계정에서 실행을 허용하는지를 나누어야 한다.

BXB의 대납 경로는 EIP-7702로 기존 계정에 연결한 실행 코드와 후원자 지갑을 함께 사용한다. 토큰 10개를 보내는 예제로, 처음 계정을 준비할 때와 실제 거래를 실행할 때 무엇이 필요한지 따라가 보자.

1. 토큰 10개와 수수료를 따로 계산한다

이번 예제의 A는 기관이 키를 관리하는 기존 EOA다. EOA는 개인키의 서명으로 제어하는 블록체인 계정이다. 1편의 스마트 계정 예제와 독립적인 사례로, 같은 잔액을 새 계정으로 옮기는 과정은 가정하지 않는다. EIP-7702를 지원하는 한 EVM 네트워크에 토큰 T와 필요한 위임 실행 코드가 준비돼 있다고 하자.

T의 소수 자릿수는 0이므로 컨트랙트에 넣는 정수 10이 토큰 10개다. A는 T 100개와 기본 코인 0개, B는 T 0개를 갖고 있다. 수수료를 낼 서비스의 후원자 지갑 S에는 기본 코인 1개가 있다. 발행·소각·토큰 전송 수수료·다른 동시 거래는 없으며, 서비스는 이번 대납 비용을 고객에게 다시 청구하지 않는다.

처음 위임을 등록하는 비용은 별도로 계산하고, 위임 준비가 끝난 뒤의 전송 한 건만 보자. 그 거래의 실제 수수료 F가 기본 코인 0.001개였다고 가정하면 성공 결과는 다음과 같다. F는 고정 요금이나 측정 결과가 아니라 계산을 위한 가정이다.

항목전송 전성공한 전송 후
A의 토큰 T10090
B의 토큰 T010
A의 기본 코인00
S의 기본 코인10.999

토큰 100개의 합계는 보존되고, 수수료는 S의 기본 코인에서 나간다. 고객의 지갑에 기본 코인을 먼저 보내 주는 절차 없이도 이 결과에 도달하는 것이 이번 대납의 목표다. 수수료가 사라진 것이 아니라 비용을 부담하는 계정이 달라진 것이다.

2. 처음에는 A의 주소에 실행 규칙을 연결한다

일반적인 EOA A의 키로 거래를 만들면 A가 그 거래의 가스비도 부담한다. 다른 계정 S가 비용을 내면서 A의 토큰을 보내려면, S의 요청을 A의 계정에서 어떻게 받아들일지 정해야 한다.

EIP-7702의 위임은 EOA 주소가 지정한 코드의 실행 규칙을 사용하도록 연결한다. 코드는 A의 계정 맥락에서 실행되므로, 그 코드가 토큰 T를 호출하면 T에는 A가 호출한 것으로 전달된다. 토큰을 후원자에게 맡겼다가 다시 보내는 구조가 아니다. 주소와 자산을 유지한 채 코드의 규칙을 쓰는 원리는 EIP-7702의 EOA 위임을 설명한 글에서 더 자세히 다룬다.

이를 처음 설정할 때는 A의 계정 키로 어떤 코드를 위임 대상으로 삼을지 허가하는 서명, 즉 authorization을 만든다. BXB는 이 허가를 포함한 거래를 후원자 키로 서명해 체인에 제출하는 경로를 둔다. A의 허가 서명과 수수료를 내는 거래의 서명이 함께 필요하지만, 두 서명의 역할은 다르다.

이 준비는 로컬 설정에 주소 하나를 적는 것으로 끝나지 않는다. 사용할 네트워크에 실행 코드가 있어야 하고, 체인에서 A의 위임이 적용된 상태여야 한다. 이 설정 거래에도 수수료가 들며, 앞의 F에는 포함하지 않았다.

위임은 해당 거래가 끝나도 유지된다. 이미 준비된 A가 다음 전송을 요청하면 같은 위임 경로를 재사용할 수 있다. 다만 실행 코드를 계속 사용하는 허가와 이번에 B에게 10개를 보내는 허가는 별개의 문제다. 후자는 위임된 코드가 어떤 조건으로 호출을 받아들이는지에 달려 있다.

3. 이번 전송에는 서로 다른 세 가지 서명 역할이 있다

먼저 개별 호출마다 A의 계정 키로 서명하는 USER_SIGNATURE 방식을 보자. 업무 시스템은 고객 A를 인증하고, B에게 10개를 보내는 요청이 업무 규칙을 만족하는지 판단한다. BXB는 선택된 A의 지갑을 바탕으로 토큰 T의 전송 호출을 만들고, 이 호출 내용에 대한 실행 서명을 준비한다.

이름에 사용자 서명이 들어 있지만, 여기서는 수탁 서버의 서명 경로가 A의 계정 키를 사용한다. 고객 브라우저가 직접 개인키로 서명했다는 뜻이 아니다. 이 서명만으로 고객이 어떤 화면을 보고 동의했는지 입증할 수도 없다. 고객 인증과 업무 승인, 서명키 사용의 관계는 고객 계정과 서명 경계를 다룬 글에서 설명한 책임 구분을 따른다.

BXB의 이 방식은 실행 서명에 호출 대상과 내용, 네트워크와 계정, 실행 순번과 유효 기한을 묶는다. 실행 순번인 nonce는 같은 승인을 반복해서 사용하는 것을 막기 위한 값이다. 현재 구현은 호출 서명을 만들 때 유효 기한을 5분 뒤로 잡는다. 위임된 코드는 이 조건과 A의 서명을 확인한 뒤에만 토큰 컨트랙트를 호출한다.

마지막으로 S의 키가 바깥쪽 블록체인 거래를 서명한다. S는 이 거래로 A의 주소를 호출하고 수수료를 낸다. A의 주소에서 실행되는 코드는 안쪽의 승인 조건을 검사한다. 따라서 수수료를 내는 서명과 A의 자산을 움직일 호출에 대한 서명을 구분할 수 있다.

서명계정 키승인 대상
위임 설정AA에서 사용할 실행 코드
이번 호출A조건에 묶인 T 전송
바깥 거래SA 호출과 비용 부담

이미 위임이 설정된 이번 전송의 흐름은 다음과 같다.

업무 시스템의 고객 인증·전송 허가

수탁 서버가 A의 키로 실행 내용 서명

S가 바깥쪽 거래를 서명하고 제출

A의 위임 코드가 실행 승인 검사

A의 계정에서 토큰 T의 전송 실행

실행 결과와 A 90 / B 10 확인

거래 해시를 받았다는 사실과 전송 성공은 같지 않다. 실행 결과인 receipt와 토큰 이벤트·잔액을 확인하고, 서비스가 요구하는 확정 조건을 적용한 뒤 완료로 판단해야 한다.

4. 미리 허용한 후원자가 요청하는 방식도 있다

BXB는 SPONSOR_WHITELIST라는 다른 검증 방식도 둔다. 이 방식에서는 위임 코드가 호출한 계정이 미리 허용된 후원자인지, 요청한 실행 순번이 현재 값과 맞는지 확인한다. 허용 목록은 운영자가 관리하며, 개별 호출마다 A의 실행 서명을 요구하는 방식과는 다르다.

초기 계정 위임에는 여전히 A의 허가가 필요하다. 그 뒤 실행할 때의 판단을 “이 호출에 A의 유효한 서명이 있는가”에서 “허용된 후원자가 올바른 순번으로 요청했는가”로 달리하는 것이다. 허용된 후원자는 개별 A 서명 없이 A의 주소에서 실행할 대상과 호출 내용을 선택할 수 있다. 따라서 후원자 등록은 비용 부담자를 정하는 일과 실행 권한을 부여하는 일을 함께 뜻한다.

방식실행 조건관리 책임
호출 서명A의 서명·순번·기한업무 승인과 서명 내용
허용 후원자후원자 허용·순번후원자 권한과 호출 정책

앞 방식의 5분 기한을 뒤 방식에도 적용된다고 가정해서는 안 된다. 두 방식 모두에 일일 예산이나 건별 금액 한도가 공통으로 제공되는 것도 아니다. 서비스가 “오늘은 고객당 다섯 번까지만 대납한다”거나 “이 토큰만 보낸다”는 조건을 원한다면, 그 업무 정책을 실제 어느 계층에서 검사할지 따로 정해야 한다.

이번에 살펴본 BXB 경로에서는 S가 직접 거래를 서명해 전송한다. 이를 ERC-4337의 Paymaster라고 부르지는 않는다. Paymaster를 이용하는 경로와 같은 대납 목적을 가질 수 있지만, 여기서 확인한 실행은 EntryPoint·Bundler를 거치는 흐름이 아니다. ERC-4337 Paymaster를 다룬 글은 그 경로에서 실행 승인과 수수료 부담을 어떻게 나누는지 설명한다.

5. 전송이 실패해도 후원자의 비용은 남을 수 있다

다시 USER_SIGNATURE 방식에서, A100/B0 상태로 10개를 보내려는 요청을 보자. 호출 서명을 만들고 전송할 때는 기한 안이었지만, 거래가 대기하다 기한을 지난 뒤 블록에서 실행됐다고 가정한다. 처음 위임을 새로 등록하는 거래가 아니라 이미 위임된 계정의 개별 전송이다.

위임된 코드는 유효 기한 검사에서 실행을 거절한다. 토큰 T의 전송까지 진행되지 않으므로, 다른 거래가 없다면 A100/B0이 그대로 남는다. 그러나 거래가 블록에 포함돼 검사를 실행했다면 그 과정에서 사용한 가스는 있다. 전송이 실패했다고 후원자의 수수료가 모두 돌려오는 것은 아니다.

실패한 거래의 실제 수수료를 G라고 두면 S의 기본 코인은 1에서 1 − G가 된다. G는 성공 예제의 F와 같다고 가정하지 않는다. A의 기본 코인은 여전히 0이다. 반면 제출 전에 만료를 발견해 요청을 중단했고 체인에 아무 거래도 올리지 않았다면, 그 시도에 대한 온체인 실행 수수료는 생기지 않는다.

이 차이 때문에 “대납을 거절했다”는 결과에도 어느 단계에서 멈췄는지가 필요하다. 업무상 거절, 전송 전 검사 실패, 체인에서의 실행 실패를 같은 비용 상태로 취급하면 고객 응대와 정산이 어긋난다. 실패한 호출을 다시 시도하려면 기존 거래 결과부터 확인하고, 현재 순번과 기한에 맞춰 실행 승인을 다시 준비해야 한다.

이 사례에서 만료된 것은 이번 호출의 서명이다. A의 계정에 설정한 위임 자체가 자동으로 해제되지는 않는다. 실패 결과, 남아 있는 위임, 다음 실행의 승인 조건은 각각 확인해야 한다.

6. 대납을 멈추는 일과 위임을 철회하는 일

서비스가 더 이상 비용을 부담하지 않으려면 후원자를 운영 대상에서 빼거나, 허용 후원자 방식의 목록에서 권한을 제거할 수 있다. A의 계정이 위임된 코드를 사용하지 않게 하려면 계정 위임 자체를 철회하는 단계가 필요하다.

BXB에는 A의 키로 철회 authorization을 만들고 후원자가 그 거래를 제출하는 경로가 있다. EIP-7702의 철회 규칙은 0 주소를 위임 대상으로 지정한 유효한 허가로 계정의 위임 코드를 지운다. 철회도 체인에 반영할 거래이므로 서명과 비용이 필요하며, 단순히 서버의 사용 설정을 끄는 것과 구별해야 한다.

철회가 적용돼도 이미 완료된 A에서 B로의 토큰 전송이 되돌아가는 것은 아니다. 성공 사례의 A90/B10은 그대로이며, 이후 어떤 실행 경로를 사용할지가 바뀐다. 또한 가스비 대납은 A가 보낼 자산을 대신 채워 주는 기능이 아니다. A가 보유하지 않은 기본 코인을 전송 금액으로 쓰려는 문제까지 해결해 주지는 않는다.

고객에게는 “기본 코인을 따로 준비하지 않고 토큰 10개를 보냈다”는 경험이 남는다. 이를 서비스로 제공하려면 계정이 사용할 코드, 개별 실행을 허용하는 조건, 비용을 부담할 후원자와 실패 시 비용을 함께 관리해야 한다. BXB의 이 경로는 그 역할들을 연결한다. 업무 시스템은 고객의 의사와 권한을 확인하고, 기관은 어떤 실행을 어떤 조건으로 후원할지 정함으로써 대납의 범위를 완성한다.