EIP-2612는 ERC-20 토큰에 permit() 함수를 추가하는 확장 표준입니다. 오프체인 EIP-712 서명만으로 토큰 지출 허용(approve)을 처리할 수 있어, 기존에 approve → transferFrom 패턴에서 필요했던 별도의 온체인 approve 트랜잭션을 제거하고 가스리스(gasless) 승인을 가능하게 합니다.
permit() 함수 시그니처
permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) 함수를 ERC-20 컨트랙트에 추가합니다. 컨트랙트는 EIP-712로 서명된 메시지를 검증해 owner가 서명한 것이 맞으면 spender의 allowance를 value로 설정합니다. v, r, s는 ECDSA 서명의 세 구성 요소입니다.
EIP-712 구조화 서명
permit 메시지는 EIP-712 표준에 따라 도메인 구분자(DOMAIN_SEPARATOR: 체인 ID, 컨트랙트 주소, 토큰 이름 등을 포함)와 구조화된 데이터 타입 해시를 결합해 서명됩니다. 이로써 피싱 사이트가 다른 체인이나 다른 컨트랙트에서 동일 서명을 재사용하는 크로스 체인·크로스 컨트랙트 리플레이 공격을 방지합니다.
가스리스 Approve와 UX 개선
기존 DeFi 사용 흐름은 ① approve 트랜잭션 → ② swap/deposit 트랜잭션의 두 단계였습니다. EIP-2612를 사용하면 사용자는 오프체인 서명만 생성하고(가스비 없음), DApp 또는 릴레이어가 permit 호출을 swap/deposit 트랜잭션에 번들링해 단 한 번의 트랜잭션으로 처리합니다. Uniswap V2/V3, DAI, USDC 등 주요 프로토콜이 구현하고 있습니다.
nonces와 리플레이 방지
각 owner 주소마다 단조 증가하는 nonce를 관리합니다. permit 서명에는 현재 nonce가 포함되며, permit 실행 후 nonce가 1 증가합니다. 이로써 동일 서명이 두 번 사용되는 리플레이 공격을 방지합니다. deadline 파라미터는 Unix 타임스탬프로, 유효 기간을 지난 서명은 무효화되어 장기 보관된 서명의 악용도 막습니다.
DOMAIN_SEPARATOR와 체인 분리
DOMAIN_SEPARATOR는 keccak256(abi.encode(typeHash, nameHash, version, chainId, address(this)))로 계산됩니다. chainId를 포함하므로 메인넷 서명이 테스트넷에서 재사용되는 것을 막습니다. 하드포크 등으로 체인 ID가 같지만 다른 네트워크가 생긴 경우를 위해 일부 구현체는 현재 블록의 chainId를 동적으로 참조합니다.