소유자가 사용자(spender)의 승인 한도(allowance)를 N에서 M으로 바꾸는 approve 거래를 보내고 아직 대기 중일 때, 사용자가 기존 N을 먼저 transferFrom으로 빼 가고 그 뒤 approve(M)가 블록에 담기면 새 M까지 쓸 수 있습니다. ERC-20 approve는 현재 승인 한도를 새 값으로 덮어쓸 뿐이라, 계약이 이런 순서 문제를 알아서 막아 주지 않습니다. 화면에서는 기존 값을 0으로 만드는 거래가 확정된 뒤 새 값을 설정하거나, 지원하는 토큰이라면 기대하는 현재값을 확인하는 증감·비교 방식과 논스 기반 permit을 써야 합니다. 먼저 비우는 방식도 두 거래 사이에 서비스가 멈출 수 있고, 단계마다 확인이 필요합니다.
대기 중인 두 거래의 순서가 결과를 바꿉니다
승인 한도가 100인 상태에서 소유자가 50으로 낮추려고 approve(spender,50)를 보냈다고 해 보겠습니다. 사용자가 이를 보고 100만큼의 transferFrom을 더 높은 수수료로 먼저 블록에 넣으면 한도는 0이 됩니다. 이어서 approve 50이 실행되면 다시 50이 생겨 모두 150을 쓸 수 있습니다.
소유자가 한도를 100에서 200으로 늘릴 때도, 사용자가 기존 100을 먼저 쓰고 새 200을 받으면 모두 300을 쓰게 됩니다. 핵심은 approve가 차이만큼 더하는 방식이 아니라 값을 통째로 덮어쓰는 방식이고, 소유자의 거래가 기존 한도를 이미 썼는지 조건으로 확인하지 않는다는 데 있습니다.
승인 한도 변경은 숫자를 고치는 일이 아닙니다. 사용자에게 남은 권한과 새 권한 사이에서 거래 순서가 어떻게 놓이느냐의 문제입니다.
JOBCOIN 해설

