본문으로 건너뛰기

지출

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

Spend 액션​

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

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

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

Spent 토큰​

ActionRequest의 실행에 대한 spend는 지출된 Balance의 Token를 포함하며, 이는 TreasuryCap과 함께 확정하거나 TokenPolicy에 전달할 수 있다. 첫 번째 경우 잔액은 TreasuryCap에서 직접 소각되며, 두 번째 경우에는 TokenPolicy의 spent_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)
}