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
29 changes: 29 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ Execution Integration Kit로 구성한다. Corner Store reference DEX는 이 공
- compliance evaluation은 venue 실행과 분리한다.
- execution routing은 법률 규칙이나 matching 로직을 직접 소유하지 않는다.
- venue adapter는 정책을 정의하지 않는다.
- Corner Store의 DEX-level compliance 보장은 `ExecutionRouter`가 실행한
router-mediated trade에 한정한다.
- ERC-3643 직접 전송, 직접 pool/venue 호출, wrapper/vault/custodian을 통한 경제적
소유권 이전은 자동으로 Corner Store 4-Layer evaluation과 `commit()`을 거치지
않는다.
- Router 밖 경로는 발행자 token-level enforcement에 위임하거나, controlled
venue/settlement로 제한하거나, 명시적으로 제품 범위 밖으로 선언해야 한다.
- 무거운 자료와 재량 판단은 오프체인, 검증·게이팅·집행은 온체인에 둔다.
- `tools/deploy-v3`는 Corner Store 제품 코드와 분리된 vendored 인프라다.

Expand All @@ -60,6 +67,28 @@ Execution Integration Kit로 구성한다. Corner Store reference DEX는 이 공
SDK와 reference DEX의 전체 실행 흐름은 제품 명세에, 세부 책임과 불변성은
`docs/architecture/`에 둔다.

보호되는 execution 경로:

```text
ExecutionRouter
→ ComplianceEngine.evaluate()
→ Adapter
→ Venue/Pool/RFQ
→ ComplianceEngine.commit()
```

보호되지 않는 경로 예시는 다음과 같다.

- ERC-3643 token 직접 `transfer` / `transferFrom`
- 사용자의 직접 AMM pool 또는 외부 venue 호출
- Router를 통하지 않는 RFQ/Order Book settlement
- wrapper, vault, custodian, omnibus account 또는 offchain ledger를 통한 RWA
economic exposure 이전

이 경계는 제품 보증 문구에도 반영해야 한다. Corner Store는 모든 가능한 RWA 이동을
전역적으로 통제한다고 주장하지 않고, router-mediated trade에 대해 DEX-level
compliance를 강제한다고 설명한다.

## External Dependencies

- Foundry / forge-std
Expand Down
59 changes: 59 additions & 0 deletions DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,62 @@ pair 거래에서는 `tokenIn`과 `tokenOut`을 각각 분류한다. 양쪽 모
- `docs/MVP-v2-multi-venue.md`
- `docs/architecture/asset-manifest.md`
- `docs/security.md`

## D006 — Corner Store compliance 보장은 Router 경로에 한정한다

Date: 2026-06-21

### Context

PR #12 이후 Corner Store 내부 실행 경로는 다음 경계를 갖는다.

- regulated-regulated pair에서 양쪽 ACTIVE Manifest를 모두 평가한다.
- 누락된 Recipe reference는 fail-closed한다.
- AMM Adapter 실행은 Router-only다.
- Router caller는 `context.initiator`와 일치해야 한다.

그러나 이런 보강은 Corner Store 경로를 거치는 거래에만 적용된다. 사용자가
ERC-3643 token을 직접 전송하거나, AMM pool/RFQ settlement/wrapper/custodian을
직접 사용하면 `ExecutionRouter`, `ComplianceEngine.evaluate()`와
`ComplianceEngine.commit()`을 우회할 수 있다.

### Decision

현재 skeleton의 보안·제품 보장은 제한된 범위 모델로 정의한다.

Corner Store는 router-mediated trade에 대해 DEX-level compliance를 강제한다.
Router 밖의 RWA 이동 또는 경제적 소유권 이전은 자동으로 Corner Store 4-Layer
evaluation과 stateful `commit()`을 거치지 않는다.

Router 밖 경로는 production deployment에서 다음 중 하나로 처리해야 한다.

- ERC-3643 token/compliance module이 핵심 제한을 직접 강제한다.
- end user가 직접 호출할 수 없는 controlled venue/settlement로 제한한다.
- 제품 문서와 사용자-facing 설명에서 명시적으로 out-of-scope로 선언한다.

### Alternatives Considered

