Permit Extension
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. owneris not the zero address.nonces[owner](before the state update) is equal tononce.r,sandvis a valid secp256k1 signature fromownerof 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 
permitfunction MUST setspender's allowance overowner's tokens tovalueif a valid signature is provided, and MUST increment the owner's nonce. - The 
permitfunction MUST revert if the signature is invalid or expired. - The 
DOMAIN_SEPARATORMUST be implemented according to CIP-712. - The 
noncesfunction MUST return the current nonce for an address. - The 
Approvalevent 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 allowedinstead of avalueargument, andexpiryinstead ofdeadline. - Stake allows expiring approvals, only permitting 
transferFromwhileexpiry >= 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 
permitfunction must be resistant to signature malleability. - The 
DOMAIN_SEPARATORmust be unique per contract and chain. - Upgradability and access control best practices should be followed.
 
Copyright
Copyright and related rights waived via CC0.