Skip to content

P0 Verification Record

Written 2026-07-27.

Target networks: XMTP dev, GIWA Sepolia (chain ID 91342).

This document records only what was confirmed on the live networks. Private keys, full session tokens, raw signatures, and message plaintext are not recorded.

1. Test addresses

Label Address
A 0xEf792c4973Cc8ef6aF433B3bd9f4461B701301f6
B 0x532dA989489eaB825d484EAd09f117018da47778
C 0x2F9713FB44eE7A15EF393eA694959324Be7a6479

2. Dojang verification status

The attesterId is TESTNET_FAUCET. Under UPBIT_KOREA all three addresses are unverified, and that is pinned in the fork test.

Before issuance (baseline block 31763461)

Address isVerified
A true
B false
C false

This block is pinned as BASELINE_BLOCK in contracts/test/ConversationEvidenceRegistry.fork.t.sol, so the mixed-state verification evidence survives later on-chain changes.

Issuing verification for B

GIWAFaucetExtension.payAndIssueEAS() was called with a 0.001 ETH fee. The attestation expires 30 days after issuance.

contract:        0x63CCe2b569A7bC35895ee24306c1512fefc06121
transactionHash: 0x245e27442da2987a3918b01e3fb48cfbdbff90f83e155bc6c5715662aa165494
blockNumber:     31763610
status:          success

After issuance (measured at block 31763622)

Address isVerified
A true
B true
C false

C is deliberately kept unverified to exercise the evidence-blocking path.

3. Evidence contract deployment

contract:        ConversationEvidenceRegistry
address:         0x675dB91aCEC52DCb44e6d20FB1F1299FFafBb51B
transactionHash: 0x8f018ccbb711133dcc52958d50f472bf0c32bde970fec943d39e637d7db01da0
blockNumber:     31763659
compiler:        v0.8.35+commit.47b9dedd

Blockscout source verification was confirmed as is_verified: true. After deployment, dojangScroll, attesterId, and domainSeparator were queried again and matched the constructor arguments.

4. Real on-chain evidence transactions

frontend/src/infrastructure/chain/ViemEvidenceContractAdapter.integration.test.ts was run against live GIWA Sepolia. All four tests passed.

Check Result
Record evidence with signatures from both A and B Success
Read the recorded evidence back from the chain Success, contentHash and participants match
Evidence including unverified C Rejected with ParticipantNotVerified
Reusing the same evidence ID Rejected with EvidenceAlreadyRecorded

The successful recordEvidence transactions:

transactionHash: 0xef01ef70199a1ec835fb9441b4859b7251c9ad7b7fffede7af6a8255f75a94fc
transactionHash: 0xc6d0f502a5c983d9225369250ad429dfc5ae80b4083a11be8f4718945feeecc2
transactionHash: 0x5ac2e5dd6ccaf2fd9a7d890334963bca770ed863ace11a466d242ea3afe1c2cc

4.1 Full use-case chain verification

frontend/src/application/evidence/EvidenceEndToEnd.integration.test.ts was run against the real backend and live GIWA Sepolia. Rather than a single adapter, it traverses the whole use-case chain from proposal to on-chain record in one pass.

Step Result
A signs in with SIWE and proposes evidence PROPOSED
The control message contains no plaintext Confirmed
A signs SIGNING
B signs READY
A submits on chain CONFIRMED
Proposal including unverified C Blocked with EVIDENCE_PARTICIPANTS_NOT_VERIFIED; neither the API request nor the control message was created

The successful end-to-end transaction:

transactionHash: 0x677de178e5d99fdb38429206a2d8f50ba2a248e6c990b72df8e2ae3b6ae436ed
blockNumber:     31766627

This is the evidence for design document §11.2, "EIP-712 multi-signature and GIWA Sepolia evidence succeed for a conversation where every participant is verified."

5. Hash rule parity

The frontend hashParticipants and the deployed contract's hashParticipants were measured to return the same value. Both produced 0x4f68b5db8071fee0ae36ede40c0b63d7e402332397de1f8ad260e1f5082c286e.

6. Live XMTP dev messaging

frontend/e2e/messaging-three-users.spec.ts was run in a real browser against the live XMTP dev network. It passed (28.6s).

Check Result
A, B, C each create or recover an XMTP Inbox Success
A and B 1:1 round trip Success
B and C 1:1 round trip Success
A creates an A/B/C group Success
Each of the three sends to the group, the other two receive on the stream Success
Messaging continues under mixed verification (A and B verified, C not) Success

Message IDs and conversation IDs change per run, so the values themselves are not recorded. The test decides pass/fail by comparing the XMTP message ID the sender received against the ID the recipient received on the stream.

7. Live app screen flows

frontend/e2e/app-wallet-login.spec.ts and app-three-users.spec.ts were run against the real backend and XMTP dev. A test-only EIP-1193 provider was injected and private keys stayed in the Node process only.

After wallet A signed in, a session row for that address was confirmed directly in the PostgreSQL sessions table.

app-three-users.spec.ts passed all three scenarios (57.4s).

Scenario Result
A, B, C sign in through the app UI and exchange A-B and B-C 1:1 messages Pass
A conversation with unverified C is routed to the request inbox and the evidence button is disabled Pass
Messages can still be sent to and received from unverified C Pass
The evidence entry point is enabled in the verified A-B conversation Pass

One wallet takes around 40 seconds to create an XMTP client. Specs that sign in several wallets sequentially need generous timeouts.

8. Automated test counts

Target Passing
frontend unit and integration 178
backend unit and PostgreSQL integration 132
contracts unit, fuzz, fork 41

8.1 A confirmed operational constraint: the XMTP installation limit

During verification, all three test wallets reached a state where XMTP Client.create stopped responding. The cause was narrowed in this order.

  1. messaging-three-users.spec.ts, which had passed at 08:57, failed with no code change. So it was not an app-code regression.
  2. A freshly generated random wallet reached the inbox from sign-in normally at the same moment. So it was not an XMTP dev network outage.
  3. Querying installations with wallet A produced this error:
Cannot register a new installation because the InboxID ... has already
registered 10/10 installations. Please revoke existing installations first.

XMTP limits an inbox to 10 installations. Because Playwright opens a context with an empty browser profile each time, every sign-in registers a new installation, so repeated runs exhaust the slots. Real users keep their browser storage, so this does not arise for them.

There are two mitigations.

  • e2e/support/persistentContext.ts pins a profile directory per wallet so reruns reuse the existing installation.
  • Wallets already at the limit are recovered with e2e/revoke-installations.spec.ts.
UMUL_REVOKE_WALLETS=A,B,C npx playwright test e2e/revoke-installations.spec.ts

9. Remaining constraints

  • Faucet attestations expire 30 days after issuance. A expires around 2026-08-10 and B around 2026-08-25; re-verifying the evidence success path after that requires reissuing them.
  • The legal weight of evidence is out of scope at this stage.
  • P0 supports EOA signatures only. EIP-1271 smart accounts are a P1 item.
  • The Android app was not implemented. The reasoning is in mobile/README.md.