본문으로 건너뛰기
전체 글

ERC-4337과 Paymaster: 거래 비용을 사용자 대신 부담하는 구조

· 약 8분
Bankware Global Engineering

고객에게 토큰 100개를 지급했는데, 10개를 보내려면 먼저 ETH를 구해야 한다. 서비스에서 쓸 자산은 이미 있는데 네트워크 수수료를 위한 자산이 하나 더 필요한 것이다. 서비스 운영자가 그 비용을 부담하면 고객은 토큰 전송에만 집중할 수 있다.

그렇다면 누가 고객 대신 거래를 제출하고, 어느 잔액에서 비용이 빠져나갈까? ERC-4337과 Paymaster를 이해하려면 자산을 움직일 권한, 체인에 거래를 제출하는 역할, 최종 비용 부담을 나누어 보아야 한다. ETH가 없는 계정의 작은 전송을 끝까지 따라가 보자.

토큰을 가진 주소와 서명하는 키를 구분한다

이더리움에 스마트 계정 A가 이미 배포되어 있다고 하자. 스마트 계정은 누가 어떤 요청을 실행할 수 있는지 컨트랙트 코드로 판단하는 계정이다. A에는 토큰 T가 100개 있고 ETH는 0이다. 받는 주소 B에는 T가 0개 있다. 목표는 A에서 B로 T 10개를 보내는 것이다.

여기서는 T의 소수 자릿수를 0으로 두고, 토큰 전송 수수료·발행·소각과 다른 동시 거래는 없다고 가정한다. 계정의 최초 배포 비용도 이 전송에서 제외한다. 실제 체인에서 측정한 결과가 아닌 설명용 예제다.

A를 제어하는 사람은 개인키로 관리하는 일반 계정, 즉 EOA C를 가지고 있다고 하자. A의 코드는 C에 대응하는 서명을 유효한 승인으로 받아들이도록 설정되어 있다. 토큰을 가진 주소는 A이고, 요청에 서명하는 개인키는 C의 키다. C의 주소에 토큰 100개가 있는 것은 아니다. A가 요청의 서명을 확인한 뒤 토큰 컨트랙트를 호출하면 A의 잔액에서 10개가 이동한다.

이 글은 키 하나의 서명을 확인하는 계정으로 설명한다. 실제 스마트 계정의 인증 규칙은 다중 서명 등으로 달라질 수 있다. ERC-4337은 그 판단을 계정의 코드에 맡긴다. 스마트 계정의 역할은 자산의 주소와 승인 규칙을 함께 관리하는 데 있다.

사용자는 실행할 요청에 서명한다

일반적인 EOA 전송에서는 사용자가 체인 거래에 서명하고 그 EOA가 가스비를 부담한다. ERC-4337에서는 앱이 먼저 UserOperation이라는 실행 요청을 만든다. 이 요청은 사용자 계정에서 수행할 동작을 담지만, 그 자체가 블록에 직접 들어가는 일반 거래는 아니다. ERC-4337 명세는 이 요청을 처리할 별도 제출 경로를 정의한다.

예제의 요청에는 실행 계정 A, B에게 T 10개를 보내라는 호출 내용, 중복 실행을 구분할 번호인 nonce, 가스 사용 한도와 수수료 조건 등이 들어간다. Paymaster를 이용한다면 비용 부담 승인을 확인할 정보도 포함한다. 사용자는 앱이 구성한 요청에 C의 키로 서명한다.

이 서명은 A가 자신의 승인 규칙을 확인하는 데 쓰인다. C가 서명했다는 이유로 C의 주소에서 토큰이 나가거나, C가 가스비를 내는 거래를 직접 제출하는 것은 아니다. 서명을 만드는 행위 자체도 온체인 거래가 아니다. 따라서 이 예제의 전송을 승인하려고 C에 ETH를 먼저 충전할 필요는 없다.

앱은 받는 주소와 수량만 보여 주고 끝내기보다, 어떤 계정이 무엇을 실행하도록 승인하는지도 일치시켜야 한다. 사용자가 승인한 요청과 실제 실행할 호출이 연결되어야 비용 대납도 의미가 있다.

계정의 승인과 Paymaster의 승인은 다르다

