VeilSwap
← All posts
実践ガイド2026-11-039 min read

URI・クリップボード・QR:アドレスは受け渡しの途中でこう壊れる

アドレスは財布に届くまでに URI・クリップボード・QR という三つのエンコーダを通ります。それぞれがどう壊すのかを実測し、送金前に確認すべき点をまとめました。

アドレスは「物」ではありません。送金ボタンを押す前に、すでに何度かエンコードされ、コピーされ、描画され、スクリーンショットに撮られ、デコードされた文字列です。交換の注文ページでは、その文字列が出ていく扉は三つしかありません。コピーボタン、200 ピクセルの QR コード、そして選択できるテキストです。三つとも壊れ方が違い、しかも壊れても見えません——壊れた版もアドレスに見えるからです。私たちはこの三つを実際のサイトで測りました。クリップボードが何を残すのか、QR が何を符号化しているのか、九種類のアドレス形式が十二種類の変形にどう反応するのか。代償は具体的です。本日 18:06 UTC、100 USDT-TRC20 は 0.13937044 XMR で見積られました。一文字欠けた着金先は注文失敗ではなく、宛先のない支払い済み注文になります。同じ時刻のカタログは 434 資産・62 ネットワーク、うち 6 資産はメモが必須でした。 (XMR→USDT 出口ルート)

まず URI です。金額を運べる唯一の経路だからです。BIP-21 の文法は bitcoin:<アドレス>?amount=<十進 BTC>。金額は十進 BTC で最大八桁、satoshi 単位は不可、クライアントは未知のパラメータを拒否ではなく無視しなければなりません。EIP-681 は ethereum:<アドレス>@<チェーン ID>/transfer?address=<受取先>&uint256=<最小単位>。ここでの金額はトークンの最小単位の整数——1 USDT は 1000000 であって 1 ではない——しかも value=2.014e18 のような指数表記が明示的に許されています。Monero は monero:<アドレス>?tx_amount=<十進 XMR>&tx_payment_id=<64 桁 hex>。wallet2.cpp のパーサは知らないパラメータを unknown_parameters に積んで、それでも成功を返します。この一行が故障の全体です:tx_amount を amount と書いた URI は拒否されず、「金額なし」として受理され、金額の入力が人間に戻ります。 (XMR→USDT 出口ルート)

サイトの検証器に九形式×十二変形、計 90 セルを通しました。URI 接頭辞が付いたものは全チェーンで拒否され、理由も「not a Bitcoin address (expect bc1…, 1… or 3…)」のように素直です。貼り付け欄としては正しい判断です。交換所は自分が生成していない文字列の中の金額を実行してはいけません。URI の金額は指示であって宛先ではないからです。代償は一方通行になることです。ウォレットやエクスプローラが bitcoin:bc1q…?amount=0.01 を渡してきても、この欄は受け取りません。scheme とクエリを落として経路だけ残してください。逆に当サイトの QR は裸のアドレスだけを符号化します。だから読み取ったコードが誤った金額を持つことはありえず、正しい金額を持つこともありません。

次はクリップボードです。三つの中で最も信用できず、最も使われています。コピーボタンは navigator.clipboard.writeText を呼び、エラーを握りつぶす try/catch で包んでいます。安全でないコンテキストや権限拒否では、何もコピーされず、何も表示されません。検証器は照合の前に trim するので、四つのありふれた残留物が静かに救われます。末尾の改行、末尾の空白、両側のノーブレークスペース(U+00A0)、先頭の BOM(U+FEFF)で、この四つは九形式すべてで通過しました。通らなかったのは三つ。ゼロ幅スペース(U+200B)、右から左へのマーク(U+200F)、ソフトハイフン(U+00AD)で、中央に挿入しても末尾に付けても全形式で拒否されました——そしてこれは PDF、チャット、両端揃えのウェブページからコピーしたときに最も紛れ込みやすい文字でもあります。第二の罠は大文字小文字です。bech32 の全大文字は合法で通過、混在はチェックサムで落ち、Monero の全大文字は即拒否、0X の大文字 X は EVM アドレスではありません。

QR は独立した節に値します。幾何が静かに成否を決めているからです。注文ページは react-qr-code を size=200、level 未指定で描画します。つまりライブラリ既定の L、訂正能力およそ 7% です。このコンポーネントはモジュールだけを描き、viewBox をモジュール数に等しく取るので、コード自身はクワイエットゾーンを持ちません。白い余白はコンテナの 16 ピクセル余白です。200 CSS ピクセルでは、その余白は 29 モジュールで 2.32 モジュール分、33 で 2.64、37 で 2.96、41 で 3.28——規格は 4 を要求します。モジュール径は 6.90 ピクセルから 4.88 ピクセルまで下がります。106 文字という長さも偶然ではありません。バージョン 5 の L におけるバイト容量そのもので、だから 95 文字の Monero アドレスも 106 文字の統合アドレスも 37 モジュールに収まり、一文字増えるか level を M に上げると 41 に飛びます。

