실습 로드맵과 작업 방식
도입
이 트랙은 앞에서 배운 stablecoin, 서명 결제, invariant, cross-chain, agent payment 개념을 하나의 실행 기록으로 묶는 구간이다. 강의를 읽는 것만으로는 checkout 시스템을 설계할 수 없다. 직접 상태를 만들고, 실패 케이스를 재현하고, 왜 그 실패를 허용하거나 차단했는지 기록해야 한다.
실습의 목표는 "테스트가 한 번 통과했다"가 아니다. 각 랩마다 문제 정의, 실행 명령, 실패 로그, 보안 체크, production 전환 시 필요한 보강점을 남겨야 한다. 이 기록이 마지막 capstone 설계 문서의 증거가 된다.
학습 목표
- 실습 순서를 이해하고 각 실습 산출물을 정한다.
- 실패 로그와 리뷰 메모를 캡스톤 증거로 보관한다.
개념 설명
개념 읽기
실습 순서를 이해하고 각 실습 산출물을 정한다.
실패 상태 확인
랩 산출물이 캡스톤의 어떤 장과 테스트 증거로 재사용되는가
실습 산출물 작성
실습 로드맵과 작업 방식 이해 점검
완료 기준 대조
랩 산출물 목록을 작성했다.
운영실습은 08-실습/mock-stablecoin-lab의 Foundry 프로젝트를 중심으로 진행한다. 하나의 mock token을 만든 뒤 그 위에 permit checkout, ERC-3009 escrow, invariant, CCTP simulator, x402 payment server를 차례로 얹는다.
| 순서 | 랩 | 핵심 질문 | 남길 산출물 |
|---|---|---|---|
| 1 | Mock Stablecoin | 발행자 권한, freeze, pause, 서명 기능이 어떤 위험을 만드는가 | role matrix, 테스트 결과, production caveat |
| 2 | Permit Checkout | approve transaction 없이 결제를 시작할 수 있는가 | 결제 상태 머신, permit 실패 케이스 |
| 3 | ERC-3009 Escrow | 사용자의 signed authorization을 escrow 흐름으로 안전하게 소진할 수 있는가 | nonce/valid window 점검표 |
| 4 | Invariant Testing | totalSupply, balance, authorization 상태가 항상 맞는가 | invariant 후보와 counterexample 로그 |
| 5 | CCTP Simulator | burn, attestation, mint를 한 결제 여정으로 연결할 수 있는가 | cross-chain 상태표와 운영 지연 대응 |
| 6 | x402 Payment Server | HTTP 402 요구사항과 onchain payment receipt를 어떻게 연결하는가 | API 흐름, settlement evidence |
기본 검증 명령은 다음 두 개다.
forge fmt --checkforge test -vvv컨트랙트실습 코드는 학습용이다. 특히 서명 검증은 구조를 드러내기 위해 직접 ecrecover를 사용한다. 실제 배포 후보라면 OpenZeppelin ERC-20, AccessControl, ECDSA/EIP712, SafeERC20로 바꾸는 검토가 반드시 필요하다.
코드로 확인하기
앞에서 만든 설계를 실습 코드로 연결한다. 예시는 그대로 외우는 대상이 아니라, 구현 파일에서 어떤 줄을 읽고 어떤 테스트를 붙일지 정하는 기준이다.
운영Foundry 프로젝트 구조
모든 랩이 한
mock-stablecoin-lab폴더 안에 있다.src/는 컨트랙트 본체,test/는 unit과 invariant test가 같이 있다.
08-실습/mock-stablecoin-lab/├── foundry.toml├── src/│ ├── MockStablecoin.sol # mint/burn, permit, ERC-3009, role/freeze/pause│ ├── PermitCheckout.sol # ERC-2612 permit + transferFrom 결제│ ├── SignedPaymentEscrow.sol # ERC-3009 transferWithAuthorization 결제│ ├── CctpSimulator.sol # burn → attestation → mint 시뮬레이션│ └── X402PaymentServer.sol # HTTP 402 + onchain receipt└── test/ ├── MockStablecoin.t.sol ├── MockStablecoinInvariant.t.sol ├── PermitCheckout.t.sol ├── SignedPaymentEscrow.t.sol ├── CctpSimulator.t.sol └── X402PaymentServer.t.sol운영랩별 실행 명령
각 랩은 동일한
forge test --match-contract <Name>패턴으로 격리 실행한다. invariant는 단일 시드 재현을 위해--seed를 함께 남긴다.
forge test --match-contract MockStablecoin -vvforge test --match-contract PermitCheckout -vvforge test --match-contract SignedPaymentEscrow -vvforge test --match-contract MockStablecoinInvariantTest --seed 0x1 -vvvforge test --match-contract CctpSimulator -vvforge test --match-contract X402PaymentServer -vv강의 포인트
| 관점 | 확인할 질문 | 증거로 남길 것 |
|---|---|---|
| 문제 정의 | 이 랩이 checkout capstone의 어떤 위험을 줄이는가 | 랩별 한 문장 문제 정의 |
| 정상 흐름 | happy path가 어떤 상태 전이를 거치는가 | 상태표 또는 sequence diagram |
| 실패 흐름 | freeze, expired signature, used nonce, delayed attestation처럼 실패가 어디서 멈추는가 | 실패 로그와 revert/상태명 |
| 운영 판단 | production 전환 전에 어떤 라이브러리, 권한, 모니터링을 바꿔야 하는가 | production caveat 목록 |
실습 기록은 아래 구조로 통일한다.
Lab:Problem:Command:Passing evidence:Failure evidence:Security note:Capstone link:Production gap:각 랩은 시작 전, 실행 중, 종료 후에 남기는 기록이 다르다. 이 루틴을 고정하면 테스트 통과 여부만 보는 습관을 줄일 수 있다.
| 시점 | 질문 | 기록 |
|---|---|---|
| 시작 전 | 이 랩이 어떤 제품 리스크를 줄이는가 | Problem, expected states |
| 실행 중 | 어떤 입력에서 실패했는가 | command, failing input, revert reason |
| 통과 후 | 무엇이 증명됐고 무엇은 아직 증명되지 않았는가 | passing evidence, uncovered cases |
| 리뷰 전 | production으로 옮기려면 무엇이 바뀌어야 하는가 | library, permission, monitoring gap |
| capstone 편입 | 이 랩의 산출물이 최종 설계 어디에 들어가는가 | diagram, checklist, runbook link |
실무 예시
새 랩을 시작할 때 바로 코드를 수정하지 않는다. 먼저 "내가 지금 증명하려는 것"을 적어야 한다.
| 랩 | 좋은 문제 정의 | 부족한 문제 정의 |
|---|---|---|
| Mock token | freeze가 transfer뿐 아니라 approve, permit, authorization에도 적용되는지 확인한다 | ERC-20을 만든다 |
| Permit checkout | expired permit과 reused nonce가 결제 완료로 이어지지 않게 한다 | permit을 테스트한다 |
| CCTP simulator | burn 이후 attestation 지연 상태를 UI와 ledger에 분리해 남긴다 | cross-chain을 구현한다 |
예를 들어 CCTP simulator에서 테스트가 실패했다면 "실패함"으로 끝내지 않는다. 어떤 상태에서 멈췄는지, 사용자는 어떤 문구를 보아야 하는지, 운영자는 어떤 nonce와 message hash를 조회해야 하는지까지 기록한다.
랩별로 capstone에 들어갈 위치도 미리 정한다.
| 랩 | capstone 문서 위치 | 연결되는 최종 산출물 |
|---|---|---|
| Mock Stablecoin | token control model | role matrix, freeze/pause policy |
| Permit Checkout | checkout authorization | signature UX, expired/reused nonce 처리 |
| ERC-3009 Escrow | exact payment flow | invoice id, validAfter/validBefore, nonce ledger |
| Invariant Testing | verification strategy | invariant list, counterexample handling |
| CCTP Simulator | cross-chain settlement | burn/attestation/mint status table |
| x402 Server | API payment gateway | HTTP 402 flow, receipt, idempotency |
최종 설계 문서는 코드 설명서가 아니다. 어떤 위험을 어떤 랩에서 확인했고, 확인하지 못한 부분은 어떤 운영 통제로 보완할지 설명하는 문서다.
흔한 오해와 실패 시나리오
| 오해 | 실제로 확인할 것 |
|---|---|
| 테스트 통과를 학습 완료로 본다. | 실패 테스트와 production gap까지 있어야 capstone 증거로 쓸 수 있다. |
| 랩을 서로 독립된 과제로만 본다. | Mock token의 권한 결정이 permit checkout, ERC-3009 escrow, invariant에 계속 영향을 준다. |
| 학습용 코드를 제품 코드처럼 취급한다. | 직접 구현한 권한, 서명, 토큰 로직은 배포 전에 검증된 라이브러리와 운영 통제로 교체해야 한다. |
| 실패 로그를 지운다. | 실패 로그는 capstone의 risk register와 runbook을 채우는 재료다. |
실습 과제
- 운영실습 산출물 표 작성: 6개 랩 각각에 대해 문제 정의, 실행 명령, 정상 증거, 실패 증거, capstone 연결점을 한 줄씩 적는다.
- 운영실패 로그 형식 고정: revert reason, transaction/input, expected state, actual state, 다음 조치를 포함한 실패 로그 템플릿을 만든다.
- 컨트랙트production gap 표시: 학습용 구현과 production 후보 구현 사이의 차이를 최소 5개 적는다. 서명 검증, role admin, SafeERC20, 이벤트 인덱싱, 운영 pause 절차를 반드시 검토한다.
완료 기준
- 랩 산출물 목록을 작성했다.
- 캡스톤 연결점을 표시했다.
- 실패 로그 형식을 정했다.
근거 자료
- 실습 로드맵: 08-실습/00-실습-로드맵.md