Skip to content

XSC-0002: Permit Authorizer

XSC-0002 standardizes signature-based token approvals through a standalone authorizer contract. The authorizer verifies the owner's signed permit and then calls the target token's approval hook.

Canonical Function

python
@export
def permit(
    token_contract: str,
    owner: str,
    spender: str,
    value: Any,
    deadline: str,
    nonce: int,
    signature: str,
):
    ...

The authorizer stores nonces[owner] and only accepts the owner's current nonce. A successful permit increments that nonce.

Token Compatibility

Tokens that support XSC-0002 expose:

python
@export
def approve_from_authorizer(owner: str, spender: str, amount: float):
    ...

That hook should restrict callers to the configured permit authorizer, write the allowance into the token's own approval state, and emit the token's normal approval event.

Message Construction

The owner signs this exact newline-separated message:

text
xian-permit-v2
chain_id:{chain_id}
authorizer:{authorizer_contract}
token_contract:{token_contract}
owner:{owner}
spender:{spender}
amount:{canonical_amount}
deadline:{deadline}
nonce:{nonce}

canonical_amount is the decimal value after contract-side normalization with decimal(str(value)). For example, 100, 100.0, and "100.000" all sign as 100.

The authorizer hashes the complete message with hashlib.sha3_text(message) and stores permits[permit_hash] = True after a successful approval. The nonce is the primary replay guard; the stored permit hash gives indexers and auditors a stable record of the exact signed approval that was consumed.

Expected Behavior

  • reject expired permits
  • reject negative values
  • reject non-current nonces
  • verify the owner's signature over the structured message
  • increment nonces[owner] only after a successful verification
  • call the target token's approve_from_authorizer(...)

deadline is checked against contract now, which means finalized block time. Permit validity depends on the timestamp of the block that includes the transaction, not on local wallet clock time or mempool arrival time.

Event Expectations

The authorizer itself does not need a separate approval event. The compatible token should emit its normal approval event when the allowance is written.