Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ cache/
broadcast/
services/rfq/dist/
services/rfq/node_modules/
deployments/
45 changes: 45 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,51 @@ passing
활성화 조건 결정.
- Non-goals: production legal 활성화, direction-aware element application.

## E2E-001 — Live Anvil E2E & Demo Runner

### Behavior

- `scripts/e2e-anvil.sh`가 fresh Anvil 노드를 띄우고 전체 스택을 배포
(`script/DeployStack.s.sol`)한 뒤 7-scenario demo suite
(`script/DemoScenarios.s.sol`)를 구동하고, scenario별 narrative + evidence +
`PASS`/`FAIL`을 출력한 다음 노드를 teardown한다. 완전히 offline로 동작하고,
하나라도 실패하면 스크립트가 non-zero로 종료한다. `--port`, `--keep` 플래그를
지원한다(`--keep`은 이후 Anvil을 계속 실행해 인터랙티브 demo/UI attach 가능).
- `DeployStack`은 registries(Element/Recipe/TokenPolicy/Operator),
ComplianceEngine, ExecutionRouter+VenueRegistry+VenueSelector,
CornerStoreFactory, 11개 element, 두 recipe(RegD 506(c) id 1, 3(c)(7) id 2) +
surveillance-enabled RegD 변형(id 7), MockPool AMM venue, RFQAdapter venue,
그리고 REAL ERC-3643 token + OnchainID 스택을 live 노드에 배포하고 주소를
`deployments/anvil-e2e.json`(gitignore)로 기록한다. T-REX 배포 코어는
`test/fixtures/TREXCore.sol`로 추출해 test fixture와 script가 공유한다.
- 7 scenario: (1) factory 1-call onboarding(propose→approve+venue), (2) compliant
trade 성공, (3) live element rejection(A-02 flip → `ComplianceRejected`, off-chain
reason-code 재계산 후 복원), (4) manifest lifecycle(suspend 차단 → resume 재거래),
(5) RFQ venue(EIP-712 quote 서명 → `RFQFilled`, 미승인 maker `RFQMakerNotApproved`),
(6) surveillance(threshold 초과 시 `SurveillanceFlag`), (7) bypass 시도(direct
adapter.execute → `NotAuthorized`).
- src/(제품 코드) 변경 없음. `tools/deploy-v3`에 의존하지 않는다(vendor isolation);
AMM venue는 MockPool을 쓰고, 실제 Uniswap v3 pool 배포는 별도 follow-up으로 남는다.

### Verification

- `scripts/e2e-anvil.sh`(fresh + repeat) 2회 실행, 각 7/7 PASS + exit 0.
- `scripts/e2e-anvil.sh --keep` 실행 후 Anvil이 계속 살아 있음을 확인.
- `forge test --offline`(238/238 유지; TREXSuite→TREXCore 추출 후에도 green).
- `forge fmt --check`.

### State

passing

### Notes

- runbook: `docs/demo.md`(실행법, scenario 순서, reason-code 재계산, mock/real 구분).
- 관련 결정: D008/D009(illustrative element library, manifest lifecycle). 실제
Uniswap v3 pool 배포와 production data source 연결은 out-of-scope.
- Non-goals: 실 Uniswap v3 pool, production governance key management,
direction-aware element application.

## CMP-002 — Manifest Lifecycle & Operator Approval Flow

### Behavior
Expand Down
63 changes: 37 additions & 26 deletions PROGRESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ source of truth로 사용한다.
- RFQ integration: RFQ 벤처를 protected router path(`ExecutionRouter → ComplianceEngine
→ RFQAdapter`)로 real ERC-3643 스택 위에서 end-to-end 커버(`test/integration/RFQFlow.t.sol`,
fill/maker-unapproved/cancel/non-compliant/direct-call bypass 5 시나리오) — RFQ-002 deferred follow-up 완료.
- `E2E-001 — Live Anvil E2E & Demo Runner`(`scripts/e2e-anvil.sh` +
`script/DeployStack.s.sol` + `script/DemoScenarios.s.sol`): fresh Anvil에 전체 스택
배포 후 7-scenario demo suite 구동, scenario별 PASS/FAIL. T-REX 배포 코어를
`test/fixtures/TREXCore.sol`로 추출해 fixture/script 공유. src/ 변경 없음. runbook은
`docs/demo.md`.