Paymaster는 사용자의 가스비를 부담할지를 판단하는 컨트랙트다. 예를 들어 서비스 운영자는 “우리 토큰의 전송에 한해 요청당 정해진 비용까지 지원한다”는 정책을 둘 수 있다. 어떤 사용자·호출·유효 기간을 지원할지는 Paymaster의 설계와 운영 정책에 달려 있다. Paymaster 안내는 이런 조건부 비용 부담을 주요 역할로 설명한다.

A가 확인하는 질문은 “이 요청이 A의 자산을 움직일 권한을 갖는가?”다. Paymaster가 확인하는 질문은 “이 요청의 비용을 우리 예산에서 지불할 것인가?”다. 유효한 사용자 서명이 있어도 지원 대상이 아니면 대납은 거절될 수 있다. 반대로 운영자가 비용 부담을 승인했다고 해서 A의 서명 검증을 생략할 수는 없다.

운영 서버가 정책을 확인한 뒤 승인 정보를 발급하고 Paymaster가 이를 검증하는 방식도 가능하다. 하지만 모든 Paymaster가 같은 서버나 같은 서명 형식을 쓰는 것은 아니다. Paymaster 유형에는 허용 목록 방식과 별도 승인 서명 방식 등이 소개되어 있다. 예제에서는 사용자에게 토큰을 추가로 청구하지 않고 운영자가 전액 부담하는 정책을 선택한다.

두 승인을 확인하는 공통 진입점이 EntryPoint다. 요청의 검증과 실행, 비용 정산을 조정하는 컨트랙트로, 계정의 validateUserOp와 Paymaster의 validatePaymasterUserOp를 각각 호출한다. Paymaster 경로에서도 계정 검증이 유지되는 이유가 여기에 있다.

Bundler가 실제 체인 거래를 제출한다

사용자의 서명이 준비되면 앱은 요청을 Bundler에 보낸다. Bundler는 실행 요청들을 받아 미리 검증하고, 하나 이상의 요청을 묶어 EntryPoint의 handleOps를 호출하는 체인 거래를 제출한다. 이 외부 거래의 가스비를 우선 부담하는 쪽도 Bundler다. Bundler의 역할은 요청을 전달하는 데서 끝나지 않고 제출 비용을 감수하는 데까지 이어진다.

예제의 실행 경로를 줄이면 다음과 같다.

사용자: C의 키로 요청 서명

Bundler: 사전 검증·거래 제출

EntryPoint: 두 승인 확인

스마트 계정 A: 호출 실행

토큰 T: A에서 B로 10개

EntryPoint가 검증을 통과한 A를 호출하면, A의 코드가 T의 전송 함수를 호출한다. 토큰 컨트랙트에서 전송 주체는 A다. Bundler가 외부 거래를 보냈다고 해서 Bundler의 토큰을 보내는 것이 아니며, Paymaster가 비용을 승인했다고 해서 Paymaster가 A의 토큰을 소유하는 것도 아니다.

사전 검증은 Bundler가 비용을 돌려받을 수 없는 요청을 걸러 내는 데 필요하다. 계정의 서명과 nonce, Paymaster의 승인과 충분한 예치금 등을 실행 전에 확인한다. 실제 체인에서는 EntryPoint를 통해 다시 검증과 실행이 이루어진다.

비용은 EntryPoint의 예치금에서 정산된다

운영자가 Paymaster 주소에 ETH를 보유하게 하는 것만으로 이 경로의 준비가 끝나지는 않는다. EntryPoint 안에 그 Paymaster의 비용 정산용 예치금인 deposit이 있어야 한다. 검증 단계에서는 요청에 필요한 최대 비용을 감당할 수 있는지 확인하고, 처리 후 해당 요청의 비용을 정산한다. 비용으로 사용되지 않은 선확보 금액은 예치금에 남거나 돌려진다. EntryPoint의 비용 처리는 이 잔액을 통해 이루어진다.

예제에서 시작 예치금은 0.010 ETH이고, 성공한 요청에 정산된 비용 F를 0.001 ETH로 가정하자. F는 설명을 위한 숫자로, 전송 한 번의 실제 측정값이나 고정 요금이 아니다. 계정 검증과 실행 등 요청 처리에 드는 비용을 포함해 정산된 금액으로 둔다.

