# 关于 ENS 的键帽字符

By [🦄️🦄️🦄️](https://paragraph.com/@0xc952fe149b640097054cfa53caf7ac2bfd0162c5) · 2022-09-27

---

背景知识
====

什么是键帽字符
-------

键帽字符是一串数字 emoji，比如：

1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣0⃣️🔟#️⃣\*️⃣

什么是完全合格的 emoji
--------------

> 起初，Unicode 字符中的 emoji 表情符号只有黑色。而随着 emoji 表情符号的逐渐发展，其中一些 emoji 开始有了彩色版本。然而，有些字体能支持显示完整的 emoji，有些字体不支持。这使同一个 emoji 在不同的平台上有了多种形式 。

以上资料引用自 [这里](https://www.emojiall.com/zh-hans/help-qualified-status)

测试调研
====

完全合格的键帽字符
---------

完全合格的键帽 1️⃣ 的 URI encode 后的结果是：

    encodeURI('1️⃣')
    '1%EF%B8%8F%E2%83%A3'
    

`%EF%B8%8F` 是 [变体选择器](https://www.emojiall.com/zh-hans/emoji/%EF%B8%8F) ，意思是将它前面的字符以 emoji 的形式展示

`%E2%83%A3` 是 [结合封闭键帽](https://www.emojiall.com/zh-hans/emoji/%E2%83%A3) ，专用于隔离键帽 emoji

输入法生成的键帽字符
----------

我用 mac 自带的输入法，拿到的 1⃣️ 的 URI encode 结果是：

    encodeURI('1⃣️')
    '1%E2%83%A3%EF%B8%8F'
    

由上面的结论可知，发现输入法生成的 **变体选择器** 和 **结合封闭键帽** 顺序是反的。自然两者也就不相等了：

    '1⃣' === '1️⃣'
    false
    

塞入多个变体选择器
---------

然后再多塞几个 **变体选择器** ，并与完全合格的键帽比较：

    decodeURI('1%EF%B8%8F%E2%83%A3%EF%B8%8F')
    '1️⃣️'
    '1️⃣️' === '1️⃣'
    false
    

_结论： 可以一直塞多个_ **_变体选择器_** _而不影响最终的视觉展示_

twitter 搜索测试
------------

在 twitter 上搜索 1️⃣2️⃣3️⃣.eth 的结果

下图的 1️⃣ 是塞了两个 **变体选择器** 的搜索结果，发现什么也搜不到：

> [https://twitter.com/search?q=1%EF%B8%8F%EF%B8%8F%E2%83%A32%EF%B8%8F%E2%83%A33%EF%B8%8F%E2%83%A3.eth&src=typed\_query&f=top](https://twitter.com/search?q=1%EF%B8%8F%EF%B8%8F%E2%83%A32%EF%B8%8F%E2%83%A33%EF%B8%8F%E2%83%A3.eth&src=typed_query&f=top)

![](https://storage.googleapis.com/papyrus_images/f1c3b20035ee7053325e06da73261e1cc58955b3c418862cabc635a43ef06377.png)

下图的 1️⃣ 就是完全合格的键帽 emoji 的 搜索结果：

> [https://twitter.com/search?q=1%EF%B8%8F%E2%83%A32%EF%B8%8F%E2%83%A33%EF%B8%8F%E2%83%A3.eth&src=typed\_query&f=top](https://twitter.com/search?q=1%EF%B8%8F%E2%83%A32%EF%B8%8F%E2%83%A33%EF%B8%8F%E2%83%A3.eth&src=typed_query&f=top)

![](https://storage.googleapis.com/papyrus_images/1eec9c8aba4ce7d5e733babcf9308c06c8900eec4ba5cef21927f1f4e278eea0.png)

浏览器地址栏显示测试
----------

### chrome

> [https://www.emojiall.com/zh-hans/emoji/0%EF%B8%8F%E2%83%A3](https://www.emojiall.com/zh-hans/emoji/0%EF%B8%8F%E2%83%A3)

![](https://storage.googleapis.com/papyrus_images/30cfa76dd28301694c2bf92f6fa0fc1d53e1d98e5fc2a496ee3a667900da471f.png)

> [https://www.emojiall.com/zh-hans/emoji/0%E2%83%A3](https://www.emojiall.com/zh-hans/emoji/0%E2%83%A3)

![](https://storage.googleapis.com/papyrus_images/70ae2439467e5a441270069b5fd769b8ae14442d6c0fc09a0f32ca7de60ddb38.png)

### safari

![](https://storage.googleapis.com/papyrus_images/47c03cebcea29138f8652c0d67e64aa12b57f8818331abd5143633595c0ab3eb.png)

![](https://storage.googleapis.com/papyrus_images/a0e52bd29086832cc7b326fb008c5344e5bad168939ddd53317c75b908dcca13.png)

_结论： 要想在浏览器地址栏里优雅地显示 emoji，则需要使用不合格表示法，即干掉里面的_ **_变体选择器_**

### 引申

那如果我们再用不合格的键帽在 twitter 上搜索呢，居然也能搜索出结果来：

> [https://twitter.com/search?q=1%E2%83%A32%E2%83%A33%E2%83%A3.eth&src=typed\_query&f=top](https://twitter.com/search?q=1%E2%83%A32%E2%83%A33%E2%83%A3.eth&src=typed_query&f=top)

![](https://storage.googleapis.com/papyrus_images/045288d5ffe15908d848094c681ea4d5dbb8842a1605d0a8c6d06a5c2c6b87db.png)

但搜索出的内容是不一样的，因为我复制了不合格搜索结果的 1⃣2⃣3⃣.eth 与完全合格的 1️⃣2️⃣3️⃣.eth 是不一样的：

    '1⃣2⃣3⃣.eth' === '1️⃣2️⃣3️⃣.eth'
    false
    

也就是说，上面的场景下，在 twitter 里面显示的 1️⃣2️⃣3️⃣.eth 和 1️⃣2️⃣3️⃣.eth 是两种不一样的 ENS，只是视觉上是一样的而已

ens domain
----------

无论搜索的是 `1️⃣2️⃣3️⃣.eth` 还是 `1⃣2⃣3⃣.eth` 展示的结果都是：[https://app.ens.domains/name/1%E2%83%A32%E2%83%A33%E2%83%A3.eth/details](https://app.ens.domains/name/1%E2%83%A32%E2%83%A33%E2%83%A3.eth/details)

![](https://storage.googleapis.com/papyrus_images/4fa51ea3e0e6befda90ac1485e7337d0a00e254fa39c46de7de9bf0c1becc8e3.png)

_结论： 所以从 ens.domain 上注册的都是不合格的键帽，但反而却被 ens 官方强制扶正，认定为这种兼容性最差的键帽格式才是正统。详情参见_ [_1️⃣2️⃣3️⃣.eth 的注册交易_](https://etherscan.io/tx/0x43d2afe7ba1e39f83142ce63c7d4497cc0a55f19b04f23bf336ae4049f13d48a) _：_

![](https://storage.googleapis.com/papyrus_images/cd19d71ba3b1606ffaa1ac8a07b699484f8481331e28602f44d7bd5645caf520.png)

opensea
-------

只能搜索到不合格的 `1⃣2⃣3⃣.eth` ，而且用的字体正好是不兼容这种不合格的 emoji 的，所以显示很奇怪：

![](https://storage.googleapis.com/papyrus_images/42c94d5dc72c713c6dfb5ad6507661202b2be02365ecf91c19d3206246b09cd7.png)

![](https://storage.googleapis.com/papyrus_images/a7918dfc08bb1c16d9f4f89abc6b8948a5fb8f6c6da7dbab85af9347781fc58f.png)

etherscan
---------

目前两种 NFT 都已被注册

完全合格的 `1️⃣2️⃣3️⃣.eth` ：[https://etherscan.io/nft/0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85/65500681650595787883240792993076550848892653777790200001583287977258956136539](https://etherscan.io/nft/0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85/65500681650595787883240792993076550848892653777790200001583287977258956136539)

不合格的 `1⃣2⃣3⃣.eth`：[https://etherscan.io/nft/0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85/33324163493671772743162099004136274185101712000141871054933792093926554750217](https://etherscan.io/nft/0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85/33324163493671772743162099004136274185101712000141871054933792093926554750217)

有趣的是细究这笔完全合格的 `1️⃣2️⃣3️⃣.eth` 注册 [交易](https://etherscan.io/tx/0x2627bf1c2164d7c0593c48641b322c05f6aa20b81482a43209cdceb490cf3b31)，会发现调用者显然也是直接与合约交互的，因为在 ens.domain 里面注册的话只会调用 `registerWithConfig` ，而这笔交易为了省点 gas 费直接使用的 `register` 接口（应该是个比较熟悉 ENS 的程序员）。

![](https://storage.googleapis.com/papyrus_images/6eb5aef7e273183d7c1b23caf6fc8fffdc435d295f2bb9cb984cc9edf6b2abbe.png)

![](https://storage.googleapis.com/papyrus_images/09e0e4f7d7445b313efb9b8877c841ab5785cd8e3f6da4b647c56ae4d395652b.png)

结论
==

可惜啊，opensea/nftgo/nftscan/metamask 等众多 dapp 都没有自建数据库，都是直接使用的 ensdomain 的接口，在这个中心化接口里将兼容性最差的 `1⃣2⃣3⃣.eth` 给强行规定为正版，兼容性更好的 `1️⃣2️⃣3️⃣.eth` 则被成了盗版，非常 web3 了。

> 猜测 ENS 选择兼容性最差的旧版的 emoji 应该是完全从域名的角度考虑（而不是从账户名角度）的，因为兼容性最好的键帽 emoji （包含在 2016 年的 [emoji 3.0](https://www.emojiall.com/zh-hans/emoji-version/3.0) 中）确实是无法与 punycode（2003 年的 [rfc3492](https://www.rfc-editor.org/rfc/rfc3492)） 互转的。
> 
> 这个带来的问题就是，以后会出现两个在聊天窗口里长得一模一样的带 emoji 的链接，点进去却发现是完全不一样的网站内容，极其容易导致视觉欺骗的钓鱼案例。这反而与 IDNA 标准的初衷违背

---

*Originally published on [🦄️🦄️🦄️](https://paragraph.com/@0xc952fe149b640097054cfa53caf7ac2bfd0162c5/ens-2)*
