가스 면제 프로토콜
이 문서는 가스 면제 메커니즘을 지정합니다: 트랜잭션 형식, 마커 라우팅, 거버넌스 제어, 면제 서버 API.
개요
가스 면제는 거버넌스 승인을 받은 소수의 주소("면제자")가 gasPrice = 0으로 트랜잭션을 제출할 수 있도록 하여 Stable에서 가스 없는 최종 사용자 트랜잭션을 가능하게 합니다. Stable은 현재 프로토콜별 래퍼 로직을 구현하지 않고도 가스 없는 UX를 제공하기 위해 통합할 수 있는 면제 서비스("면제 서버")를 운영하고 있습니다.
범위
이 사양은 다음을 다룹니다:
- 가스 면제 트랜잭션에 대한 프로토콜 수준 규칙
- 래퍼 트랜잭션 메커니즘 및 마커 주소
- 거버넌스 제어 승인 및 허용된 대상
- 서명된 사용자 트랜잭션 제출을 위한 면제 서버 인터페이스
정의
- 면제자(Waiver): 유효성 검사기 거버넌스를 통해 온체인에 등록되어 가스 면제 트랜잭션을 제출할 수 있는 Ethereum 주소.
- 내부 트랜잭션(InnerTx):
gasPrice = 0으로 최종 사용자가 서명한 트랜잭션. - 래퍼 트랜잭션(WrapperTx): 사용자
InnerTx를 체인으로 전송하고 실행을 승인하는 면제자가 서명한 트랜잭션. - 마커 주소(Marker address): 면제자 래퍼 트랜잭션을 식별하는 데 사용되는 센티넬 주소:
0x000000000000000000000000000000000000f333. - 허용된 대상(AllowedTarget): 면제자를 특정 계약 주소 및 메서드 선택기로 제한하는 정책.
개요
가스 면제는 래퍼 트랜잭션 패턴을 사용합니다:
- 사용자는
gasPrice = 0으로InnerTx에 서명합니다. - 면제자는
InnerTx를WrapperTx로 래핑하고 브로드캐스트합니다. - 유효성 검사기는 마커 트랜잭션을 감지하고 면제자 승인 및 정책 제약 조건을 확인한 다음 내장된
InnerTx를 실행합니다.
Stable은 승인된 면제자로 온체인에 등록된 면제 서비스(면제 서버)를 운영합니다. 서명된 InnerTx 페이로드를 제출하려면 면제 서버 API와 통합합니다.
프로토콜 사양
마커 주소 라우팅
트랜잭션은 다음의 경우에만 면제자 래퍼 트랜잭션으로 처리됩니다.
to == 0x000000000000000000000000000000000000f333.
프로토콜은 트랜잭션 data 필드를 인코딩된 내부 트랜잭션 페이로드로 해석하고 아래의 면제자 확인 규칙을 사용하여 처리합니다.
승인 및 정책 확인
각 후보 래퍼 트랜잭션에 대해 유효성 검사기는 다음을 적용해야 합니다:
-
면제자 승인
WrapperTx.from은 거버넌스를 통해 온체인에 등록된 면제자 주소여야 합니다.
-
가스 면제
WrapperTx.gasPrice는0과 같아야 합니다.InnerTx.gasPrice는0과 같아야 합니다.
-
대상 허용 목록
InnerTx.to및InnerTx.data에서 추출된 메서드 선택기는 면제자의AllowedTarget정책에 의해 허용되어야 합니다.
-
값 제한
WrapperTx.value는0과 같아야 합니다.
어떤 확인이라도 실패하면 유효성 검사기는 래퍼 트랜잭션을 거부하고 내부 트랜잭션을 실행하지 않습니다.
실행 의미론
모든 확인이 통과하면:
- 프로토콜은 사용자의
from,nonce및 호출 의미론을 유지하면서InnerTx를 사용자로 실행합니다. - 가스 계산은 면제 메커니즘에 의해 처리됩니다. 사용자는 가스를 지불하지 않으며, 면제 트랜잭션은 기능 정의에 따라
gasPrice = 0을 사용합니다. - 래퍼 트랜잭션은
InnerTx실행(래핑 해제 및 확인을 위한 오버헤드 포함)을 커버하기에 충분한gasLimit을 제공해야 합니다.
트랜잭션 형식
WrapperTx
래퍼 트랜잭션은 면제자가 서명하고 마커 주소로 전송됩니다.
WrapperTx {
from: waiver_address,
to: 0x000000000000000000000000000000000000f333,
value: 0, // 0이어야 함
data: RLP(InnerTx), // RLP 인코딩된 내부 트랜잭션
gasPrice: 0, // 0이어야 함
gasLimit: sufficient_for_inner, // 내부 실행 + 오버헤드를 커버해야 함
nonce: waiver_nonce
}InnerTx
내부 트랜잭션은 최종 사용자가 서명합니다.
InnerTx {
from: user_address,
to: target_contract,
value: value,
data: call_data,
gasPrice: 0, // 0이어야 함
gasLimit: execution_gas,
nonce: user_nonce
}거버넌스 제어 접근
면제자 승인은 유효성 검사기 거버넌스에 의해 온체인에서 통제됩니다.
거버넌스 제어는 다음을 제공합니다:
- 면제자 주소의 검토 가능한 승인
- 면제자 등록 및 업데이트의 온체인 투명성
- 취소 기능
AllowedTarget을 통한 면제자별 범위 지정
보안 모델
최종 사용자 서명 무결성
사용자는 InnerTx에 서명합니다. 면제자는 서명을 무효화하지 않고는 내부 트랜잭션 페이로드를 수정할 수 없습니다. 사용자가 의도한 트랜잭션 페이로드에만 서명하도록 여전히 확인해야 합니다.
신뢰 경계
가스 면제는 파트너가 면제 서버를 통해 제출을 라우팅하는 경우 서비스 종속성을 도입합니다:
- 서비스 가용성은 가스 없는 트랜잭션을 제출하는 기능에 영향을 미칩니다.
- 승인은 온체인에 남아 있습니다. 등록된 면제자 주소만 유효한 래퍼 제출을 생성할 수 있습니다.
통합
세 가지 경로는 동일한 온체인 결과를 생성하며, 누가 면제자 키를 보유하는지에 따라 다릅니다. 통합 경로 선택을 참조하십시오.
호스팅된 면제 서버를 사용하는 경우:
- 사용자로부터 서명된
InnerTx(gasPrice = 0)를 수집합니다. - 서명된 내부 트랜잭션을 면제 서버 API에 제출합니다.
- 스트리밍된 결과를 처리하고 최종 사용자에게 트랜잭션 해시를 표시합니다.
직접 등록한 면제자 주소에서 @stablechain/enterprise는 한 번의 호출로 WrapperTx를 빌드, 서명 및 브로드캐스트합니다. 가스 면제를 사용하여 릴레이 또는 자체 호스팅 가스 면제를 참조하여 래퍼를 직접 구성하십시오.
면제 서버
개요
면제 서버는 서명된 사용자 InnerTx 페이로드를 면제자가 승인한 래퍼 트랜잭션으로 래핑하고 브로드캐스트합니다. 래퍼 트랜잭션을 구성하거나 면제자 주소를 운영할 필요가 없습니다.
엔드포인트 및 기본 URL
기본 URL:
- 메인넷: TBD
- 테스트넷:
https://waiver.testnet.stable.xyz
인증
건강을 제외한 모든 엔드포인트는 베어러 토큰 인증을 요구합니다:
Authorization: Bearer <your-api-key>API
GET /v1/health
건강 확인 엔드포인트.
인증: 없음.
POST /v1/submit
서명된 내부 트랜잭션 배치를 제출합니다.
인증: 필수(Bearer).
요청 본문:
{
"transactions": ["0x<signedInnerTx1>", "0x<signedInnerTx2>"]
}응답은 NDJSON(줄 바꿈으로 구분된 JSON)으로 스트리밍됩니다. 각 줄은 제출된 트랜잭션 인덱스에 해당합니다.
예시:
{"index":0,"id":"abc123","success":true,"txHash":"0x..."}
{"index":1,"id":"def456","success":false,"error":{"code":"VALIDATION_FAILED","message":"invalid signature"}}GET /v1/submit
스트리밍 제출을 위한 WebSocket 인터페이스.
인증: 필수(Bearer).
통합 예시
const WAIVER_SERVER = "https://waiver.testnet.stable.xyz";
async function submitGaslessTransaction(signedInnerTxHex, apiKey) {
const response = await fetch(`${WAIVER_SERVER}/v1/submit`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
transactions: [signedInnerTxHex],
}),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value).trim().split("\n");
for (const line of lines) {
const result = JSON.parse(line);
console.log(result);
}
}
}사용자 InnerTx 생성
gasPrice = 0으로 InnerTx를 구성한 다음 사용자 서명을 수집하는 것은 사용자에게 달려 있습니다.
예시:
import { ethers } from "ethers";
async function createInnerTx(userWallet, contractAddress, callData, nonce) {
const innerTx = {
to: contractAddress,
data: callData,
value: value,
gasPrice: 0, // 면제를 위해 0이어야 함
gasLimit: 100000,
nonce: nonce,
chainId: 2201, // 메인넷은 988, 테스트넷은 2201
};
return await userWallet.signTransaction(innerTx);
}오류 코드
PARSE_ERROR: 트랜잭션 파싱 실패INVALID_REQUEST: 요청 본문 형식이 잘못됨BATCH_SIZE_EXCEEDED: 배치 크기가 허용된 최대값을 초과함VALIDATION_FAILED: 트랜잭션 유효성 검사 실패BROADCAST_FAILED: 체인으로 브로드캐스트 실패RATE_LIMITED: 비율 제한 초과QUEUE_FULL: 서버 큐가 용량에 도달함TIMEOUT: 요청 시간 초과
다음 권장 사항
- 제로 가스 트랜잭션: 가스 수수료가 0인 영수증을 보여주는 데모 중심의 설명서.
- 가스 없는 트랜잭션 활성화: 배치 제출 및 오류 처리가 포함된 전체 호스팅 API 통합 가이드.
- 자체 호스팅 가스 면제: 호스팅된 API 없이 자체 면제 인프라를 실행합니다.
- 가스 면제를 사용하여 릴레이: 유형이 지정된 Enterprise SDK 클라이언트를 사용하여 자체 면제에서 가스를 후원합니다.

