RWA 토큰화 플랫폼
RTX는 ERC-1155 멀티토큰 표준 기반의 RWA(Real World Asset) 토큰화 플랫폼으로,
실물 자산의 발행·결합·거래·사용까지 전 라이프사이클을 온체인에서 관리합니다.
이종 가맹점 쿠폰의 상호 합의형 결합, 에스크로 기반 사용 처리,
그리고 P2P 거래소를 통한 2차 시장 유통을 지원합니다.
1. 발명의 개요
발명 1. 블록체인 기반 이종 가맹점 쿠폰의 결합과 사용 처리 시스템
발명 2. 블록체인 기반 RWA 토큰화 거래소
기존 쿠폰 시스템은 중앙 서버에서 발행 수량, 사용 내역, 유효기간을 관리하므로 운영자가 임의로 발행량을 조작하거나 사용 기록을 변조할 수 있다. 소비자는 쿠폰의 진위 여부나 잔여 수량을 독립적으로 검증할 수 없다.
종래의 쿠폰은 발행 가맹점 내에서만 사용할 수 있어, 서로 다른 가맹점(예: 치킨점과 맥주점)의 쿠폰을 결합하여 새로운 혜택(예: 치맥 세트 할인)을 만드는 것이 구조적으로 불가능하다. 설령 제휴를 한다 하더라도, 일방적 제휴 설정만으로는 상대 가맹점의 동의 없이 결합이 강제될 위험이 있다.
쿠폰이 결합되더라도 양쪽 가맹점 모두에서 순차적으로 사용되어야 하는 경우(AND 모드), 한쪽 가맹점만 사용하고 나머지를 사용하지 않는 상황에서 미사용분 처리 로직이 없어 소비자 피해가 발생할 수 있다.
블록체인 기반 시스템에서 오프라인 매장 결제를 구현할 때, 기존 방식(setApprovalForAll)은 점주에게 소비자의 전체 토큰에 대한 무제한 권한을 부여하게 되어, 특정 쿠폰 1장만 소각하려 해도 모든 자산이 위험에 노출된다.
ERC-1155 온체인 쿠폰 발행 — 발행 수량(maxSupply), 유효기간(startAt/expiresAt), 메타데이터(IPFS URI)가 스마트 컨트랙트에 불변 기록되어, 누구나 블록체인에서 독립적으로 검증 가능. 만료된 토큰은 _update() 레벨에서 전송 자체가 차단됨.
상호 합의형 결합(Hybrid allowMerge) — 양쪽 가맹점이 각각 setAllowMerge()를 호출하여 상호 동의한 경우에만 결합 타입 생성이 가능. 일방적 결합을 원천 방지.
AND 모드 에스크로 + 타임아웃 자동 반환 — 첫 번째 가맹점 사용 시 에스크로 생성, 두 번째 가맹점이 타임아웃 내 완료하지 않으면 미사용 소스 토큰을 소비자에게 자동 반환(mint-back). 소비자 보호와 가맹점 간 공정성을 스마트 컨트랙트로 보장.
EIP-712 건별 서명 기반 QR 결제 — 소비자가 특정 tokenId, 수량, orderId, deadline에 대해서만 1회성 서명(Redeem 타입)을 생성. 점주는 이 서명으로만 해당 쿠폰을 소각할 수 있으며, 다른 토큰이나 추가 수량에 대한 권한은 전혀 부여되지 않음.
2. 시스템 아키텍처
- 결합 정의 — createMergeType (OR/AND 모드 지정)
- registerMerchant — 가맹점 등록 (merchantIndex ↔ address 매핑)
- setIssuer — 발행자 권한 부여/회수
- pause / unpause — 컨트랙트 긴급 정지
- setDefaultEscrowTimeout — 에스크로 기본 타임아웃 설정
3. 핵심 기능 상세
각 기능의 전제 조건, 처리 흐름, 구체적 실시 예를 기술합니다.
전제 조건
- 가맹점이
registerMerchant(merchantIndex, address)로 사전 등록되어 있어야 한다. - 호출자(msg.sender)는 해당 가맹점의 소유자(merchantOwner)이거나 관리자(owner/issuer)여야 한다.
- 메타데이터 URI(IPFS CID)가 비어 있지 않아야 한다.
- maxSupply가 0이 아닌 경우, initialSupply는 maxSupply를 초과할 수 없다.
토큰 ID 생성 규칙
토큰 ID는 256비트 정수로, 상위 192비트에 merchantIndex(uint32), 하위 64비트에 localId(uint64)를 배치하여 생성된다.
이 구조로 인해 가맹점 간 토큰 ID 충돌이 원천 방지되며, 토큰 ID에서 가맹점을 역산할 수 있다.
처리 흐름
createCoupon(merchantIndex, tokenUri, startAt, expiresAt, maxSupply, initialSupply)가 호출된다.nextLocalId[merchantIndex]를 자동 증가시키고, _makeId()로 고유 tokenId를 생성한다.CouponCreated 이벤트가 발생한다.구체적 실시 예
| 가맹점 | 구로통닭 (merchantIndex = 1) |
| 점주 지갑 | 0x1234...abcd |
| 쿠폰명 | 치킨 5,000원 할인권 |
| 발행 수량 | 1,000장 (maxSupply = 1,000) |
| 유효기간 | 2025-01-01 ~ 2025-12-31 |
| 생성된 tokenId | (1 << 64) | 1 = 18446744073709551617 |
| 메타데이터 | ipfs://bafk...xyz (이미지, 이름, 설명, 혜택 포함) |
전제 조건
- 소비자가 EVM 호환 지갑 주소를 보유하고 있어야 한다.
- 점주가 해당 tokenId의 토큰을 1개 이상 보유하고 있어야 한다.
- 해당 쿠폰이 만료(expiresAt)되지 않았어야 한다.
처리 흐름
safeTransferFrom(merchant, consumer, tokenId, amount, 0x)가 호출된다.setAllowMerge()를 호출하여 상호 합의한 경우에만, 소비자가 두 토큰을 동시 소각(burn)하고 새로운 결합 토큰을 발행(mint)받을 수 있도록 한 시스템. 결합된 토큰은 다시 원래 토큰으로 분리(unmerge)할 수 있어 가역성을 보장한다.
3-3-1. 결합 허용 설정 (setAllowMerge)
- 호출자는 자기 토큰의 가맹점 소유자이거나 관리자여야 한다.
- 자기 토큰(myToken)이 이미 결합 토큰(isMerged=true)이 아니어야 한다.
- 양쪽 토큰이 모두 존재(exists=true)해야 한다.
- 양방향 합의 필수: A 가맹점이
mergeAllowed[tokenA][tokenB] = true로 설정하고, B 가맹점도mergeAllowed[tokenB][tokenA] = true로 설정해야만isMergePairAllowed()가 true를 반환한다.
3-3-2. 결합 타입 생성 (createMergeType)
- 관리자(owner/issuer)만 호출 가능하다.
- 소스 토큰 A, B가 서로 다른 가맹점이어야 한다 (SameMerchant 방지).
isMergePairAllowed(sourceIdA, sourceIdB)가 true여야 한다.- OR 또는 AND 모드를 지정한다.
결합 토큰의 merchantIndex는 0(MERGE_NAMESPACE)으로 설정되어, 일반 가맹점 토큰과 구분된다. 유효기간은 두 소스 토큰 중 더 이른 만료일(_minExpiry)이 적용되고, 시작일은 더 늦은 시작일(_maxStart)이 적용된다.
allowedMerchantA/B에는 소스 토큰들의 merchantIndex가 정렬(lo/hi)되어 저장되며, 이는 이후 OR/AND 모드에서 해당 가맹점만 사용 처리를 할 수 있도록 제한하는 근거가 된다.
3-3-3. 결합 실행 (mergeTo)
mergeTo(sourceIdA, sourceIdB, mergeId)를 호출한다._burn(user, sourceIdA, 1) + _burn(user, sourceIdB, 1) + _mint(user, mergeId, 1)가 원자적(atomic)으로 실행된다.3-3-4. 분리 (unmerge) — 가역성 보장
- 소비자가 결합 토큰을 1개 이상 보유하고 있어야 한다.
- 해당 사용자+결합토큰에 대해 활성 에스크로가 없어야 한다 (
activeEscrow[user][mergeId] == 0).
unmerge(mergeId) 호출 시: 결합 토큰 1장을 소각하고, 원래의 소스 토큰 A, B를 각 1장씩 소비자에게 재발행(mint)한다. 이로써 소비자는 결합 결정을 철회하고 원래 쿠폰으로 되돌릴 수 있다.
구체적 실시 예
| 소스 A | 구로통닭 - 치킨 5,000원 할인권 (merchantIndex=1, tokenId=18446744073709551617) |
| 소스 B | 골목맥주 - 맥주 3,000원 할인권 (merchantIndex=2, tokenId=36893488147419103233) |
| 결합 전 | 구로통닭 점주가 setAllowMerge(tokenA, tokenB, true) 호출 골목맥주 점주가 setAllowMerge(tokenB, tokenA, true) 호출 |
| 모드 | OR — 어느 한 가맹점에서 1회 사용 |
| 결합 결과 | 치맥 결합권 (merchantIndex=0, tokenId=1) allowedMerchantA=1(구로통닭), allowedMerchantB=2(골목맥주) |
| 결합 실행 | 소비자가 mergeTo 호출 → 치킨권 1장 소각 + 맥주권 1장 소각 → 치맥 결합권 1장 발행 |
| 분리 | 소비자가 unmerge 호출 → 치맥 결합권 소각 → 치킨권 1장 + 맥주권 1장 복원 |
전제 조건
- 결합 토큰의 mergeMode가 OR이어야 한다.
- 사용 처리를 실행하는 점주의 merchantIndex가 allowedMerchantA 또는 allowedMerchantB 중 하나여야 한다.
처리 흐름
OR 모드 결합 쿠폰은 일반 쿠폰과 동일한 방식으로 사용된다. 기존의 redeemWithSig() (QR 서명 기반) 또는 redeemFrom() (승인 기반)을 그대로 사용하며, _validateMerchantForToken()에서 결합 토큰인 경우 allowedMerchantA/B 중 하나와 매칭되는지를 검증한다.
소비자가 구로통닭 매장에서 치맥 결합권을 제시 → 점주가 redeemWithSig로 소각 → 결합권 1장 소각됨 (맥주점 사용 불가 — 이미 소각되었으므로). 또는 골목맥주에서 사용하면 동일하게 1회 소각으로 완료된다.
에스크로 상태 머신
Step 1: 첫 번째 가맹점 사용 (QR 기반)
- 결합 토큰의 mergeMode가 AND이어야 한다.
- 호출자(점주A)가 allowedMerchantA 또는 allowedMerchantB의 가맹점 소유자여야 한다.
- 소비자(user)가 호출자에게
setApprovalForAll을 부여했어야 한다. - 소비자가 결합 토큰을 1개 이상 보유하고 있어야 한다.
- 동일 user + mergeTokenId에 대해 기존 활성 에스크로가 없어야 한다.
setApprovalForAll(merchantWallet, true)이 먼저 실행된다.{ type: "escrow-confirm", rid, wallet, mergeTokenId, balance }가 포함된다. 소비자가 이 QR2를 점주에게 제시한다.useAtFirstMerchant(user, mergeTokenId, merchantIndex)를 호출한다._burn)되고, 에스크로 레코드가 생성된다: { state: A_USED, user, mergeTokenId, usedMerchantIndex, timeout }. 에스크로 ID가 화면에 크게 표시되며, 소비자에게 이 ID를 전달한다. activeEscrow[user][mergeTokenId] = escrowId로 기록되어 중복 에스크로가 방지된다.소비자의 에스크로 ID 조회
소비자는 에스크로 확인 페이지의 "내 에스크로 ID 조회" 기능을 통해, 결합 토큰 ID를 입력하면 activeEscrow(myAddress, mergeTokenId)를 온체인으로 조회하여 자신의 활성 에스크로 ID를 확인할 수 있다. 이 에스크로 ID는 Step 2에서 B 가맹점 방문 시 필요하다.
Step 2: 두 번째 가맹점 완료 (QR 기반)
- 에스크로 상태가 A_USED여야 한다.
- 호출자(점주B)의 merchantIndex가 첫 번째 사용 가맹점(usedMerchantIndex)과 달라야 한다 (AlreadyUsedAt 방지).
- 타임아웃이 경과하지 않았어야 한다.
{ type: "escrow-step2-confirm", rid, wallet, escrowId }가 포함된다. 핵심적으로 에스크로 ID가 소비자에 의해 QR2에 포함되어 점주B에게 전달된다.useAtSecondMerchant(escrowId, merchantIndex)를 호출한다.activeEscrow[user][mergeTokenId]가 0으로 초기화된다. 양쪽 가맹점 모두에서 쿠폰 사용이 완료된다.에스크로 ID 전달 흐름의 설계 의도
B 가맹점(점주B)은 소비자의 에스크로 ID를 사전에 알 수 없다. 에스크로 ID는 Step 1에서 온체인으로 생성되며, 소비자만이 자신의 에스크로 ID를 알고 있다. 따라서 소비자가 QR2를 통해 에스크로 ID를 점주B에게 전달하는 구조를 채택하였다. 이로써:
- 점주B는 에스크로 ID를 직접 입력하거나 조회할 필요가 없어 UX가 간소화된다.
- 소비자가 자신의 에스크로를 능동적으로 제시하므로, 잘못된 에스크로가 처리될 위험이 없다.
- QR 기반 대면 인증으로 소비자 본인 확인이 이루어진다.
타임아웃 및 자동 반환 (expireEscrow)
- 에스크로 상태가 A_USED이고,
block.timestamp > timeout이어야 한다. - 누구나(anyone) 호출할 수 있다 — 탈중앙화 실행.
타임아웃 시 에스크로가 EXPIRED로 전환된다. 이때 첫 번째 가맹점이 이미 사용한 소스 토큰은 소각된 것으로 유지되고, 두 번째 가맹점에 해당하는 미사용 소스 토큰만 소비자에게 반환(mint-back)된다.
if (sourceIdA의 merchantIndex == usedMerchantIndex) → sourceIdB를 반환
else → sourceIdA를 반환
이 메커니즘으로 첫 번째 가맹점의 혜택 제공은 유효하게 인정하면서, 두 번째 가맹점의 미제공 혜택에 해당하는 원래 쿠폰은 소비자에게 되돌려 준다.
| 상황 | 소비자가 치맥 결합권(AND 모드) 1장을 보유. 구로통닭(치킨)과 골목맥주(맥주)에서 모두 사용해야 완료됨. |
| Step 1 | 구로통닭 매장 방문 → 점주A가 QR1 생성 → 소비자가 스캔, setApprovalForAll 승인, QR2 생성 → 점주A가 QR2 스캔 → useAtFirstMerchant 호출 → 치맥 결합권 1장 소각 → 에스크로 생성 (escrowId=1, state=A_USED, timeout=30일후) → 소비자에게 에스크로 ID=1 전달 |
| 에스크로 ID 조회 | 소비자가 에스크로 확인 페이지에서 "내 에스크로 ID 조회" → 결합 토큰 ID 입력 → activeEscrow 조회 → 에스크로 ID=1 확인 |
| Step 2 (정상) | 30일 내 골목맥주 매장 방문 → 점주B가 2단계 QR1 생성 → 소비자 스캔, 에스크로 ID=1 입력, QR2 생성 → 점주B가 QR2 스캔 → useAtSecondMerchant(escrowId=1, merchantIndex=2) 호출 → 에스크로 COMPLETE |
| Step 2 (타임아웃) | 30일 경과 후 소비자가 골목맥주를 방문하지 않음 → 누군가가 expireEscrow(escrowId=1) 호출 → 에스크로 EXPIRED → 맥주 할인권(sourceIdB) 1장이 소비자에게 자동 반환됨 (치킨은 이미 사용되었으므로 반환되지 않음) |
setApprovalForAll()과 달리 전체 자산 노출 위험이 원천 차단된다.
EIP-712 서명 구조체
QR 2단계 프로토콜
redeemWithSig(user, tokenId, amount, merchantIndex, orderId, nonce, deadline, sig)를 호출. 컨트랙트가 서명 검증 후 쿠폰을 소각한다.nonce를 통한 리플레이 방지
각 사용자(user)별로 redeemNonces[user]가 관리된다. 서명에 포함된 nonce와 현재 저장된 nonce가 일치해야만 유효하며, 사용 후 nonce가 +1 증가한다. 따라서 동일 서명을 재사용(replay)하는 것이 불가능하다.
| QR1 생성 | 구로통닭 점주가 POS에서 { merchantIndex:1, tokenId:18446744073709551617, amount:1, orderId:0xabc..., deadline:now+300초 } QR 생성 |
| 소비자 서명 | 소비자가 QR1 스캔 → MetaMask에서 EIP-712 서명 → sig(65 bytes) 생성 |
| QR2 제시 | 소비자 화면에 QR2 표시 (sig + user + nonce 포함) |
| 소각 처리 | 점주가 QR2 스캔 → redeemWithSig 호출 → 서명 검증(ECDSA.recover) → nonce 확인 → 쿠폰 1장 소각 |
ERC-1155의 _update() 내부 함수를 오버라이드하여, 모든 토큰 전송(transfer, safeTransfer, batch) 시점에 다음을 검증한다:
- 만료 차단:
expiresAt != 0 && block.timestamp > expiresAt && to != address(0)→ 전송 거부 (Expired). 단,to == address(0)(소각)은 허용하여 만료 쿠폰의 정리를 가능하게 한다. - 미시작 차단:
startAt != 0 && block.timestamp < startAt && from != address(0)→ 전송 거부 (NotStarted). 단,from == address(0)(민팅)은 허용하여 사전 발행을 가능하게 한다. - 일시정지:
whenNotPaused수정자로 긴급 정지 시 모든 전송이 차단된다.
이 설계로 인해 만료된 쿠폰이 2차 시장에서 거래되거나, 시작 전 쿠폰이 유출되는 것을 온체인 레벨에서 방지한다.
_update() 오버라이드로 만료 토큰의 거래소 예치가 자동 차단된다. 향후 RWA(Real World Asset) 토큰 거래로 확장 가능한 구조이다.
거래소 아키텍처
CouponExchange는 Coupon1155V3와 별도로 배포되는 독립 컨트랙트이다. ERC1155Holder를 상속하여 ERC-1155 토큰을 에스크로로 보유할 수 있으며, 판매자/제안자의 토큰을 컨트랙트에 예치한 후 구매자/수락자의 행동에 의해 원자적으로 정산한다.
3-8-1. 판매 모드 (Sell Order: 쿠폰 → ETH)
- 판매자가 거래소 컨트랙트에
setApprovalForAll을 부여해야 한다. - 쿠폰이 만료되지 않았어야 한다 (만료 시
safeTransferFrom이 revert). - 판매 가격(priceWei)이 0보다 커야 한다.
createSellOrder(tokenId, amount, priceWei)를 호출. 쿠폰이 판매자 지갑에서 거래소 컨트랙트로 에스크로 전송된다.buyCoupon(orderId)를 ETH와 함께 호출. 수수료(feeBps, 기본 2.5%)가 공제된 후 판매대금이 판매자에게, 쿠폰이 구매자에게 원자적으로 전달된다.cancelSellOrder(orderId)로 취소 가능. 에스크로된 쿠폰이 판매자에게 반환된다.3-8-2. 스왑 모드 (Swap Order: 쿠폰 ↔ 쿠폰)
- 제안자가 제공할 쿠폰(offerToken)과 원하는 쿠폰(wantToken)을 지정한다.
- 제안자의 쿠폰이 거래소에 에스크로된다.
- 수락자는 원하는 쿠폰을 보유하고 있어야 하며, 거래소에
setApprovalForAll을 부여해야 한다.
createSwapOrder(offerTokenId, offerAmt, wantTokenId, wantAmt)를 호출. 제공 쿠폰이 에스크로된다.acceptSwap(orderId)를 호출. 수락자의 쿠폰이 제안자에게, 에스크로된 제안자의 쿠폰이 수락자에게 원자적(atomic)으로 교환된다. 한쪽만 전달되는 상황이 불가능하다.cancelSwapOrder(orderId)로 취소 가능.3-8-3. 만료 토큰 거래 자동 차단
Coupon1155V3의 _update() 오버라이드로 인해, 만료된 쿠폰을 거래소 컨트랙트로 전송(safeTransferFrom)하는 것 자체가 revert된다. 따라서 거래소 컨트랙트에 별도의 만료 검증 로직을 구현할 필요가 없으며, 쿠폰 컨트랙트의 보안 정책이 거래소에도 투명하게 적용된다. 이는 ERC-1155 표준의 _update() 레벨 제어가 생태계 전반에 파급되는 설계적 이점이다.
3-8-4. 호가 거래 모드 (Order Book Trading)
현재 마켓(게시판) 모드에 더하여, 대량 발행된 동일 토큰에 대해 호가(Order Book) 방식의 거래도 지원할 수 있도록 설계되어 있다. ERC-1155의 특성상 동일 tokenId의 토큰은 대체 가능(Fungible)하므로, 매수/매도 호가를 매칭하는 연속 거래가 가능하다.
3-8-4-1. 듀얼 모드 아키텍처
- 마켓 모드 (현재 구현): 개별 쿠폰, 한정판, 결합 쿠폰 등 소량/다종 거래에 적합. 판매자가 가격을 지정하고 구매자가 수락하는 게시판 방식.
- 호가 모드 (설계 완료): 정액 상품권, 포인트 토큰, RWA 자산 등 대량/동종 거래에 적합. 매수/매도 호가가 자동 매칭되는 연속 경매(Continuous Double Auction) 방식.
3-8-4-2. 호가 매칭 엔진 설계
호가 거래 모드는 가격-시간 우선(Price-Time Priority) 원칙에 따라 주문을 매칭한다. 온체인 가스 비용을 최적화하기 위해 하이브리드 매칭 구조를 채택한다.
- 온체인 정산: 매칭된 주문의 토큰 이전과 ETH 정산은 스마트 컨트랙트에서 원자적으로 실행. 부분 체결(Partial Fill) 지원.
- 오프체인 매칭 (옵션): 대량 주문 시 매칭 연산을 오프체인에서 수행하고 결과만 온체인에 제출하는 릴레이어 구조. zkProof로 매칭 정당성을 검증할 수 있다.
- 주문 유형: 지정가(Limit Order) — 특정 가격 지정, 시장가(Market Order) — 현재 최우선 호가로 즉시 체결.
- 호가창 구조: 매도 호가(Ask)는 낮은 가격순, 매수 호가(Bid)는 높은 가격순으로 정렬. 스프레드(Spread)는 최우선 매도가와 최우선 매수가의 차이.
3-8-4-3. RWA(Real World Asset) 확장
ERC-1155 기반 토큰화 인프라와 호가 거래소를 결합하면, 쿠폰을 넘어 다양한 실물 자산(RWA)의 토큰화와 2차 시장 거래가 가능하다. 동일 플랫폼에서 발행-유통-거래의 전 라이프사이클을 관리할 수 있는 것이 핵심 강점이다.
- 부동산 분할 소유권: 건물/토지의 소유권을 N개 토큰으로 분할 발행. 투자자 간 호가 거래로 유동성 확보. 임대 수익은 토큰 보유 비율에 따라 자동 분배.
- 상품권/포인트: 정액 상품권, 기프트카드, 포인트를 토큰화. 시세에 따른 할인/프리미엄 거래. 만료 기능이 그대로 적용되어 유효기간 자동 관리.
- 탄소 크레딧: 탄소 배출권 1톤 단위 토큰화. 기업 간 대량 호가 거래. 온체인 투명성으로 이중 사용 방지.
- 공연/이벤트 티켓: 좌석별 토큰 발행. 2차 시장 리세일 시 원작자 로열티 자동 정산. 전매 가격 상한 설정 가능.
- 멤버십/구독권: 기간제 멤버십을 토큰화. 잔여 기간에 따라 가치가 변동하는 감가 거래.
| 부동산 | A 건물 100분의 1 소유권 토큰(tokenId=100) 1,000개 발행 → 투자자들이 호가 거래소에서 매수/매도 → 0.5 ETH에 체결 → 분기별 임대수익 자동 분배 |
| 상품권 | 5만원 상품권 토큰(tokenId=200) 10,000장 발행 → 호가창에서 0.025 ETH(액면가 대비 5% 할인)에 거래 → 시장 수급에 따라 가격 변동 |
| 탄소크레딧 | 1톤 크레딧 토큰(tokenId=300) → 기업 A가 100톤 매수 주문(0.01 ETH/톤) → 기업 B가 매도 수락 → 즉시 온체인 정산 |
| 판매 | 사용자 A가 치킨 5,000원 할인권 1장을 0.001 ETH에 판매 등록 → 쿠폰이 거래소에 에스크로 → 사용자 B가 0.001 ETH 지불 → 쿠폰이 B에게, ETH가 A에게 원자적 정산 (수수료 2.5% 공제) |
| 스왑 | 사용자 A가 "치킨 할인권 1장 ↔ 맥주 할인권 1장" 스왑 제안 → 치킨 할인권 에스크로 → 사용자 C(맥주 할인권 보유)가 수락 → 치킨권이 C에게, 맥주권이 A에게 원자적 교환 |
| 만료 차단 | 사용자 D가 만료된 쿠폰을 판매 등록 시도 → safeTransferFrom에서 Expired revert → 등록 자체 불가 |
4. 전체 서비스 흐름도
AND 모드: 점주A가 QR1 생성 → 소비자가 승인+QR2 제시 → 점주A가 useAtFirstMerchant로 에스크로 생성 → 소비자가 에스크로 ID 확인 → 점주B가 2단계 QR1 생성 → 소비자가 에스크로 ID 입력+QR2 제시 → 점주B가 useAtSecondMerchant로 완료. 타임아웃 시 미사용분 자동 반환.
스왑: 소비자 간 쿠폰↔쿠폰 교환 제안/수락. 이종 가맹점 쿠폰도 자유롭게 교환 가능.
만료된 쿠폰은 거래소 등록 자체가 차단됨.
5. 컨트랙트 정보
(미배포)-
URI: -
점주 재고: -
| ID | 가맹점 | 요청자 | Token ID | 수량 | 내 재고 | 상태 | 액션 |
|---|
보유/재료 상태
A 1장 + B 1장 보유 시 결합 가능
미리보기
URI: -
-
-소비자가 #에스크로 확인 페이지에서 QR2를 보여줍니다.
-소비자가 에스크로 확인 페이지에서 QR2를 보여줍니다.
에스크로 ID를 입력하고 조회하세요.
요청 상세
----(empty)
점주가 QR2를 스캔하면 에스크로가 생성됩니다.
1단계 완료 후 여기서 에스크로 ID를 확인하여 2단계에서 사용하세요.
-url:
-QR2가 복잡할 수 있으니 카메라 초점을 맞춰주세요.
불러오는 중...
요청 상세
------1회 소각 권한만 서명합니다 (전체 권한 아님)
-(empty)
QR2가 복잡하면 화면 밝기를 높이고 거리를 띄워주세요.