## Blocked

Expand All @@ -49,42 +54,48 @@ source of truth로 사용한다.

1. acquisition/lot data source와 holding-period Recipe 활성화 조건을 결정한다
(C-01 Lockup은 현재 fixture-only mock acquisition source).
2. live Anvil deployment/E2E를 추가한다.
2. 실제 Uniswap v3 pool 배포를 demo/E2E에 연결한다(현재 AMM venue는 MockPool;
`tools/deploy-v3` vendor isolation 유지).
3. Order Book은 matching/custody/surveillance 모델 결정 후 구현한다.
4. CI hardening(static analysis 등)을 강화한다.

## Last Session Summary

- CMP-002 (Manifest Lifecycle & Operator Approval Flow)을 landing했다. Task 1
(registry state machine)에 이어 Task 2에서 engine fail-open을 닫고 factory/seam
finalization, 통합 시나리오, bookkeeping을 완료했다.
- `E2E-001` (Live Anvil E2E & Demo Runner)을 landing했다. src/ 변경 없이 forge
script 두 개 + 셸 러너 + T-REX 배포 코어 추출로 live-Anvil E2E/demo를 구현했다.
- 변경한 파일:
- product: `src/compliance/ComplianceEngine.sol`(evaluate positive-allowlist
default-deny + commit 주석), `src/registry/TokenPolicyRegistry.sol` +
`src/interfaces/compliance/ITokenPolicyRegistry.sol`(clearUnregulated),
`src/factory/CornerStoreFactory.sol`(register→approve natspec)
- test: `test/unit/compliance/Engine.t.sol`(신규 4 default-deny),
`test/unit/registry/TokenPolicyRegistry.t.sol`(신규 8 clearUnregulated+auth),
`test/integration/EmergencyPause.t.sol`(신규 3 router E2E),
`test/integration/IntegrationBase.sol`/`Surveillance.t.sol`(seam 정리)
- bookkeeping: `DECISIONS.md`(D009), `FEATURES.md`(CMP-002), `PROGRESS.md`
- Task 1(앞선 커밋): `src/types/ComplianceTypes.sol`(enum append),
`src/libraries/Errors.sol`(InvalidManifestTransition), registry state machine
- TDD: engine 4개 default-deny 테스트가 먼저 RED로 오늘의 fail-open(PROPOSED/
RETIRED × UNREGULATED/ACTIVE가 allowed=true)을 증명한 뒤 positive-allowlist로
GREEN 전환.
- script: `script/DeployStack.s.sol`(전체 스택 live 배포 + JSON artifact),
`script/DemoScenarios.s.sol`(7-scenario 러너), `script/DemoConstants.sol`(공유
상수)
- runner: `scripts/e2e-anvil.sh`(anvil 기동/배포/scenario/teardown, `--port`/
`--keep`, offline)
- fixture refactor: `test/fixtures/TREXCore.sol`(신규, `is CommonBase`,
admin-parameterized, prank-free) + `test/fixtures/TREXSuite.sol`(thin facade
`is Test, TREXCore`) — test suite green 유지
- config: `foundry.toml`(fs_permissions read-write, JSON artifact),
`.gitignore`(`deployments/`)
- docs: `docs/demo.md`(runbook), `docs/testing.md`(E2E 섹션), `docs/README.md`
- bookkeeping: `FEATURES.md`(E2E-001), `PROGRESS.md`
- 설계 요점:
- broadcast(pk)로 persist해야 하는 상태 전이/거래를, prank(addr)+try/catch로
revert 기대 시나리오(compliance/policy/authz 거부)를 구동. reason code는
off-chain 재계산 후 revert data와 비교.
- onboarding은 scenario 1에서 factory가 수행하도록 deploy 시 manifest를 UNKNOWN로
남기고 policyReg/venueReg 소유권을 factory로 이전, deployer는 policyReg operator로
남겨 lifecycle(suspend/resume/retire) 구동 가능하게 함.
- anvil genesis timestamp가 실제 wall-clock이라 C-01 Rule 144 lockup(t=1 seed)이
on-chain에서 자연 통과 → vm.warp 불필요.
- 실행한 명령:
- `forge fmt`
- `forge fmt` / `forge fmt --check`
- `forge test --offline`
- `scripts/e2e-anvil.sh`(fresh + repeat, `--keep`)
- 통과한 검증:
- `forge test --offline` 227/227(pre-task 212 + 신규 15).
- engine default-deny(양방향 ordering 포함), registry clearUnregulated +
onlyOwner-vs-onlyOperator auth, 통합 PROPOSED/RETIRED reject + suspend→resume
재거래.
- `forge test --offline` 238/238(TREXCore 추출 후에도 green).
- `scripts/e2e-anvil.sh` 2회 실행 모두 7/7 PASS, exit 0. `--keep`로 anvil 잔존 확인.
- 남은 리스크:
- ungated legacy mock element(A-01/A-03/QP)와 새 operator-gated element 사이
hardening divergence — follow-up으로 정렬(CMP-001 deferred).
- C-01 Lockup은 fixture-only mock acquisition source에 의존; production
- AMM venue는 MockPool(1:1); 실제 Uniswap v3 pool 배포는 별도 follow-up(vendor
isolation). demo는 `tools/deploy-v3`에 의존하지 않는다.
- C-01 Lockup은 fixture/demo mock acquisition source에 의존; production
acquisition/lot data source와 holding-period 활성화 default는 미결정.
- production data source(OFAC/ONCHAINID/ERC-165/EDGAR) 연결과 legal 활성화는
approval-gated로 열려 있다.
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
| [`architecture/README.md`](./architecture/README.md) | 책임 레이어와 경계 인덱스 | Current |
| [`ROADMAP.md`](./ROADMAP.md) | 구현 순서, 완료 조건, blocker | Current |
| [`testing.md`](./testing.md) | 테스트와 완료 기준 | Current |
| [`demo.md`](./demo.md) | live Anvil E2E / demo runbook | Current |
| [`security.md`](./security.md) | 보안 규칙 | Current |
| [`rfq-threat-model.md`](./rfq-threat-model.md) | RFQ venue 위협 모델 | Current |
| [`MVP.md`](./MVP.md) | 초기 AMM 중심 설계 기록 | Superseded |
Expand Down
1 change: 1 addition & 0 deletions docs/compliance/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
| ⑥ | [Phase 1~2 실행 플랜](./06-phase-1-2-plan.md) | *그래서 지금 무엇을* 결정·구현하나? 데모 6 장면이 완성 기준 | 15분 | **전원** ⭐ |
| ⑦ | [BUIDL 구현 시나리오](./07-buidl-implementation.md) | 첫 시연 자산 BUIDL을 올리려면 *구체적으로 무엇을* 만드나? — 신상카드·신규 구현 5개·거래 walkthrough | 20분 | 개발팀 + 관심 있는 분 |
| ⑧ | [리걸 파트 리서치·구현 플랜](./08-legal-research-plan.md) | 검사 부품 27개를 법적으로 *어떻게 완성해서 코드로 넘기나* — 부품별 현황·리서치 큐·변환 패턴 3종 | 15분 | 리걸 협업자 + 개발팀 인수인계 담당 |
| ⑨ | [Element Data-Source Matrix](./element-data-source-matrix.md) | 구현된 부품 11개의 mock이 production에서 *어떤 데이터 소스로 무엇을 통해* 교체되나 — seam 위치·법무 확정 질문 포함 | 10분 | **개발팀 + 리걸** ⭐ |
| 부속 | [개발팀 수정요청서](./appendix-change-request.md) | 우리 쪽이 요청하는 구체 변경 목록 (결정 권한은 개발팀) | — | 개발팀만 |

