LP-3026
ImplementedLRC-20 Permit Extension
Gasless approval extension for LRC-20 tokens via EIP-2612 signatures
LP-3026: LRC-20 Permit Extension
Abstract
This LP defines the Permit extension for LRC-20 tokens, enabling gasless approvals through EIP-2612 signatures.
Motivation
Traditional ERC-20 approvals require a separate transaction, creating friction:
- Users must hold native tokens for gas
- Two transactions needed for approve-then-transfer flows
- Poor UX for new users without gas tokens
The Permit extension solves this by allowing approvals via off-chain signatures.
Specification
Interface
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.8.31;
import "./ILRC20.sol";
/**
* @title ILRC20Permit
* @notice LRC-20 extension for gasless approvals (EIP-2612)
*/
interface ILRC20Permit is ILRC20 {
/**
* @notice Sets allowance via signature
* @param owner Token owner
* @param spender Approved spender
* @param value Approval amount
* @param deadline Signature expiry timestamp
* @param v Recovery byte
* @param r ECDSA signature r
* @param s ECDSA signature s
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Returns current nonce for address
* @param owner Token owner
* @return Current nonce
*/
function nonces(address owner) external view returns (uint256);
/**
* @notice Returns EIP-712 domain separator
* @return Domain separator hash
*/
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
EIP-712 Typed Data
bytes32 public constant PERMIT_TYPEHASH = keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
);
Implementation
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.8.31;
import "./LRC20.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
/**
* @title LRC20Permit
* @notice LRC-20 with EIP-2612 permit functionality
*/
abstract contract LRC20Permit is LRC20, EIP712 {
bytes32 private constant PERMIT_TYPEHASH =
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
mapping(address owner => uint256) private _nonces;
error LRC20PermitExpiredSignature(uint256 deadline);
error LRC20PermitInvalidSigner(address signer, address owner);
constructor(string memory name) EIP712(name, "1") {}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
if (block.timestamp > deadline) {
revert LRC20PermitExpiredSignature(deadline);
}
bytes32 structHash = keccak256(
abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)
);
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, v, r, s);
if (signer != owner) {
revert LRC20PermitInvalidSigner(signer, owner);
}
_approve(owner, spender, value);
}
function nonces(address owner) public view virtual returns (uint256) {
return _nonces[owner];
}
function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {
return _domainSeparatorV4();
}
function _useNonce(address owner) internal virtual returns (uint256) {
unchecked {
return _nonces[owner]++;
}
}
}
Rationale
EIP-2612 Compliance
Full compliance with EIP-2612 ensures:
- Interoperability with existing tools (Uniswap, etc.)
- Standard signature format
- Familiar developer experience
Nonce Mechanism
Sequential nonces prevent:
- Replay attacks
- Double-spending of permits
- Out-of-order execution issues
Backwards Compatibility
This extension is fully compatible with LRC-20 (LP-3020). Standard approve() functionality remains available.
Security Considerations
- Deadline Validation: Always validate signature deadline
- Nonce Tracking: Nonces must increment atomically
- Domain Separation: Use EIP-712 domain separator to prevent cross-chain/contract replay
- Front-Running: Permits can be front-run; consider using permits within atomic transactions
Reference Implementation
~/work/lux/standard/contracts/tokens/LRC20/LRC20Permit.sol
Related LPs
- LP-3020: LRC-20 Fungible Token Standard (base)
- LP-3612: LRC-2612 Permit Extension (detailed specification)
- LP-3009: Transfer with Authorization
Document Maintainer: Lux Industries Last Updated: 2025-12-25