Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ERC: Distinguishable base256emoji Addresses #354

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
373 changes: 373 additions & 0 deletions ERCS/erc-7673.md
@@ -0,0 +1,373 @@
---
eip: 7673
title: Distinguishable base256emoji Addresses
description: Depict Account Addresses As A String of Emoji
author: William Morriss (@wjmelements)
discussions-to: https://ethereum-magicians.org/t/erc-7673-distinguishable-account-addresses/19461
status: Draft
type: Standards Track
category: ERC
created: 2024-04-01
---

## Abstract

Introduce base256emoji for use as the primary input and display for account addresses in all user interfaces.

## Motivation

Human users often fail to distinguish between long strings of hexadecimal characters, especially when they match at the beginning and at the end.
This makes hexadecimal strings a poor format for human-readable account addresses.
The problem is being exploited by several spoofing strategies that mine similar addresses and spoof [ERC-20](./eip-20.md) Transfer events with the goal of tricking the end user into copying the wrong recipient address.
These address spoofing attacks have mislead tens of thousands of ether, and countless other tokens.
Spoofers flooding the network with fake Transfer events waste network resources and complicate blockchain accounting.
Improving the distinguishability of addresses will reduce the incentives for this behavior.

## Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

User interfaces:
- SHALL depict account addresses as a base256emoji string instead of hexadecimal.
- SHALL accept base256emoji strings as input for user-supplied account address parameters.
- SHOULD recognize and interpret strings of exactly 20 consecutive emoji as addresses when all of them are valid base256emoji.

### base256emoji encoding table

