Owner가 spender allowance를 N에서 M으로 바꾸는 approve transaction을 pending 상태로 보낸 동안 spender가 기존 N을 먼저 transferFrom하고, 이후 approve(M)가 포함되면 새 M도 사용할 수 있습니다. ERC-20 approve는 현재 allowance를 새 값으로 덮어쓰므로 이 ordering을 contract가 자동 방지하지 않습니다. UI는 기존 값을 0으로 만드는 transaction이 확정된 뒤 새 값을 설정하거나, 지원 token에서는 기대 current value를 검증하는 증감·compare 방식과 nonce 기반 permit을 사용해야 합니다. Zero-first도 두 transaction 사이 서비스 중단과 각 단계 확인이 필요합니다.
두 pending 거래의 순서가 결과를 바꿉니다
Allowance가 100이고 owner가 50으로 낮추려 approve(spender,50)를 보냈다고 하겠습니다. Spender가 이를 보고 transferFrom 100을 더 높은 fee로 먼저 포함시키면 allowance는 0이 됩니다. 뒤이어 approve 50이 실행되면 다시 50이 생겨 총 150을 쓸 수 있습니다.
Owner가 100에서 200으로 늘릴 때도 spender가 기존 100을 먼저 쓰고 새 200을 받으면 총 300 사용이 가능합니다. 문제는 approve가 delta가 아니라 absolute overwrite이며 owner transaction이 기존 사용 여부를 조건으로 검사하지 않는다는 데 있습니다.
Allowance 변경은 숫자 편집이 아니라 spender에게 남은 권한과 새 권한 사이의 transaction ordering 문제입니다.
JOBCOIN 해설

그림은 이 주제의 공통 개념을 단순화한 설명입니다. 아래 항목에서 이 글의 구체적인 조건과 예외를 함께 읽어보세요.
- 두 pending 거래의 순서가 결과를 바꿉니다
Allowance가 100이고 owner가 50으로 낮추려 approve(spender,50)를 보냈다고 하겠습니다.
- 표준은 UI의 zero-first를 권고합니다
ERC-20 명세는 같은 spender의 allowance를 바꿀 때 client UI가 먼저 0으로 설정한 뒤 새 값을 두도록 권고하면서 기존 contract 호환을 위해 token contract 자체가 강제해서는 안 된다고 적습니다.
- Safe wrapper도 경제적 권한을 대신 판단하지 않습니다
SafeERC20의 forceApprove는 직접 approve가 실패하면 0 설정 뒤 desired value를 설정하는 token 호환 흐름을 제공합니다.
AI로 제작한 개념도 · 실제 가격·거래 내역·통계가 아닙니다.
표준은 UI의 zero-first를 권고합니다
ERC-20 명세는 같은 spender의 allowance를 바꿀 때 client UI가 먼저 0으로 설정한 뒤 새 값을 두도록 권고하면서 기존 contract 호환을 위해 token contract 자체가 강제해서는 안 된다고 적습니다. 따라서 모든 token이 nonzero에서 nonzero approve를 거부한다고 가정하지 않습니다.
Zero transaction이 pending인 상태에서 새 approve를 함께 보내면 block ordering에 따라 의도와 달라질 수 있습니다. 0 설정 receipt가 canonical로 충분히 확인되고 allowance 조회도 0인 뒤 다음 transaction을 전송합니다. 이 동안 spender 동작이 중단될 수 있음을 UX에 표시합니다.
| 방식 | 장점 | 남는 조건 |
|---|---|---|
| 직접 approve M | 한 transaction | old+new 경쟁 |
| approve 0→M | 폭넓은 호환 | 두 확정·중단 |
| increase/decrease | delta 의도 | token 지원·현재 값 |
| forceApprove | zero-first token 호환 | 호출 성공만 처리 |
| permit | off-chain 서명 | nonce·domain·deadline |
Safe wrapper도 경제적 권한을 대신 판단하지 않습니다
SafeERC20의 forceApprove는 직접 approve가 실패하면 0 설정 뒤 desired value를 설정하는 token 호환 흐름을 제공합니다. 이는 optional bool·특정 token 동작을 다루지만 spender가 이미 기존 allowance를 소비했는지 owner 의도를 검증하는 compare-and-swap은 아닙니다.
safeIncreaseAllowance와 safeDecreaseAllowance를 쓸 때도 token이 표준 allowance 의미를 따르는지 확인합니다. Fee-on-transfer·callback token과 upgradeable token은 transferFrom 중 다른 상태 변화를 만들 수 있습니다. Wrapper 성공을 최종 자산 안전으로 부르지 않습니다.
- 현재 on-chain allowance와 pending approvals를 조회합니다.
- Spender와 token contract 주소를 다시 확인합니다.
- 필요하면 0 승인 확정과 canonical 상태를 기다립니다.
- 새 최소 권한과 deadline을 설정합니다.
- 사용 뒤 allowance 회수와 실제 transferFrom을 감시합니다.
Permit은 mempool 거래를 서명 replay 문제로 바꿉니다
Permit은 owner가 typed data에 spender·value·nonce·deadline을 서명하고 relayer가 on-chain 제출하게 할 수 있습니다. Current nonce가 한번 소비되면 같은 signature는 재사용되지 않아야 합니다. 하지만 무제한 value와 긴 deadline을 승인하면 위험한 권한 자체는 그대로입니다.
Domain의 chainId와 verifying contract가 없거나 proxy upgrade가 domain을 잘못 처리하면 다른 배포 replay가 생길 수 있습니다. Relayer가 언제 제출할지 통제할 수도 있어 user는 deadline과 nonce 취소 정책을 알아야 합니다.
운영은 현재값과 소비 이력을 함께 보여 줍니다
Explorer의 Approval event만 최신 권한으로 가정하면 일부 token의 구현 차이나 reorg를 놓칠 수 있습니다. Canonical block 기준 allowance(owner,spender)를 직접 읽고 transferFrom events·transactions와 대조합니다.
Frontend는 ‘승인 완료’ 대신 token, spender, 현재값, 새 값과 무제한 여부를 표시합니다. Router upgrade 권한과 spender contract code가 바뀔 가능성도 별도 위험입니다. 필요한 정확한 금액과 기간만 승인하는 기본값을 둡니다.
자주 묻는 질문
Approve를 0으로 만들면 이미 사용된 token도 돌아오나요?
아닙니다. 앞으로의 transferFrom 권한만 줄이며 이미 완료된 이전 전송은 되돌리지 않습니다.
ForceApprove가 race condition을 완전히 막나요?
아닙니다. Token 호환 zero-first 호출을 돕지만 pending ordering과 기존 사용 여부를 자동 해결하지 않습니다.
무제한 permit은 nonce가 있어 안전한가요?
서명 재사용은 제한해도 한번 설정된 무제한 allowance 자체의 위험은 남습니다.
더 깊이 읽기
본문에서 다룬 개념과 확인 절차를 다음 글에서 이어서 살펴보세요.