- Router-exclusive model을 즉시 확정: 임의의 third-party pool과 직접 호출 가능한
venue를 기술적으로 차단하는 방식이 아직 설계되지 않아 제외한다.
- Token-level enforcement model을 즉시 확정: ERC-3643 issuer module이 Corner
Store의 모든 Recipe, cap, venue와 surveillance 요구를 대체한다는 외부 운영
계약이 없어 제외한다.
- 모든 non-router path를 암묵적으로 안전하다고 취급: Corner Store 검사가 생략될
수 있어 제외한다.

### Consequences

- `docs/security.md`와 `ARCHITECTURE.md`는 protected path와 non-protected path를
명시해야 한다.
- RFQ/Order Book settlement와 future Adapter는 Router-only authorization 또는
동등한 호출자 제한을 merge 조건으로 가져야 한다.
- 직접 ERC-3643 transfer, 직접 venue call, wrapper/vault/custodian과 offchain
beneficial ownership transfer는 별도 제한·위임·out-of-scope 결정 전까지 Corner
Store 보장으로 표현하지 않는다.
- Stateful surveillance는 Router 경로에서만 완전성을 주장할 수 있다.

### Related Files

- `docs/security.md`
- `ARCHITECTURE.md`
- `docs/architecture/execution-routing.md`
9 changes: 9 additions & 0 deletions docs/architecture/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ ERC-3643 Token & Identity는 이 네 layer 중 하나가 아니라 그 아래에
- Manifest와 `UNREGULATED` 분류가 모두 없는 자산은 `UNKNOWN`으로 fail-closed한다.
- `ACTIVE` Manifest의 누락·불완전 reference는 fail-closed다.
- settlement 직전 최신 Manifest, actor와 operator 상태를 평가한다.
- Corner Store의 4-Layer compliance 보장은 `ExecutionRouter`를 통한
router-mediated trade에 한정한다.
- ERC-3643 직접 전송, 직접 pool/venue 호출, wrapper/vault/custodian 이전과
offchain beneficial ownership 이전은 별도 제한·위임·out-of-scope 결정 없이는
Corner Store 보장으로 표현하지 않는다.
- non-custodial Router와 Adapter에는 의도하지 않은 자산 잔액이 남지 않는다.
- 무거운 자료와 재량 판단은 오프체인에 두고 승인된 결과만 온체인에 입력한다.

Expand All @@ -80,6 +85,10 @@ SDK 공통 컴포넌트는 특정 venue나 Corner Store 배포 구성에 의존
구체 Adapter는 reference 구현이며, 제3의 DEX는 같은 interface를 구현해 자체
venue를 등록할 수 있다.

현재 skeleton의 보안 보장은 limited-scope model이다. Router를 거치지 않는 RWA
이동 또는 경제적 노출 이전은 발행자 token-level enforcement, controlled
venue/settlement 또는 명시적 out-of-scope 선언으로 별도 처리해야 한다.

외부 협업 범위:

- production 법률 기준과 Element 승인
Expand Down
16 changes: 12 additions & 4 deletions docs/architecture/execution-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,15 @@ Uniswap v3, RFQ와 Order Book의 구체 Adapter 및 Corner Store 배포 configur

- Router는 Registry에 등록된 adapter와 venue만 신뢰한다.
- Adapter 구현체 교체와 중단은 권한이 분리된 관리 작업이다.
- Adapter와 settlement contract는 Router-only authorization 또는 동등한
호출자 제한을 가져야 한다.
- decision 자체가 유효해도 요청 parameter가 decision과 다르면 실행하지 않는다.
- Router를 지원 진입점으로 둔다고 표준 pool 직접 호출이 기술적으로 차단되는 것은
아니다.
- Corner Store 4-Layer compliance 보장은 Router 지원 경로에 한정한다. 직접 pool
호출은 Corner Store 지원 실행으로 간주하지 않는다.
- Router를 지원 진입점으로 둔다고 ERC-3643 직접 전송, 표준 pool 직접 호출,
wrapper/vault/custodian 이전 또는 offchain beneficial ownership 이전이
기술적으로 차단되는 것은 아니다.
- Corner Store 4-Layer compliance 보장은 Router 지원 경로에 한정한다. 직접 token
transfer, 직접 pool/venue 호출과 non-router settlement는 Corner Store 지원
실행으로 간주하지 않는다.

