본문으로 건너뛰기

지출

Token 타입은 store ability를 가지지 않기 때문에 이를 다른 객체에 저장하는 것은 불가능하다. 따라서 Coin과 유사한 지출 방식은 사용할 수 없다. 결제를 위해 Token을 받는 애플리케이션은 이를 자신의 잔액에 추가할 수 없다. 이 문제를 해결하기 위해 Tokenspend 메서드를 가지며, 이를 통해 하나의 애플리케이션에서 지출한 뒤 spent_balanceTokenPolicy에 전달하거나 TreasuryCap을 사용해 즉시 소각할 수 있다.

Spend 액션

spend 메서드를 호출하여 Tokens를 지출할 수 있다. 이 메서드는 다음 인자를 받는다:

// module sui::token
public fun spend<T>(token: Token<T>, ctx: &mut TxContext): ActionRequest<T>;

시그니처에서 보이듯이 Token 객체는 소비된다. 그 잔액은 spent_balanceActionRequest가 된다.

Spent 토큰

ActionRequest의 실행에 대한 spend는 지출된 BalanceToken를 포함하며, 이는 TreasuryCap과 함께 확정하거나 TokenPolicy에 전달할 수 있다. 첫 번째 경우 잔액은 TreasuryCap에서 직접 소각되며, 두 번째 경우에는 TokenPolicyspent_balance로 전달된다.

지출된 잔액은 어떤 방식으로도 사용할 수 없으며 이를 인출하는 것도 불가능하다. 유일하게 가능한 동작은 flush이며, 이는 spent_balance을 가져와 TreasuryCap를 소각하는 것이다.

Gating the spend 액션

일반적으로 spend의 실행에는 목적 없는 지출을 방지하기 위해 최소 하나의 규칙이 할당되어야 하며, 토큰을 수락하는 애플리케이션에서 지출을 승인하는 권장 방식은 지출이 수행되는 함수 내에서 이를 직접 스탬프하는 것이다. 예를 들어:

/// Rule-like witness to stamp the ActionRequest
struct GiftShop has drop {}

/// Spend the token and return a Gift + ActionRequest
public fun buy_gift(
token: Token<CREDITS>,
ctx: &mut TxContext
): (Gift, ActionRequest<CREDITS>) {

// token is spent
let action_request = token::spend(token, ctx);

// stamp the ActionRequest as performed by GiftShop
token::add_approval(GiftShop {}, &mut action_request, ctx);

// return already stamped ActionRequest
(Gift { ... }, action_request)
}