잔액실행 전성공 후
A의 T10090
B의 T010
A의 ETH00
Paymaster 예치금0.010 ETH0.009 ETH

T의 합계는 여전히 100개다. 운영자가 부담한 F만큼 예치금이 줄고, EntryPoint는 비용을 모아 Bundler가 지정한 수취 주소인 beneficiary에 지급한다. 이 예제에서는 Bundler 자신의 수취 주소로 둔다. Bundler는 외부 거래에 필요한 ETH를 마련해 제출하고 이 경로로 비용을 보전받는다. 여러 요청이 묶인 경우에는 외부 거래 전체의 가스비와 개별 요청의 정산액을 구분해서 읽어야 한다.

Paymaster의 stake는 이 예치금과 다르다. 검증 인프라를 악용하는 행위를 제한하기 위해 잠가 두는 보증 성격의 자금으로, 인출 대기 기간 등이 적용된다. 매번 가스비를 차감하는 잔액은 deposit이다. stake 적용 조건은 검증 중 사용하는 저장소 등과 관련되며, stake 잔액이 많다고 부족한 deposit을 대신하지 않는다. 이 구분은 명세의 Paymaster 확장에 명시되어 있다.

전송이 실패해도 비용이 남을 수 있다

두 승인을 통과하고 체인에서 실행을 시작했는데 토큰 전송이 되돌려지는 경우를 생각해 보자. 예를 들어 전송 시점에 T 컨트랙트가 정지 상태라면 A의 호출이 실패할 수 있다. 이 전송의 상태 변경이 되돌려지면 A는 T 100개, B는 0개를 유지한다. 그러나 검증과 실행 시도에 사용한 가스까지 되돌아오지는 않는다.

Paymaster가 승인한 요청의 실행이 되돌려지는 경우에도 비용을 부담한다. 실패 시 비용은 그때의 처리 결과로 정산하므로 앞서 성공 사례의 F와 같다고 가정하지 않는다. 명세의 Paymaster 실행 후 처리도 성공과 실행 실패를 구분하면서 실행 실패 시의 가스비 부담을 남겨 둔다. 전송 성공 횟수만으로 대납 예산을 잡으면 실패 처리에 사용한 비용을 빠뜨리게 된다.

반면 Bundler의 오프체인 사전 검증에서 거절되어 체인에 제출되지 않은 요청은 다르다. 그 요청 때문에 온체인 가스비가 정산되는 것은 아니다. 사전 검증 거절, 제출 후 검증 문제, 검증을 통과한 뒤의 실행 실패를 모두 “전송 실패” 하나로 기록하면 누가 무엇을 부담했는지 파악하기 어렵다. 체인에 올라간 외부 거래 자체가 되돌려지면 Bundler의 가스비가 발생하며, 예정한 Paymaster 정산도 되돌려질 수 있다.

사용자에게 가스비가 보이지 않을 때의 운영 책임

A는 ETH를 받지 않고도 T 10개를 보냈다. 그 결과를 만든 것은 사용자에게 ETH를 미리 송금한 일이 아니라, 사용자의 실행 승인과 서비스의 비용 승인을 연결하고 별도 제출자에게 비용을 정산한 경로다. 따라서 서비스에서는 토큰 잔액과 함께 대납 예산, 지원할 호출, 요청별 비용 한도, 실패 시 부담을 관리해야 한다.

예치금이 부족하거나 지원 정책이 바뀌면, A의 토큰 잔액이 충분해도 같은 요청의 대납은 중단될 수 있다. 앱은 자산 부족과 비용 지원 거절을 구분해 설명해야 한다. “사용자 가스비 0”은 비용이 사라졌다는 뜻이 아니라 사용자가 별도의 ETH를 준비하지 않아도 되도록 서비스가 지불 경로를 마련했다는 뜻이다.

이 글은 별도 컨트랙트인 스마트 계정 A의 경로를 살폈다. ERC-4337과 EIP-7702는 단순한 대체 관계가 아니며, 현재 ERC-4337 명세에는 7702 권한 위임을 함께 사용하는 경로도 있다. 다음 편에서는 별도의 EOA 예제로 EIP-7702가 기존 주소에 실행 코드를 연결하는 방식을 살펴본다.