| Emoji | Unicode codepoint | Byte Value |
|:-:|:-:|:-:|
| 🚀 | U+1F680 | 0 |
| 🪐 | U+1FA90 | 1 |
| ☄ | U+2604 | 2 |
| 🛰 | U+1F6F0 | 3 |
| 🌌 | U+1F30C | 4 |
| 🌑 | U+1F311 | 5 |
| 🌒 | U+1F312 | 6 |
| 🌓 | U+1F313 | 7 |
| 🌔 | U+1F314 | 8 |
| 🌕 | U+1F315 | 9 |
| 🌖 | U+1F316 | 10 |
| 🌗 | U+1F317 | 11 |
| 🌘 | U+1F318 | 12 |
| 🌍 | U+1F30D | 13 |
| 🌏 | U+1F30F | 14 |
| 🌎 | U+1F30E | 15 |
| 🐉 | U+1F409 | 16 |
| ☀ | U+2600 | 17 |
| 💻 | U+1F4BB | 18 |
| 🖥 | U+1F5A5 | 19 |
| 💾 | U+1F4BE | 20 |
| 💿 | U+1F4BF | 21 |
| 😂 | U+1F602 | 22 |
| ❤ | U+2764 | 23 |
| 😍 | U+1F60D | 24 |
| 🤣 | U+1F923 | 25 |
| 😊 | U+1F60A | 26 |
| 🙏 | U+1F64F | 27 |
| 💕 | U+1F495 | 28 |
| 😭 | U+1F62D | 29 |
| 😘 | U+1F618 | 30 |
| 👍 | U+1F44D | 31 |
| 😅 | U+1F605 | 32 |
| 👏 | U+1F44F | 33 |
| 😁 | U+1F601 | 34 |
| 🔥 | U+1F525 | 35 |
| 🥰 | U+1F970 | 36 |
| 💔 | U+1F494 | 37 |
| 💖 | U+1F496 | 38 |
| 💙 | U+1F499 | 39 |
| 😢 | U+1F622 | 40 |
| 🤔 | U+1F914 | 41 |
| 😆 | U+1F606 | 42 |
| 🙄 | U+1F644 | 43 |
| 💪 | U+1F4AA | 44 |
| 😉 | U+1F609 | 45 |
| ☺ | U+263A | 46 |
| 👌 | U+1F44C | 47 |
| 🤗 | U+1F917 | 48 |
| 💜 | U+1F49C | 49 |
| 😔 | U+1F614 | 50 |
| 😎 | U+1F60E | 51 |
| 😇 | U+1F607 | 52 |
| 🌹 | U+1F339 | 53 |
| 🤦 | U+1F926 | 54 |
| 🎉 | U+1F389 | 55 |
| 💞 | U+1F49E | 56 |
| ✌ | U+270C | 57 |
| ✨ | U+2728 | 58 |
| 🤷 | U+1F937 | 59 |
| 😱 | U+1F631 | 60 |
| 😌 | U+1F60C | 61 |
| 🌸 | U+1F338 | 62 |
| 🙌 | U+1F64C | 63 |
| 😋 | U+1F60B | 64 |
| 💗 | U+1F497 | 65 |
| 💚 | U+1F49A | 66 |
| 😏 | U+1F60F | 67 |
| 💛 | U+1F49B | 68 |
| 🙂 | U+1F642 | 69 |
| 💓 | U+1F493 | 70 |
| 🤩 | U+1F929 | 71 |
| 😄 | U+1F604 | 72 |
| 😀 | U+1F600 | 73 |
| 🖤 | U+1F5A4 | 74 |
| 😃 | U+1F603 | 75 |
| 💯 | U+1F4AF | 76 |
| 🙈 | U+1F648 | 77 |
| 👇 | U+1F447 | 78 |
| 🎶 | U+1F3B6 | 79 |
| 😒 | U+1F612 | 80 |
| 🤭 | U+1F92D | 81 |
| ❣ | U+2763 | 82 |
| 😜 | U+1F61C | 83 |
| 💋 | U+1F48B | 84 |
| 👀 | U+1F440 | 85 |
| 😪 | U+1F62A | 86 |
| 😑 | U+1F611 | 87 |
| 💥 | U+1F4A5 | 88 |
| 🙋 | U+1F64B | 89 |
| 😞 | U+1F61E | 90 |
| 😩 | U+1F629 | 91 |
| 😡 | U+1F621 | 92 |
| 🤪 | U+1F92A | 93 |
| 👊 | U+1F44A | 94 |
| 🥳 | U+1F973 | 95 |
| 😥 | U+1F625 | 96 |
| 🤤 | U+1F924 | 97 |
| 👉 | U+1F449 | 98 |
| 💃 | U+1F483 | 99 |
| 😳 | U+1F633 | 100 |
| ✋ | U+270B | 101 |
| 😚 | U+1F61A | 102 |
| 😝 | U+1F61D | 103 |
| 😴 | U+1F634 | 104 |
| 🌟 | U+1F31F | 105 |
| 😬 | U+1F62C | 106 |
| 🙃 | U+1F643 | 107 |
| 🍀 | U+1F340 | 108 |
| 🌷 | U+1F337 | 109 |
| 😻 | U+1F63B | 110 |
| 😓 | U+1F613 | 111 |
| ⭐ | U+2B50 | 112 |
| ✅ | U+2705 | 113 |
| 🥺 | U+1F97A | 114 |
| 🌈 | U+1F308 | 115 |
| 😈 | U+1F608 | 116 |
| 🤘 | U+1F918 | 117 |
| 💦 | U+1F4A6 | 118 |
| ✔ | U+2714 | 119 |
| 😣 | U+1F623 | 120 |
| 🏃 | U+1F3C3 | 121 |
| 💐 | U+1F490 | 122 |
| ☹ | U+2639 | 123 |
| 🎊 | U+1F38A | 124 |
| 💘 | U+1F498 | 125 |
| 😠 | U+1F620 | 126 |
| ☝ | U+261D | 127 |
| 😕 | U+1F615 | 128 |
| 🌺 | U+1F33A | 129 |
| 🎂 | U+1F382 | 130 |
| 🌻 | U+1F33B | 131 |
| 😐 | U+1F610 | 132 |
| 🖕 | U+1F595 | 133 |
| 💝 | U+1F49D | 134 |
| 🙊 | U+1F64A | 135 |
| 😹 | U+1F639 | 136 |
| 🗣 | U+1F5E3 | 137 |
| 💫 | U+1F4AB | 138 |
| 💀 | U+1F480 | 139 |
| 👑 | U+1F451 | 140 |
| 🎵 | U+1F3B5 | 141 |
| 🤞 | U+1F91E | 142 |
| 😛 | U+1F61B | 143 |
| 🔴 | U+1F534 | 144 |
| 😤 | U+1F624 | 145 |
| 🌼 | U+1F33C | 146 |
| 😫 | U+1F62B | 147 |
| ⚽ | U+26BD | 148 |
| 🤙 | U+1F919 | 149 |
| ☕ | U+2615 | 150 |
| 🏆 | U+1F3C6 | 151 |
| 🤫 | U+1F92B | 152 |
| 👈 | U+1F448 | 153 |
| 😮 | U+1F62E | 154 |
| 🙆 | U+1F646 | 155 |
| 🍻 | U+1F37B | 156 |
| 🍃 | U+1F343 | 157 |
| 🐶 | U+1F436 | 158 |
| 💁 | U+1F481 | 159 |
| 😲 | U+1F632 | 160 |
| 🌿 | U+1F33F | 161 |
| 🧡 | U+1F9E1 | 162 |
| 🎁 | U+1F381 | 163 |
| ⚡ | U+26A1 | 164 |
| 🌞 | U+1F31E | 165 |
| 🎈 | U+1F388 | 166 |
| ❌ | U+274C | 167 |
| ✊ | U+270A | 168 |
| 👋 | U+1F44B | 169 |
| 😰 | U+1F630 | 170 |
| 🤨 | U+1F928 | 171 |
| 😶 | U+1F636 | 172 |
| 🤝 | U+1F91D | 173 |
| 🚶 | U+1F6B6 | 174 |
| 💰 | U+1F4B0 | 175 |
| 🍓 | U+1F353 | 176 |
| 💢 | U+1F4A2 | 177 |
| 🤟 | U+1F91F | 178 |
| 🙁 | U+1F641 | 179 |
| 🚨 | U+1F6A8 | 180 |
| 💨 | U+1F4A8 | 181 |
| 🤬 | U+1F92C | 182 |
| ✈ | U+2708 | 183 |
| 🎀 | U+1F380 | 184 |
| 🍺 | U+1F37A | 185 |
| 🤓 | U+1F913 | 186 |
| 😙 | U+1F619 | 187 |
| 💟 | U+1F49F | 188 |
| 🌱 | U+1F331 | 189 |
| 😖 | U+1F616 | 190 |
| 👶 | U+1F476 | 191 |
| 🥴 | U+1F974 | 192 |
| ▶ | U+25B6 | 193 |
| ➡ | U+27A1 | 194 |
| ❓ | U+2753 | 195 |
| 💎 | U+1F48E | 196 |
| 💸 | U+1F4B8 | 197 |
| ⬇ | U+2B07 | 198 |
| 😨 | U+1F628 | 199 |
| 🌚 | U+1F31A | 200 |
| 🦋 | U+1F98B | 201 |
| 😷 | U+1F637 | 202 |
| 🕺 | U+1F57A | 203 |
| ⚠ | U+26A0 | 204 |
| 🙅 | U+1F645 | 205 |
| 😟 | U+1F61F | 206 |
| 😵 | U+1F635 | 207 |
| 👎 | U+1F44E | 208 |
| 🤲 | U+1F932 | 209 |
| 🤠 | U+1F920 | 210 |
| 🤧 | U+1F927 | 211 |
| 📌 | U+1F4CC | 212 |
| 🔵 | U+1F535 | 213 |
| 💅 | U+1F485 | 214 |
| 🧐 | U+1F9D0 | 215 |
| 🐾 | U+1F43E | 216 |
| 🍒 | U+1F352 | 217 |
| 😗 | U+1F617 | 218 |
| 🤑 | U+1F911 | 219 |
| 🌊 | U+1F30A | 220 |
| 🤯 | U+1F92F | 221 |
| 🐷 | U+1F437 | 222 |
| ☎ | U+260E | 223 |
| 💧 | U+1F4A7 | 224 |
| 😯 | U+1F62F | 225 |
| 💆 | U+1F486 | 226 |
| 👆 | U+1F446 | 227 |
| 🎤 | U+1F3A4 | 228 |
| 🙇 | U+1F647 | 229 |
| 🍑 | U+1F351 | 230 |
| ❄ | U+2744 | 231 |
| 🌴 | U+1F334 | 232 |
| 💣 | U+1F4A3 | 233 |
| 🐸 | U+1F438 | 234 |
| 💌 | U+1F48C | 235 |
| 📍 | U+1F4CD | 236 |
| 🥀 | U+1F940 | 237 |
| 🤢 | U+1F922 | 238 |
| 👅 | U+1F445 | 239 |
| 💡 | U+1F4A1 | 240 |
| 💩 | U+1F4A9 | 241 |
| 👐 | U+1F450 | 242 |
| 📸 | U+1F4F8 | 243 |
| 👻 | U+1F47B | 244 |
| 🤐 | U+1F910 | 245 |
| 🤮 | U+1F92E | 246 |
| 🎼 | U+1F3BC | 247 |
| 🥵 | U+1F975 | 248 |
| 🚩 | U+1F6A9 | 249 |
| 🍎 | U+1F34E | 250 |
| 🍊 | U+1F34A | 251 |
| 👼 | U+1F47C | 252 |
| 💍 | U+1F48D | 253 |
| 📣 | U+1F4E3 | 254 |
| 🥂 | U+1F942 | 255 |