## 시간이 없다면 — 15분 코스
Expand Down
55 changes: 55 additions & 0 deletions docs/compliance/element-data-source-matrix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Element Data-Source Matrix (기술측)

각 compliance Element의 **현재(illustrative) 구현 → production 데이터 소스 → 연동 방식 → 코드상 seam → 결정 상태**를 한 곳에 모은 변환표다. ADR-004가 Phase 1 착수 조건으로 요구하는 **Legal-to-Technical Matrix**(법 → 증거 → 집행)의 *기술측 절반*을 채우며, 각 행의 "법무 확정 질문"이 법률측 절반의 입력이 된다.

> **원칙 (ROADMAP/MVP-v2, D008).** 모든 Element의 데이터 실질은 법률 검토 승인 전까지
> operator-settable attestation mock으로 유지한다. 이 표의 "production 소스" 열은
> 승인 후 연결할 대상의 후보이지, 승인된 정책이 아니다.

> **출처 주의.** Element별 데이터 소스의 1차 도출은 전략 보고서(노트 14,
> `docs/reference/14-decipher-rwa-dex-overview.md`) §3.2인데, 이 파일은 현재
> **main에 없다**(`layer1-layer2-mvp-for-dex` 브랜치에만 존재). main 편입 여부가
> 미결이므로, 이 표가 main에서 참조 가능한 유일한 요약본이다.

