Skip to content
This repository was archived by the owner on Jan 24, 2021. It is now read-only.

Commit 0b10302

Browse files
committed
Initial code drop.
0 parents  commit 0b10302

8 files changed

+1532
-0
lines changed

README.md

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
Distinguished Format String
2+
===========================
3+
4+
This is a very rough outline of the inkling of an idea. Do not implement this
5+
yet.
6+
7+
8+
JSON-RPC Method
9+
---------------
10+
11+
eth_signFormattedString(address, [ formatString, ... ], paramTypes, paramValues)
12+
13+
- A UI should display the human-readable string as well as the address (reverse ENS lookup should be performed)
14+
- If multiple formatStrings are provided, the best matching string SHOULD be choosen,
15+
taking into account locale. If a coder is not locale-aware, it should choose the first string.
16+
- Once user-confirmed, the hash should be computed and signed and the signature returned
17+
18+
19+
eth_sendFormattedTransaction(address, [ formatString, ... ], signature, paramTypes, paramValues)
20+
21+
- A UI should display the human-readable string as well as the address (reverse ENS lookup should be performed)
22+
- If multiple formatStrings are provided, the best matching string SHOULD be choosen,
23+
taking into account locale. If a coder is not locale-aware, it should choose the first string.
24+
- The signature must match [ bytes32, ...paramTypes ]
25+
- Once user-confirmed, the hash should be computed and sent as a transaction
26+
27+
28+
Parameters
29+
----------
30+
31+
- target: Address (20 bytes)
32+
- format: Array of Format Strings
33+
- types: Array of type strings
34+
- values: Array of values
35+
36+
37+
Distinguished Pack Encoding Algorithm
38+
-------------------------------------
39+
40+
- All fixed length types are tightly packed
41+
i.e. a uint48 is packed into 6 bytes Big Endian
42+
- All dynamic types are prefixed with their length as a uint256 and then tightly packed
43+
i.e. The string "foo" is (32 + 3 bytes) long
44+
45+
Note: Cannot use standard ABIv2, as it contains pointers, so the bytes created can be
46+
implementation dependent
47+
48+
49+
Distingushed Hashing Bytes
50+
--------------------------
51+
52+
This is used to derive the bytes necessary for hashing.
53+
54+
FormatId = keccak256(
55+
keccak256(
56+
concat(sorted(format.map(string => id(string))))
57+
),
58+
id(
59+
types.join(",")
60+
)
61+
)
62+
63+
Preamble = keccak256(
64+
target,
65+
FormatId
66+
)
67+
68+
HashBytes = DistinguishPackEncoding([ bytes32, ...types ], [ Preamble, ...values])
69+
70+
Note: The Format can be computed at Solidity compile-time for most cases,
71+
including where the address may change.
72+
The Preamble can be computed at deployment-time for cases where even
73+
the target does not change.
74+
75+
76+
Metadata
77+
--------
78+
79+
Metadata is provided as key-value pairs, using the `\m{key=value}` format specifier
80+
within a string. The output string MUST NOT contain the metadata.
81+
82+
Metadata may be critical or non-critical. A critical key MUST begin with a capital
83+
letter after any leading underscore (_) and any coder which encounters a critical
84+
key it does not understand MUST fail. Non-critical keys which a coder does not
85+
understand may be silently ignored, or presented to the user another way.
86+
87+
Metadata may also be private or public. A private key MUST begin with an underscore (_)
88+
and is meant for application specific formatting. Public keys are maintained as a
89+
well-known set in this document or future expansions.
90+
91+
Within a given format string, the same metadata key may not be used more than once.
92+
93+
94+
Metadata Keys
95+
-------------
96+
97+
locale - the locale this format string represents; this may impact
98+
how numbers or dates are formatted in the format string or
99+
the choice of quote characters. A locale-aware coder SHOULD
100+
attempt to choose the most appropriate format string for the
101+
user's current locale. See ISO XXXX. (non-critical)
102+
Version - the version of the distinguished format string to use (critical)
103+
104+
105+
String Encoding
106+
---------------
107+
108+
All charcters in a Distinguished Format String MUST belong to the printable
109+
ASCII set (i.e. XXX).
110+
111+
To represent Unicode characters within a string the `\u{XXX}` format specifier
112+
may be used, and the value within the braces must be itself distinguished (i.e.
113+
no uneeded leading zeros).
114+
115+
116+
Substitution Sepcifiers
117+
-----------------------
118+
119+
A Substitution Format Specifier is of the form `${ expression, expression, ... }`, where *expression*
120+
is a series of functions and literals.
121+
122+
123+
Escape Sequences
124+
----------------
125+
126+
The `$$` escape sequence can be used to insert a `$` in the final string.
127+
128+
Within strings inside a Substitution Format Specifier, a `\"` can be used
129+
to insert a `"` in the string.
130+
131+
132+
Examples
133+
--------
134+
135+
eth_signFormatString(
136+
DAI_ADDRESS,
137+
[
138+
"\\m{locale=en}Hello! I allow sending $$${ formatUnits(atIndex(1), 18) (in DAI) to ${ atIndex(2) }.",
139+
"\\m{locale=fr}Allo! A ${ atIndex(2) }, je permitte $$${ formatUnits(atIndex(1), 18) (en DAI)"
140+
],
141+
[ "uint", "address" ],
142+
[ "0x1b9de674df070000", "0x1234" ]
143+
)
144+
145+
To English Users: (to DAI contract)
146+
"Hello! I allow sending $1.99 (in DAI) to 0x1234."
147+
148+
To French Users: (to DAI contract)
149+
"Bonjour! A 0x1234, je permitte $1,99 (en DAI)."
150+
151+
152+
eth_signFormatString(
153+
WISP_ADDRESS,
154+
[
155+
"Please co-sign a call to ${ sighash("transfer(address to, uint256 amount)") } to ${ atIndex(2) } with ${ atIndex(3) } WETH."
156+
],
157+
[ , "address", "uint256" ],
158+
[ , 0x1234, 1 ]
159+
)
160+
161+
162+
Notes:
163+
- Must validate all inputs match their types

0 commit comments

Comments
 (0)