## Rationale

Previous attempts to reduce spoofing and other copy errors such as [ERC-55](./eip-55.md) have not reduced the number of characters in an address.
Any base-256 standard would achieve this goal but emoji were chosen to maximize human-distinguishability.
Multiple base-256 emoji encodings have been proposed.
The base256emoji encoding was chosen due to its acceptance into the multibase repository.

This standard does not also recommend base256emoji for use in depicting other bytestrings such as transaction hashes and calldata.
Transaction hashes are not yet being spoofed.
Calldata is best decoded via the appropriate ABI.
By only using base256emoji for addresses, addresses can be easily noticed among other information.

## Backwards Compatibility

Using the encoding table, the base256emoji encoding can be transcoded into hexadecimal and vice-versa.

## Test Cases
| base256emoji | ERC-55 |
|:-:|:-:|
|🚀🚀🚀🚀🚀🚀😀💓🥴💣👻🙌🙈🤢😥☹🌏💩🍎💕|`0x0000000000004946c0e9F43F4Dee607b0eF1fA1c`|
|🚀🚀🚀🚀🚀🚀💸🎊💡🌿🚩🔥📌🙂💙❄🛰💩🤝⭐|`0x000000000000c57CF0A1f923d44527e703F1ad70`|
|☀☀☀☀☀❤🌊🌖❌💀✔🌎🎈❌💞🛰💗😅❓☄|`0x111111111117dC0aa78b770fA6A738034120C302`|
|👍🤫😋✊🤪😞🤐👶😭❤👉🚩💔🌱🤝🌊💚🪐🚩😐|`0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984`|
|😆🌎✅✨👋😜💛☺😶👋🐸🤩🌔🙌✋🤤⭐🍑☹⚡|`0x2a0f713aA953442EacA9EA47083f656170e67BA4`|
|🔥🤬🌔😝😞🙄👌💢🗣🌍✨😙🐾😡😑🤘💸😂😤🔵|`0x23B608675a2B2fB1890d3ABBd85c5775c51691d5`|
|🗣😅😞✨🤷😆🌟🐷🌷👶☝🪐🥀🖥🤟🐉💀💪😏❄|`0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7`|
|🥴😆😰✌🤟🔥📣🎵🌖🌏😡🎶💙🐸🍒🌔😱🤘🍀➡|`0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`|
|▶🌻😥👏💘😛💐💨❄💸😂😪😝🤤🐸💻😟☝🍃🥺|`0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72`|


