Zum Hauptinhalt springen

Permit Extension

Status: Draft
Requires: CIP-20, CIP-712

A standardized smart contract interface for approvals via signatures (CIP-712), enabling energyless approvals for CBC-20 tokens and similar standards.

Abstract

This standard defines a method for approvals via off-chain signatures (CIP-712), allowing users to approve token allowances for CBC-20 tokens without sending an on-chain transaction. CBC-2612 enables energyless approvals, improving UX and composability for wallets, dApps, and DeFi protocols.

Motivation

Traditional CBC-20 approvals require users to send an on-chain transaction, incurring energy costs and requiring two transactions for many workflows (approve + transferFrom). CBC-2612 introduces a permit function, allowing approvals to be made via signed messages, enabling energyless approvals and meta-transactions.

Specification

Compliant contracts MUST implement the following functions in addition to CBC-20:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ICBC2612 /* is ICBC20 */ {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;

function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}

The semantics are as follows:

For all addresses owner, spender, uint256s value, deadline and nonce, uint8 v, bytes32 r and s, a call to permit(owner, spender, value, deadline, v, r, s) MUST set allowance[owner][spender] to value, increment nonces[owner] by 1, and emit a corresponding Approval event, IF and ONLY IF all the following conditions are met:

  • The current blocktime is less than or equal to deadline.
  • owner is not the zero address.
  • nonces[owner] (before the state update) is equal to nonce.
  • r, s and v is a valid secp256k1 signature from owner of the message:
sha256(abi.encodePacked(
hex"1901",
DOMAIN_SEPARATOR,
sha256(abi.encode(
sha256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"),
owner,
spender,
value,
nonce,
deadline))
))

where DOMAIN_SEPARATOR is defined according to CIP-712. The DOMAIN_SEPARATOR should be unique to the contract and chain to prevent replay attacks from other domains, and satisfy the requirements of CIP-712, but is otherwise unconstrained. A common choice for DOMAIN_SEPARATOR is:

DOMAIN_SEPARATOR = sha256(
abi.encode(
sha256('CIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
sha256(bytes(name)),
sha256(bytes(version)),
chainid,
address(this)
));

The message is the CIP-712 typed structure:

{
"types": {
"CIP712Domain": [
{ "name": "name", "type": "string" },
{ "name": "version", "type": "string" },
{ "name": "chainId", "type": "uint256" },
{ "name": "verifyingContract", "type": "address" }
],
"Permit": [
{ "name": "owner", "type": "address" },
{ "name": "spender", "type": "address" },
{ "name": "value", "type": "uint256" },
{ "name": "nonce", "type": "uint256" },
{ "name": "deadline", "type": "uint256" }
]
},
"primaryType": "Permit",
"domain": {
"name": cbc20name,
"version": version,
"chainId": chainid,
"verifyingContract": tokenAddress
},
"message": {
"owner": owner,
"spender": spender,
"value": value,
"nonce": nonce,
"deadline": deadline
}
}

The caller of the permit function can be any address. If any of the above conditions are not met, the call MUST revert.

Method Behaviors

  • The permit function MUST set spender's allowance over owner's tokens to value if a valid signature is provided, and MUST increment the owner's nonce.
  • The permit function MUST revert if the signature is invalid or expired.
  • The DOMAIN_SEPARATOR MUST be implemented according to CIP-712.
  • The nonces function MUST return the current nonce for an address.
  • The Approval event MUST be emitted on a successful permit.

Backward Compatibility

There are existing permit functions in some token contracts (e.g., DAI, Stake) with different semantics:

  • DAI uses a bool allowed instead of a value argument, and expiry instead of deadline.
  • Stake allows expiring approvals, only permitting transferFrom while expiry >= block.timestamp.

CBC-2612 aligns with the Uniswap V2 implementation and the CBC-20 standard, using value and deadline as specified above. The requirement to revert if the permit is invalid is consistent with all major implementations.

Reference Implementation

A reference implementation can be provided upon request, following the CBC-2612 interface and best practices for signature verification and nonce management.

Rationale

CBC-2612 improves UX and composability by enabling energyless approvals, reducing friction for users and enabling new workflows for wallets and dApps.

Security Considerations

  • Implementers must ensure signatures are unique and cannot be replayed (use nonces).
  • The permit function must be resistant to signature malleability.
  • The DOMAIN_SEPARATOR must be unique per contract and chain.
  • Upgradability and access control best practices should be followed.

Copyright and related rights waived via CC0.

Tags:CBC