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.