## Reference Implementation

```python3
to_emoji = [
'🚀', '🪐', '☄', '🛰', '🌌', '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘', '🌍', '🌏', '🌎',
'🐉', '☀', '💻', '🖥', '💾', '💿', '😂', '❤', '😍', '🤣', '😊', '🙏', '💕', '😭', '😘', '👍',
'😅', '👏', '😁', '🔥', '🥰', '💔', '💖', '💙', '😢', '🤔', '😆', '🙄', '💪', '😉', '☺', '👌',
'🤗', '💜', '😔', '😎', '😇', '🌹', '🤦', '🎉', '💞', '✌', '✨', '🤷', '😱', '😌', '🌸', '🙌',
'😋', '💗', '💚', '😏', '💛', '🙂', '💓', '🤩', '😄', '😀', '🖤', '😃', '💯', '🙈', '👇', '🎶',
'😒', '🤭', '❣', '😜', '💋', '👀', '😪', '😑', '💥', '🙋', '😞', '😩', '😡', '🤪', '👊', '🥳',
'😥', '🤤', '👉', '💃', '😳', '✋', '😚', '😝', '😴', '🌟', '😬', '🙃', '🍀', '🌷', '😻', '😓',
'⭐', '✅', '🥺', '🌈', '😈', '🤘', '💦', '✔', '😣', '🏃', '💐', '☹', '🎊', '💘', '😠', '☝',
'😕', '🌺', '🎂', '🌻', '😐', '🖕', '💝', '🙊', '😹', '🗣', '💫', '💀', '👑', '🎵', '🤞', '😛',
'🔴', '😤', '🌼', '😫', '⚽', '🤙', '☕', '🏆', '🤫', '👈', '😮', '🙆', '🍻', '🍃', '🐶', '💁',
'😲', '🌿', '🧡', '🎁', '⚡', '🌞', '🎈', '❌', '✊', '👋', '😰', '🤨', '😶', '🤝', '🚶', '💰',
'🍓', '💢', '🤟', '🙁', '🚨', '💨', '🤬', '✈', '🎀', '🍺', '🤓', '😙', '💟', '🌱', '😖', '👶',
'🥴', '▶', '➡', '❓', '💎', '💸', '⬇', '😨', '🌚', '🦋', '😷', '🕺', '⚠', '🙅', '😟', '😵',
'👎', '🤲', '🤠', '🤧', '📌', '🔵', '💅', '🧐', '🐾', '🍒', '😗', '🤑', '🌊', '🤯', '🐷', '☎',
'💧', '😯', '💆', '👆', '🎤', '🙇', '🍑', '❄', '🌴', '💣', '🐸', '💌', '📍', '🥀', '🤢', '👅',
'💡', '💩', '👐', '📸', '👻', '🤐', '🤮', '🎼', '🥵', '🚩', '🍎', '🍊', '👼', '💍', '📣', '🥂'
]
from_emoji = {emoji: "{0:02x}".format(i) for i, emoji in enumerate(to_emoji)}

def encode_address(hexadecimal_address):
if len(hexadecimal_address) != 42 or not hexadecimal_address.startswith('0x'):
return None
return ''.join([to_emoji[int(hexadecimal_address[i:i+2], 16)] for i in range(2, 42, 2)])


def decode_address(emoji_address):
# In python, these unicode characters all have a len() of 1
if len(emoji_address) != 20:
return None
try:
return '0x' + ''.join(from_emoji[emoji] for emoji in emoji_address)
except IndexError:
return None
```

## Security Considerations

With the base256emoji encoding, addresses use half as many characters.
The characters used are more distinguishable.
This squares the difficulty of generating similar addresses, making address spoofing impractical.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).