그림은 이 주제의 공통 개념을 단순화한 설명입니다. 아래 항목에서 이 글의 구체적인 조건과 예외를 함께 읽어보세요.
- 대기 중인 두 거래의 순서가 결과를 바꿉니다
승인 한도가 100인 상태에서 소유자가 50으로 낮추려고 approve(spender,50)를 보냈다고 해 보겠습니다.
- 표준은 화면에서 먼저 비우라고 권합니다
ERC-20 명세는 같은 사용자의 한도를 바꿀 때 클라이언트 화면이 먼저 0으로 설정한 다음 새 값을 넣도록 권합니다.
- 안전 래퍼도 경제적 권한까지 판단해 주지는 않습니다
SafeERC20의 forceApprove는 approve를 바로 실행했다가 실패하면 0으로 설정한 뒤 원하는 값을 넣는 토큰 호환 흐름을 제공합니다.
설명을 위한 개념도 · 실제 가격·거래 내역·통계가 아닙니다.
표준은 화면에서 먼저 비우라고 권합니다
ERC-20 명세는 같은 사용자의 한도를 바꿀 때 클라이언트 화면이 먼저 0으로 설정한 다음 새 값을 넣도록 권합니다. 다만 기존 계약과의 호환을 위해 토큰 계약 자체가 이를 강제해서는 안 된다고 적고 있습니다. 그러니 모든 토큰이 남은 한도가 있는 상태에서 다른 값으로 바꾸는 approve를 거부한다고 가정하지 않습니다.
한도를 비우는 거래가 대기 중일 때 새 approve를 함께 보내면 블록 안 순서에 따라 의도와 다른 결과가 나올 수 있습니다. 0 설정 영수증이 정식 체인에서 충분히 확인되고 한도 조회 결과도 0이 된 뒤에 다음 거래를 보냅니다. 그 사이 사용자 쪽 기능이 멈출 수 있다는 점은 화면에 알려 줍니다.
| 방식 | 장점 | 남는 조건 |
|---|---|---|
| approve M 바로 실행 | 거래 한 번 | 기존·새 한도 경쟁 |
| approve 0→M | 폭넓은 호환 | 두 번 확정·서비스 중단 |
| increase/decrease | 차이만큼 바꾸는 의도 | 토큰 지원·현재값 |
| forceApprove | 먼저 비우기를 요구하는 토큰과 호환 | 호출 성공만 처리 |
| permit | 체인 밖 서명 | 논스·도메인·마감 시한 |
안전 래퍼도 경제적 권한까지 판단해 주지는 않습니다
SafeERC20의 forceApprove는 approve를 바로 실행했다가 실패하면 0으로 설정한 뒤 원하는 값을 넣는 토큰 호환 흐름을 제공합니다. 반환값이 선택적인 토큰이나 특이한 토큰 동작은 다뤄 주지만, 사용자가 이미 기존 한도를 썼는지 소유자의 의도와 맞춰 보는 비교 후 교체 방식은 아닙니다.
safeIncreaseAllowance와 safeDecreaseAllowance를 쓸 때도 토큰이 표준 승인 한도 의미를 따르는지 확인합니다. 전송 수수료형 토큰이나 콜백이 붙은 토큰, 업그레이드 가능한 토큰은 transferFrom 도중 다른 상태 변화를 일으킬 수 있습니다. 래퍼 호출이 성공했다고 자산이 최종적으로 안전하다고 부르지 않습니다.
- 현재 체인 위 승인 한도와 대기 중인 승인 거래를 조회합니다.
- 사용자 주소와 토큰 계약 주소를 다시 확인합니다.
- 필요하면 0 승인이 확정되고 정식 체인에 반영될 때까지 기다립니다.
- 새로 필요한 최소 권한과 마감 시한을 설정합니다.
- 쓴 뒤에는 한도를 회수하고 실제 transferFrom을 지켜봅니다.
permit은 멤풀 경쟁을 서명 재사용 문제로 바꿉니다
permit은 소유자가 타입 데이터에 사용자·금액·논스·마감 시한을 서명하고, 중계자가 이를 체인에 제출하게 하는 방식입니다. 현재 논스가 한 번 쓰이면 같은 서명은 다시 쓰일 수 없어야 합니다. 하지만 무제한 금액과 긴 마감 시한을 승인하면 위험한 권한 자체는 그대로입니다.
도메인에 chainId와 검증 계약 주소가 빠졌거나 프록시 업그레이드가 도메인을 잘못 처리하면 다른 배포본에서 서명이 재사용될 수 있습니다. 중계자가 언제 제출할지를 쥐고 있을 수도 있으니, 이용자는 마감 시한과 논스 취소 정책을 알아 둬야 합니다.
운영 화면은 현재값과 사용 이력을 함께 보여 줍니다
탐색기의 Approval 이벤트만 보고 최신 권한이라고 가정하면 일부 토큰의 구현 차이나 체인 재편성을 놓칠 수 있습니다. 정식 블록 기준으로 allowance(owner,spender)를 직접 읽고, transferFrom 이벤트와 거래 기록과 맞춰 봅니다.
프런트엔드는 ‘승인 완료’라는 문구 대신 토큰, 사용자 주소, 현재값, 새 값, 무제한 여부를 보여 줍니다. 라우터 업그레이드 권한이나 사용자 계약 코드가 바뀔 가능성도 따로 따져야 할 위험입니다. 꼭 필요한 금액과 기간만 승인하도록 기본값을 정해 둡니다.
자주 묻는 질문
한도를 0으로 바꾸면 이미 빠져나간 토큰도 돌아오나요?
아닙니다. 앞으로의 transferFrom 권한만 줄어들 뿐, 이미 끝난 전송은 되돌리지 않습니다.
forceApprove가 경쟁 조건을 완전히 막아 주나요?
아닙니다. 토큰 호환을 위해 먼저 비우는 호출을 도와줄 뿐, 대기 거래의 순서와 기존 한도 사용 여부까지 해결하지는 않습니다.
무제한 permit은 논스가 있으니 안전한가요?
서명 재사용은 막을 수 있어도, 한 번 설정된 무제한 승인 한도 자체의 위험은 남습니다.
더 깊이 읽기
본문에서 다룬 개념과 확인 절차를 다음 글에서 이어서 살펴보세요.