そして幾何を信じずに実際にデコードしました。200 ピクセルの実レイアウトを四倍で描き、劣化させ、jsQR 1.4.0 で一セルあたり 20 回のランダムな揺らぎを与えて読ませた結果は、きれいな曲線になりました。116 ピクセル幅——描画サイズの半分——までは、二十四通りすべてが毎回正しく読めました。品質 40 の JPEG、2 度の回転、サブピクセル偏移を重ねてもです。93 ピクセル、0.8 ピクセルのぼかし、JPEG 40、3 度回転では、短いコードは持ちこたえました(29 モジュール 20/20、33 モジュール 19〜20/20)。長いコードは落ちました。37 モジュールは 9/20 と 8/20、41 モジュールは 2/20 と 0/20 です。訂正を L から M に上げると、これらの長いコードはむしろ悪化しました。同じ 200 ピクセルに四つ多くのモジュールを詰め込むからです。一方、幅の 18% を覆う白い円を偏心させて置いた場合は生き残りました。短いコードで 16〜19/20、長いコードは 20/20 で、冗長面積の大きい側が強いという結果です。

最後の穴は幾何ではなく構造です。QR が符号化するのは入金アドレスだけで、コンポーネントに渡されている値がそれしかないからです。メモはその下の別のコピー行にあります。カタログ 434 資産のうち 6 つがメモ必須——XRP、XLM、HBAR、ATOM、STX、NEIRO-eth——で、共用入金アドレスがこの穴を広げます。タグで振り分けるチェーンでは複数の注文が一つのアドレスを共有し、QR で止まった人はタグなしで送ることになります。XRP ではそれは遅延ではなく、プールが帰属できない入金です。コードを見ると形もそのままです。QR は depositAddress から、メモは depositExtraId から、別々の要素で描かれ、読み取れるのは片方だけです。

実務の手順は短いものです。コピーして貼ったら、送信前に先頭四文字と末尾四文字を画面と突き合わせる——この一手間で切り詰めも字形の置換も一度に捕まります。アドレス欄に URI を貼らない、自分が作っていない URI の金額を信用しない。QR を読むなら金額はゼロ扱いにして注文ページから打ち直し、八桁すべてを合わせる。0.13937044 は 0.1394 ではなく、100 USDT の注文では到着額のおよそ 0.3% の差になります。メモ必須の資産はそもそも読み取らず、アドレスとメモを別々にコピーし、メモは二度確認する——チェックサムのない唯一の欄だからです。そして QR をスクリーンショットしてチャットに流す行為こそ、93 ピクセルの事例が現実になる場所です。画像は残り、アドレスは残らないことがあります。 (XMR→USDT 出口ルート)

特殊な話ではありません。三つのエンコーダ、三つの壊れ方、その間にいて壊れた箇所が見えない人間。URI は金額を黙って落とし、クリップボードは幅のない文字を運び、QR は 200 ピクセルの箱に 37 モジュールを敷き詰める。解決は良いソフトだけではなく、この文字列がどの扉から出てきたかを知り、その扉が壊しうる部分を確認することです。自分で管理するウォレットから送り、返金先は同じチェーンに置く。一つだけ覚えるならこれです——画面のアドレスとウォレットのアドレスは、突き合わせるまでは別物です。

Frequently asked questions

アドレスはデバイス間でどんな三つの型で壊れますか?

URI、クリップボード、QR はそれぞれ文字列の別の部分を壊します。URI は単位を間違えたり金額を黙って落としたりし、クリップボードは U+200B のようなゼロ幅文字を混ぜることがあり(当サイトの検証器は実測した九形式すべてで拒否)、200 ピクセルの QR はアドレスが約 80 文字を超えて画像が半分以下に縮むと読み取り信頼性が急落します(37 モジュールは劣化画像で 9/20)。三経路が共通して守るのは、失ってはならない部分、つまりアドレス本体です。だから確認はいつも同じ——宛先を突き合わせ、金額は自分で入れ直す。

アドレス欄は bitcoin: や monero: で始まる URI を受け付けますか?

いいえ。実測では URI 接頭辞付きの変形は九形式すべてで拒否され、エラーは「not a Bitcoin address」のような形でした。通るのは裸のアドレスだけで、送信前にフロント側が前後の空白を trim します。ウォレットが URI を渡してきたら、scheme からクエリまでを落としてアドレスだけ残し、金額は注文ページから手入力してください。

QR の訂正レベルを上げると、長いアドレスが読み取りにくくなるのはなぜですか?

ピクセル予算が固定だからです。200 CSS ピクセルの描画で、95 文字のアドレスを L から M に上げるとシンボルは 37 から 41 モジュールに増え、1 モジュールは 5.41 から 4.88 ピクセルに縮みます。劣化画像の試行では、これで成功が 9/20 から 2/20 に落ちました。訂正はモジュールが十分大きいときだけ意味を持ちます。その閾値より下では、冗長性はより小さな点で支払われるので、取引は逆方向に働きます。

Keep reading

All articles →

Ready to swap?

No account · No KYC · No email

Exchange now
URI・クリップボード・QR:アドレスは受け渡しの途中でこう壊れる — VeilSwap