본문으로 건너뛰기

Sponsored Transactions

Sui sponsored transaction은 한 Sui address(sponsor의 address)가 다른 address(사용자의 address)가 초기화한 transaction의 gas fee를 지불하는 것을 의미한다. Sponsored transaction을 사용하면 사이트나 앱의 사용자가 fee를 부담하지 않도록 대신 지불할 수 있다. 이는 Web2 사용자가 Web3로 진입할 때 맞닥뜨리는 on-chain에서 transaction을 수행하기 위해 토큰을 구매해야 하는 중요한 장벽을 제거한다. 예를 들어, 전환율을 높이기 위해 게이머의 초기 transaction을 sponsor할 수 있다.

Sponsored transaction은 자금 전송을 위해 SUI 토큰을 보유한 여러 계정을 유지할 필요가 없으므로 자산 관리도 용이하게 한다.

Sui sponsored transaction은 다음과 같은 용도로 사용할 수 있다:

  • 사용자가 초기화한 transaction을 sponsor(gas fee 지불)한다.
  • Sponsor로서 초기화한 transaction을 sponsor한다.
  • 사용자에게 와일드카드 GasData object를 제공한다. 이 object는 사용자 transaction의 gas fee를 대신 부담한다. GasData object는 예산이 충분한 한 해당 transaction에 대해 결정된 모든 fee 금액을 충당한다.

Potential risks using sponsored transactions

Sponsored transaction을 사용할 때 가장 중요한 잠재적 위험은 equivocation이다. 일부 조건에서는 sponsored transaction이 Sui validators가 검사할 때 gas를 포함한 연관된 모든 owned object가 locked 상태가 되는 결과를 초래할 수 있다. 이중 지출을 방지하기 위해 validators는 transaction을 검증할 때 object를 lock한다. Equivocation은 owned object의 쌍(ObjectID, SequenceNumber)이 여러 개의 확정되지 않은 transaction에서 동시에 사용될 때 발생한다.

Equivocation을 일으키려면 사용자 또는 sponsor가 원래 transaction의 owned object를 조작하려는 또 다른 transaction에 서명하고 제출해야 한다. Owned object는 오직 소유자만 사용할 수 있으므로 이 조건을 발생시킬 수 있는 이는 사용자와 sponsor뿐이다.

Create a user-initiated sponsored transaction

사용자에 의해 초기화된 sponsored transaction은 다음 단계들을 포함한다:

  1. 사용자가 GasLessTransactionData transaction을 초기화한다.
  2. 사용자가 GasLessTransactionData를 sponsor에게 보낸다.
  3. Sponsor는 transaction을 검증하고 gas fee가 포함된 TransactionData를 구성한 뒤 해당 TransactionData에 서명한다.
  4. Sponsor는 서명된 TransactionData와 sponsor의 Signature를 사용자에게 다시 보낸다.
  5. 사용자는 TransactionData를 검증 후 서명하고 이중 서명된 transaction을 full node 또는 sponsor를 통해 Sui network로 보낸다.

GasLessTransactionData

GasLessTransactionData는 기본적으로 GasData가 없는 TransactionData이다. 이는 sui-core 데이터 구조가 아니며, 사용자와 sponsor 사이의 인터페이스일 뿐이다.

다음 예시는 GasLessTransactionData object를 구성한다.

pub struct GasLessTransactionData {
pub kind: TransactionKind,
sender: SuiAddress,

}

Create a sponsor-initiated sponsored transaction

Sponsor에 의해 초기화된 sponsored transaction은 다음 단계를 포함한다:

  1. Sponsor는 transaction 세부 정보와 관련 gas fee 데이터를 포함하는 TransactionData object를 구성한다. Sponsor는 이를 사용자에게 보내기 전에 서명하여 Signature를 생성한다. 서명되지 않은 TransactionData는 email, SMS, 또는 애플리케이션 인터페이스를 통해 보낼 수 있다.
  2. 사용자는 transaction을 확인하고 서명하여 해당 transaction의 두 번째 Signature를 생성한다.
  3. 사용자는 이중 서명된 transaction을 Sui full node 또는 sponsor에게 제출하여 실행한다.

Sponsor에 의해 초기화된 sponsored transaction은 광고주로서 사용하거나 사용자가 gas fee를 지불하지 않고 특정 행동을 하도록 인센티브를 제공하기 위해 사용할 수 있다.

Create sponsored transactions using a GasData object