## Invariants

Expand All @@ -61,6 +65,7 @@ Uniswap v3, RFQ와 Order Book의 구체 Adapter 및 Corner Store 배포 configur
multi-Recipe 평가 결과를 얻은 뒤 Adapter를 호출한다.
- Adapter에 전달하는 decision은 actor, token, amount, venue, version, expiry와
execution nonce에 바인딩한다.
- 실행 caller는 `context.initiator`와 일치해야 한다.
- nonce 재사용과 deadline 초과 요청을 거부한다.
- Router는 matching 로직과 법률 규칙을 포함하지 않는다.
- Router에 의도하지 않은 사용자 자산 잔액이 남지 않는다.
Expand All @@ -87,13 +92,16 @@ Uniswap v3, RFQ와 Order Book의 구체 Adapter 및 Corner Store 배포 configur
- 표준 pool 직접 호출에는 ERC-3643 자체 transfer enforcement만 적용될 수 있다.
비우회 4-Layer enforcement가 필요한 production RWA venue는 별도 enforcement와
외부 승인이 확정되기 전 활성화하지 않는다.
- RFQ와 Order Book settlement는 Router-only authorization 또는 동등한 권한 모델이
확정되기 전 production-supported venue로 취급하지 않는다.

## Open Decisions

- exact venue 지정과 deterministic selector의 최종 API
- 외부 preview API의 응답 형식
- nonce scope와 batch execution
- adapter upgrade/replace governance
- Router-exclusive, token-level enforcement, limited-scope 중 production 보장 모델
- 일반 ERC-20 public venue fast path의 허용 venue와 관측 이벤트 범위
- 자산 classification onboarding과 integrator API

Expand Down
5 changes: 5 additions & 0 deletions docs/architecture/token-and-identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Corner Store의 Manifest, `ComplianceDecision` 또는 venue를 생성·선택하
원자적으로 실패해야 한다.
- ERC-3643 검사를 통과했다고 해서 venue, 거래 규모, 상대방, 운영자 조건이
자동으로 허용되는 것은 아니다.
- ERC-3643 직접 전송은 Corner Store `ExecutionRouter`, 4-Layer evaluation과
stateful `commit()`을 자동으로 실행하지 않는다. 직접 전송 경로의 제한은 발행자
token-level policy에 위임되거나 제품 범위 밖으로 명시되어야 한다.
- RWA-RWA pair는 양쪽 토큰의 identity/compliance 조건을 각각 만족해야 한다.
- 규제 토큰을 delist해도 일반 ERC-20 경로로 자동 전환하지 않는다.

Expand All @@ -72,6 +75,8 @@ Corner Store의 Manifest, `ComplianceDecision` 또는 venue를 생성·선택하
- ERC-3643의 identity와 발행자 compliance 모듈을 재사용한다.
- Corner Store는 발행 측 coverage를 중복하지 않는 execution-level compliance를
추가한다.
- Corner Store는 router-mediated trade에 대한 DEX-level compliance layer이며,
모든 ERC-3643 token movement의 전역 enforcement layer로 표현하지 않는다.
- AMM Pool처럼 자산을 보유하는 주소는 venue identity 등록 대상으로 본다.
- Adapter가 토큰을 보관하지 않는 구조를 우선한다.

Expand Down
91 changes: 91 additions & 0 deletions docs/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,64 @@
- ERC-3643 / ONCHAINID의 identity와 token transfer enforcement는 외부 발행자
시스템의 책임이다.
- Corner Store는 외부 판정을 임의로 완화하거나 우회하지 않는다.
- Corner Store의 DEX-level compliance 보장은 `ExecutionRouter`를 통한 실행
경로에 한정한다. Router 밖에서 발생하는 ERC-3643 직접 전송, 직접 venue 호출,
wrapper/vault/custodian을 통한 경제적 소유권 이전은 별도 제한, token-level
enforcement 위임 또는 명시적 out-of-scope 처리가 필요하다.
- `tools/deploy-v3`는 vendored Uniswap v3 인프라이며 제품 compliance 보장을
제공하지 않는다.

세부 제품 경계는 `docs/architecture/`를 기준으로 한다.

## Compliance Enforcement Boundary