## 구현된 Element (11)

| ID | 현재 mock 구현 (seam 위치) | Production 데이터 소스 | 연동 방식 | 상태 / 법무 확정 질문 |
| --- | --- | --- | --- | --- |
| **A-01 Sanctions** | operator가 `setBlocked`로 켜는 bool — `src/compliance/elements/Sanctions.sol` | OFAC SDN 리스트 (Chainalysis/TRM 류 온체인 oracle) | oracle 컨트랙트 조회로 `check` 내부 교체, 또는 oracle→attestation 갱신 봇 | 승인 게이트. Q: 리스트 갱신 SLA(거래 시점 최신성 요구 수준), 2차 제재(secondary sanctions) 포함 범위 |
| **A-02 Jurisdiction** | `jurisdictionOf` + `allowedJurisdiction` operator 매핑 — `Jurisdiction.sol` | ONCHAINID 관할권 claim (trusted issuer 발급) | claim topic 등록 + `check`가 claim 존재·유효성 조회 | 승인 게이트. Q: Reg S category 기준의 국가 분류표, allowed-set 변경 거버넌스(누가·어떤 절차로) |
| **A-03 Accredited Investor** | 단일 bool `setAccredited` — `AccreditedInvestor.sol` | ONCHAINID `ACCREDITED_INVESTOR_TOPIC` + `SELF_CERT_TOPIC` claims | **element 세분화 선행**: 노트 14 §3.1의 4-원자(적격 claim / 최소투자금액 / 자기인증 / 제3자 자금조달 부재)로 분해 후 claim별 연동 | 승인 게이트 + **구현 분해 필요**. Q: 506(c) 합리적 검증 방법(소득/순자산 증빙 기준, 2025-03 SEC No-Action Letter 반영 범위), claim 유효기간/갱신 주기 |
| **A-04 Identity Uniqueness** | operator `bindIdentity` 1:1 바인딩 (불변식은 setter가 강제) — `IdentityUniqueness.sol` | ONCHAINID IdentityRegistry (T-REX와 공유) | ERC-3643 IdentityRegistry 조회로 교체 (지갑↔identity 매핑은 이미 그쪽이 원본) | 승인 게이트. Q: 1인 다지갑 허용 정책(허용 시 한도 합산 기준), identity 회수·재발급 절차 |
| **A-05 US Tax Resident** | `setUsTaxResident` 플래그, **미플래그=통과(fail-open, 주석으로 명시)** — `UsTaxResident.sol` | 적극적 비거주 attestation (IRS Substantial Presence Test 기반) | 부재=거부(fail-closed)로 뒤집고 positive claim 요구 | 승인 게이트 + **시맨틱 반전 필요**. Q: 증빙 형식(W-8BEN 상당?), 판정 주체와 갱신 주기 |
| **A-13 Qualified Purchaser** | bool `setQualifiedPurchaser` — `QualifiedPurchaser.sol` | ONCHAINID claim | claim 존재·issuer·만료 검증 ("Pattern B") | 승인 게이트. **법률 심층 문서 존재**: `docs/compliance/elements/A-13_qualified-purchaser.md` (11개 중 유일한 walkthrough — 나머지 element의 표준 포맷) |
| **B-01 Asset Classification** | `setClassification(asset, tag)` + 생성자 `requiredClassification` — `AssetClassification.sol` | 발행인 선언 (Listing Agreement) + operator 승인 | Manifest 등록 시 분류를 함께 심사·기록하는 운영 절차와 결합 | 승인 게이트. Q: 분류 선언의 책임 주체(발행인 vs operator), 오분류 발견 시 정정·소급 절차 |
| **B-02 ERC-3643 Native** | `setErc3643Native` attestation (**의도적 stand-in**, natspec에 seam 명시) — `Erc3643Native.sol` | ERC-165 `supportsInterface`(T-REX `IToken`) 또는 token registry 조회 | `check` 내부를 introspection으로 교체 — **결정론적, 법무 불필요** | **기술 결정만 남음** (vendored T-REX의 ERC-165 지원 여부 검증 필요, D008) |
| **C-01 Rule 144 Lockup** | 주입식 `IAcquisitionSource` mock — `Lockup.sol` (test fixture에서만 활성, "CR-3" seam) | 취득 시점/lot 데이터 소스 — **미결정** (ROADMAP Decision Backlog 1순위) | acquisition registry 신설 또는 transfer-agent 피드 | **데이터 소스 자체가 open decision** — 결정 전 holding-period Recipe production 비활성이 문서화된 default. Q: lot 회계 방식(FIFO?), 데이터 원천(transfer agent? 체인 이벤트 재구성?), 6개월/1년 기간 기산점 |
| **E-01 Form D Filing** | `setFormDFiled(asset, filed, ref)` + 참조 해시 — `FormDFiling.sol` | EDGAR oracle 또는 hash-anchored Listing Agreement | 제출 확인 봇이 attestation 갱신 + `filingRef`에 accession number 해시 | 승인 게이트. Q: 최초 판매 후 15일 제출 시한의 온체인 반영(유예 처리), amendment 추적 범위 |
| **F-02 Market Conduct (Surveillance)** | 거래 카운터 임계 초과 시 flag 이벤트 (STATEFUL, 차단 안 함) — `SurveillanceFlag.sol` | Phase 3 operator 시장감시 규칙 | 감시 패턴은 off-chain 분석 + on-chain flag hook 유지 | **Phase 3 범위** (Layer 4). Q: 감시 패턴 정의와 broker-dealer 규제 연구 결과 대기 (Element catalog freeze 노트 참조) |

