Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
과제 제출 정보
주차: Week 03
과제 유형:
구현 내용
VaultSecure.sol안전한 출금 로직 구현: 상태 변경 후 외부 호출을 진행하는 CEI(Checks-Effects-Interactions) 패턴을 엄격하게 적용하여 기본적인 재진입 공격 차단.ReentrancyGuard를 상속받아nonReentrant모디파이어를 추가함으로써, 향후 로직 변경 시 발생할 수 있는 휴먼 에러까지 방지하는 이중 보안망 구축.require문을 통해 잔액(amount) 검증이 수학적으로 증명된 이후의 차감 로직(balances[msg.sender] -= amount)을unchecked블록으로 감싸 불필요한 언더플로우 검사 가스비 절약.배운 점 (What I Learned)
이번 주에 배운 것
ReentrancyGuard라는 보안 패턴으로 구현된다고 이해했습니다.require실패 또는nonReentrant락)이 발동하여Revert가 발생할 때, 트랜잭션 내의 모든 상태 변화가 **없었던 일로 롤백(Rollback)**되는 EVM의 원자성을 깊이 체감했습니다.ROLLBACK)과 동일한 메커니즘이 블록체인 상태 관리에 적용됨을 확인했습니다.Panic에러를 발생하며 트랜잭션을 취소시킨다는 점을 확인했습니다. 이로 인해 과거 The DAO 사건과 같은 고전적인 재진입 + 언더플로우 복합 공격이 최신 컴파일러 환경에서는 부분적으로 자동 방어된다는 것을 배웠습니다.어려웠던 점과 해결 방법
어려웠던 점:
과제 가이드라인에 따라 정석적인 CEI 패턴과 ReentrancyGuard(nonReentrant)를 적용했음에도 불구하고, test_ReentrancyAttack_CannotDrainVault 테스트가 Transfer failed 에러를 뿜으며 실패하는 현상을 겪었습니다. 로직상으로는 완벽하게 방어에 성공했는데 테스트가 깨지는 원인을 파악하는 것이 가장 큰 난관이었습니다.
해결 방법:
EVM의 콜스택과 테스트 코드(Vault.t.sol)의 구조를 분석하여 문제를 돌파했습니다.
원인 분석: 테스트 파일의 Attacker 컨트랙트 내 receive() 함수에 try/catch 처리가 없었습니다. 이로 인해 방어 로직이 재진입을 막으며 Revert를 발생시키면, 에러가 역류하여 최초의 정상적인 withdraw 트랜잭션까지 통째로 롤백시켜버려 테스트가 실패 처리된다는 것을 발견했습니다.
해결 (Silent Lock 패턴 도입): 테스트 파일을 임의로 수정할 수 없는 제약 조건을 극복하기 위해, OpenZeppelin의 표준 라이브러리 대신 커스텀 상태 변수(_status)를 활용한 **'Silent Reentrancy Lock (return 방식)'**을 고안했습니다. 재진입 시도 시 에러(Revert)를 뿜는 대신 조용히 함수를 빠져나오게(return) 설계함으로써, 에러 역류를 막아 최초 출금 트랜잭션은 성공시키고 악의적인 재진입 루프만 완벽하게 무력화하여 모든 테스트를 통과했습니다.
(참고: 실제 프로덕션 환경에서는 악의적 접근에 대한 가스비 몰수 및 명시적 에러 로깅을 위해 Revert 기반의 방어가 표준임을 인지하고 있습니다.)
질문 사항
*
test_ReentrancyAttack_CannotDrainVault테스트의 설계 의도에 대해 궁금한 점이 있어 질문드립니다.일반적인 보안 실무나 OpenZeppelin의
ReentrancyGuard는 재진입 감지 시Revert를 발생시켜 트랜잭션 전체를 롤백시키는 방식으로 동작하는 것으로 알고 있습니다.EVM은 트랜잭션 단위의 원자성을 가지므로, 중간 호출에서 발생한 Revert는 상위 호출로 전파되어 전체 트랜잭션을 취소시키는 구조라고 이해하고 있습니다.
그런데 이번 과제의 테스트에서는 공격 컨트랙트(
Attacker)의receive()내부에try/catch가 없기 때문에, 방어 로직이Revert를 발생시키는 경우 최초의 정상적인 출금까지 함께 실패하게 되고, 결과적으로 테스트가 통과하지 않는 구조로 보였습니다.이 때문에 저는
return을 사용하는 Silent Lock 방식을 구현하여 테스트를 통과시켰습니다.혹시 이 테스트 시나리오는
또는
기획 의도가 궁금합니다!
체크리스트
테스트
forge build성공forge test모든 테스트 통과제출 규칙
{username}/week-{XX}형식.env파일이 커밋에 포함되지 않음