지원되는 enforcement 경로:

```text
ExecutionRouter
→ ComplianceEngine.evaluate()
→ Adapter
→ Venue/Pool/RFQ
→ ComplianceEngine.commit()
```

이 경로에서는 Router가 최신 Manifest와 applicable Recipe를 평가하고, 허용된
venue/adapter에만 실행을 위임하며, 성공 후 stateful compliance `commit()`을
호출한다.

지원 경로 밖에서는 Corner Store의 4-Layer compliance가 자동으로 실행되지 않는다.
특히 다음 경로는 production-ready 보장으로 간주하지 않는다.

- ERC-3643 token의 직접 `transfer` / `transferFrom`
- 사용자가 AMM pool 또는 외부 venue를 직접 호출하는 swap
- Router를 거치지 않는 RFQ 또는 Order Book settlement
- wrapper, vault, custodian 또는 omnibus account를 통한 경제적 소유권 이전
- offchain ledger에서의 beneficial ownership 이전

이런 경로가 열려 있으면 다음 Corner Store 검사가 생략될 수 있다.

- investor qualification Recipe
- amount cap과 offering/fund cap
- venue allowlist와 operator pause
- nonce/replay control
- `ComplianceEngine.commit()` 기반 surveillance/stateful Element update
- future lockup, affiliate, jurisdiction-specific rule

현재 skeleton의 기본 보안 모델은 제한된 범위 모델이다.

> Corner Store는 router-mediated trade에 대해 DEX-level compliance를 강제한다.
> Router 밖의 RWA 이동 또는 경제적 노출 이전은 발행자 token-level enforcement에
> 위임되거나, 별도 controlled venue로 제한되거나, 제품 범위 밖으로 명시되어야 한다.

더 강한 production 보장이 필요하면 다음 중 하나를 별도 설계 결정으로 확정해야 한다.

- Router-exclusive model: end user가 직접 호출할 수 없는 controlled venue/settlement만
지원한다.
- Token-level enforcement model: 핵심 제한을 ERC-3643 compliance module이 Router
밖에서도 강제한다.
- Limited-scope model: Corner Store 보장을 router-mediated trade로 한정하고,
non-router path는 문서와 제품 설명에서 out-of-scope로 명시한다.

## Secrets

- private key, RPC credential과 API token을 코드나 문서에 커밋하지 않는다.
Expand All @@ -27,6 +80,7 @@
## Input Validation

- 외부 주소, amount, deadline, nonce, manifest version과 venue context를 검증한다.
- Router 실행 요청의 caller는 `context.initiator`와 일치해야 한다.
- 명시적 `UNREGULATED` public path와 `ACTIVE` Manifest regulated path를 명시적으로
구분한다.
- `ACTIVE` Manifest의 invalid Recipe/reference, unsupported engine와 version
Expand All @@ -39,9 +93,30 @@
## Asset Safety

- Router와 Adapter는 의도하지 않은 자산을 보관하지 않는 구조를 우선한다.
- Adapter와 settlement contract는 Router-only authorization 또는 동등한 호출자
제한을 가져야 한다.
- ERC-20 상호작용은 return value를 직접 가정하지 않고 `SafeERC20` 또는 동등한
safe wrapper를 사용한다.
- 실패한 실행은 nonce, fill accounting과 token balance를 원자적으로 되돌려야 한다.
- ERC-3643 transfer 실패를 성공으로 취급하거나 swallow하지 않는다.

## Venue Integration Security

- Uniswap-style callback은 등록되었거나 계산으로 검증한 pool에서만 수락한다.
callback `data`가 payer/token을 포함하더라도 callback origin 검증 없이 신뢰하지
않는다.
- Pool/venue 등록은 compliance 보장의 일부다. 잘못된 venue 또는 악성 adapter가
등록되면 Router를 타더라도 settlement 결과가 왜곡될 수 있으므로 governance와
preflight 검증 대상이다.
- RFQ와 Order Book signature flow는 구현 전에 chain id, verifying contract,
maker/taker, token pair, venue, policy/manifest version, nonce와 expiry를
binding해야 한다.
- Slippage, deadline과 amount cap은 서로 다른 축이다. `amountIn`, RWA 수량,
quote notional과 investor/fund/offering cap의 기준을 혼동하지 않는다.
- External call, callback, token transfer가 포함된 경로는 access control,
reentrancy, unchecked return, signature replay와 business-logic bypass를 함께
검토한다.