Transaction의 gas fee를 sponsor하기 위해 GasData object를 사용하려면, 해당 transaction에 대해 결정된 fee를 대신 지불하는 GasData object를 생성한다. 이는 오직 gas fee를 대신 지불하는 데만 사용할 수 있는 백지 수표를 사용자에게 제공하는 것과 유사하다. 사용자는 fee가 얼마인지 알거나 이를 승인할 필요가 없다.

GasData object를 사용하는 sponsor transaction은 다음 단계를 포함한다:

  1. Sponsor는 사용자에게 GasData object를 제공한다.
  2. 사용자는 TransactionData를 구성하고 서명하여 Signature를 생성한다.
  3. 사용자는 TransactionDataSignature를 sponsor에게 보낸다.
  4. Sponsor는 TransactionData를 확인하고 서명한다.
  5. Sponsor는 이중 서명된 TransactionData를 full node에 제출하여 transaction을 실행한다.

Create a Sui gas station

Sui에서 gas station은 사용자 transaction을 sponsor하기 위한 프로세스를 설정하는 장소를 설명하는 개념이다. 필요한 특정 사용자 지향 기능을 지원하도록 Sui gas station을 커스터마이즈할 수 있다. Sui gas station의 예시 유즈 케이스는 다음과 같다:

  • 네트워크의 실시간 gas price를 모니터링하여 station이 제공할 gas price를 결정한다.
  • 네트워크에서 사용자에게 제공된 gas 사용량을 추적한다.
  • 비용을 최소화하거나 잠금 상태에서 비유동적으로 남아 있는 대량의 잠금된 object 위험을 줄이기 위해 특정 gas object를 사용하는 등 gas pool 관리를 수행한다.

Authorization and rate limiting

Gas station의 성격에 따라 악의적 행위자에 의한 스팸을 방지하기 위해 다양한 권한 규칙을 적용할 수 있다. 가능한 정책은 다음을 포함한다:

  • 계정 또는 IP address별로 gas 요청을 rate limit한다.
  • 별도의 rate limit을 가진 유효한 authorization header가 있는 요청만 수락한다.

Abuse detection

Sponsor로서 제공하는 모든 gas object에 대해 사용자가 equivocation을 시도하여 object를 잠그려는지를 추적해야 한다. 이러한 행동을 감지하면 해당 사용자 또는 요청자를 적절히 차단한다.

Code examples to create a Sui gas station

다음 Rust SDK 코드 예시는 앞서 설명한 각 sponsored transaction 유형을 지원하는 Sui gas station을 구현하는 방법을 보여준다.

User-initiated sponsored transactions

API endpoint를 사용하여 GaslessTransaction transaction을 수신하고 단독 서명된 SenderSignedData object를 반환한다.

pub fn request_gas_and_signature(gasless_tx: GaslessTransaction) -> Result<SenderSignedData, Error>;

API endpoint를 사용하여 단독 서명된 SenderSignedData를 수신하고 transaction의 결과를 반환한다.

pub fn submit_sole_signed_transaction(sole_signed_data: SenderSignedData) -> Result<(Transaction, CertifiedTransactionEffects), Error>;

또는 API endpoint를 사용하여 GasData object를 반환한다.

pub fn request_gas(/*requirement data*/) -> Result<GasData, Error>;

User and sponsor-initiated transaction

API endpoint를 사용하여 이중 서명된 SenderSignedData를 수신하고 transaction의 결과를 반환한다.

pub fn submit_dual_signed_transaction(dual_signed_data: SenderSignedData) -> Result<(Transaction, CertifiedTransactionEffects), Error>;

사용자에 의해 초기화된 transaction 및 sponsor에 의해 초기화된 transaction의 경우, 사용자는 이중 서명된 transaction을 sponsor 또는 full node를 통해 제출할 수 있다.

다음 코드 블록은 sponsored transaction을 위한 TransactionData 구조와 GasObject를 설명한다. Sui GitHub repository에서 source code를 볼 수 있다.

TransactionData Structure

#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
pub struct TransactionDataV1 {
pub kind: TransactionKind,
pub sender: SuiAddress,
pub gas_data: GasData,
pub expiration: TransactionExpiration,
}

GasData Structure

#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
pub struct GasData {
pub payment: Vec<ObjectRef>,
pub owner: SuiAddress,
pub price: u64,
pub budget: u64,
}

Sui에서 transaction에 대해 더 알아보려면 Transactions을 참조하라.