## 백로그 Element (미구현 — pool freeze v1 기준)

| ID | 내용 | 데이터 소스 후보 | 상태 |
| --- | --- | --- | --- |
| C-02 Swap Cooldown | 스왑 간 최소 간격 | on-chain state (자체 기록) | Phase 1·2 optional |
| C-03 Max Balance per Holder | 보유 한도 | on-chain state + manifest 파라미터 | Phase 1·2 optional |
| E-02 Issuer Standing | 발행인 자격 유지 | issuer attestation | Phase 1·2 optional |
| D-03 Listing Differential Disclosure | 상장 차등 공시 | operator/issuer 공시 채널 | Phase 3 |
| F-01 Operator Affiliate Restriction | 운영자 특수관계인 제한 | operator 신고 | Phase 3 |

41개 확장 카탈로그(법률 리서치 제안)는 backlog 입력이며, market-conduct/broker-dealer
연구 완료 전 개별 Element의 법적 정확성·데이터 소스는 검토되지 않은 것으로 본다
(`docs/compliance/04-element-interface.md` 배너, MVP-v2 §5·§8).

## 다음 단계

1. **법무측 절반**: 이 표의 "법무 확정 질문" 열을 입력으로 Legal-to-Technical Matrix의
법률 검증(ADR-004 요구 산출물)을 완성한다. Element당 심층 포맷은 A-13 walkthrough를
표준으로 한다.
2. **기술 선행 작업** (법무 무관하게 진행 가능): B-02 introspection 전환 검증,
A-03 4-원자 element 분해 설계, A-05 fail-closed 반전 설계.
3. **결정 대기**: C-01 acquisition 데이터 소스 (ROADMAP Decision Backlog).

관련 문서: D008/D009(`DECISIONS.md`), `docs/demo.md`(mock vs real 경계),
`docs/compliance/04-element-interface.md`(인터페이스·택소노미),
`docs/compliance/elements/A-13_qualified-purchaser.md`(walkthrough 표준).
Loading
Loading