## Logging

- 민감한 identity 자료와 법률 문서를 온체인 event나 일반 로그에 기록하지 않는다.
Expand Down Expand Up @@ -75,3 +150,19 @@ scripts/check.sh
- Manifest lifecycle과 cumulative multi-Recipe test
- `UNKNOWN`, explicit `UNREGULATED`와 regulated path 구분 test
- unregulated-regulated와 regulated-regulated pair의 양쪽 Manifest 적용 test
- 모든 Adapter/RFQ/OrderBook settlement의 direct caller rejection test
- ERC-20 safe transfer behavior와 callback-origin validation test
- signed order/decision 도입 시 chain/domain/nonce/expiry replay test

## Reference Security Inputs

- ERC-3643 official documentation: permissioned tokens provide identity-backed
transfer checks, but Corner Store-specific venue, Recipe, amount cap와
surveillance 보장을 자동으로 대체하지 않는다.
- OpenZeppelin `SafeERC20`: ERC-20 operation failure, false return과 no-return
token 처리를 위해 safe wrapper를 사용한다.
- Uniswap v3 integration references: pool/callback origin 검증과 audited periphery
pattern을 직접 venue adapter 설계의 기준으로 삼는다.
- OWASP Smart Contract Security Top 10 / SCSVS: access control, input validation,
unchecked external calls, reentrancy, signature replay와 business-logic risk를
review checklist에 포함한다.
5 changes: 4 additions & 1 deletion src/execution/adapters/amm/UniswapV3Adapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity 0.8.17;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Governed} from "../../../auth/Governed.sol";
import {IAMMAdapter} from "../../../interfaces/execution/adapters/IAMMAdapter.sol";
import {IPool} from "../../../interfaces/execution/adapters/IPool.sol";
Expand All @@ -22,6 +23,8 @@ import {Errors} from "../../../libraries/Errors.sol";
/// - The callback `data` ABI-encodes `(address payer, address tokenIn)` where `payer` is the
/// buyer who has approved this adapter to spend `tokenIn`.
contract UniswapV3Adapter is IAMMAdapter, Governed {
using SafeERC20 for IERC20;

mapping(address => bool) public registeredPool;
address public router;

Expand Down Expand Up @@ -86,7 +89,7 @@ contract UniswapV3Adapter is IAMMAdapter, Governed {
// The owed amount is the positive delta (pool is owed tokenIn).
uint256 amountOwed = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);

IERC20(tokenIn).transferFrom(payer, msg.sender, amountOwed);
IERC20(tokenIn).safeTransferFrom(payer, msg.sender, amountOwed);
}

function _decodeVenueData(bytes calldata venueData)
Expand Down
24 changes: 22 additions & 2 deletions src/execution/adapters/orderbook/OrderBookAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,33 @@ pragma solidity 0.8.17;
import {IOrderBookAdapter} from "../../../interfaces/execution/adapters/IOrderBookAdapter.sol";
import {ExecutionRequest, ExecutionResult} from "../../../types/ExecutionTypes.sol";
import {ComplianceDecision} from "../../../types/ComplianceTypes.sol";
import {Errors} from "../../../libraries/Errors.sol";
import {Governed} from "../../../auth/Governed.sol";

/// @title OrderBookAdapter
/// @notice Stub. Order-book execution is not implemented in the skeleton.
contract OrderBookAdapter is IOrderBookAdapter {
/// @dev Even as a stub, order-book settlement keeps the production security
/// invariant: fills may only be entered through the router, never directly
/// by maker/taker.
contract OrderBookAdapter is IOrderBookAdapter, Governed {
address public router;

event RouterSet(address indexed router);

modifier onlyRouter() {
if (msg.sender != router) revert Errors.NotAuthorized();
_;
}

function setRouter(address router_) external onlyOwner {
router = router_;
emit RouterSet(router_);
}

function execute(ExecutionRequest calldata, ComplianceDecision calldata)
external
pure
view
onlyRouter
returns (ExecutionResult memory)
{
revert("OrderBook: not implemented");
Expand Down
Loading
Loading