1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
//! Bindings for the identity-names stack (`solidity/contracts/identity/`):
//! `IdentityNames`.
/// Bindings for `identity/IdentityNames.sol`.
///
/// `Rules` mirrors `HandleNormalizer.Rules` — the normalization rules the
/// contract stores per platform. Platform ids are `keccak256` of the
/// platform's domain string.
#[allow(clippy::too_many_arguments, unused_attributes)]
mod names_inner {
use alloy::sol;
sol! {
#[sol(rpc, abi)]
interface IdentityNames {
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Rules {
uint16 maxLength;
bool stripLeadingAt;
bool isEmail;
bool allowUnderscore;
bool allowHyphen;
}
/// One account a wallet proved, as its list reports it. `handle`
/// is the one the account proved most recently, and
/// `handleCurrent` says whether the handle node still points back
/// at this account: it stops doing so when another account proves
/// the same handle, and the string stays as the last thing the
/// account was known as.
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Account {
bytes32 platformId;
string userId;
string handle;
bool handleCurrent;
}
function initialize(address owner_) external;
/// The wallet that proved an account id, and when.
function byId(bytes32 idNode) external view returns (address owner, uint64 observedAt);
/// The wallet that last proved a handle node, and when. A zero
/// owner: nobody holds it.
function byHandle(bytes32 handleNode) external view returns (address owner, uint64 observedAt);
/// The operation domain a claim's authorization names.
function CLAIM_IDENTITY_DOMAIN() external view returns (bytes32);
function owner() external view returns (address);
function pendingOwner() external view returns (address);
function transferOwnership(address newOwner) external;
function acceptOwnership() external;
/// Always reverts; the contract declares it `pure`.
function renounceOwnership() external pure;
/// The keyspace half: what a handle on this platform means. It
/// does not vary by proof version — two versions normalizing
/// differently would put one handle on two nodes.
function setPlatform(bytes32 platformId, Rules calldata rules) external;
/// Which contract holds the Supported Version Set. Registering a
/// version is that contract's call, not this one's.
function setProofVerifier(address verifier) external;
function proofVerifier() external view returns (address);
/// The one write. The contract does not know what `payload` is:
/// it names a platform and this chain's verifier version for it,
/// and the Proof Verifier routes the bytes to the one contract
/// that decodes them. The value attached must equal `quoteBind`
/// for the same pair exactly.
function bind(bytes32 platformId, uint16 verifierVersion, bytes calldata payload, bool publishName) external payable;
function quoteBind(bytes32 platformId, uint16 verifierVersion) external view returns (uint256);
function digestSpent(bytes32 digest) external view returns (bool);
function unpublish(bytes32 platformId) external;
function resolveId(bytes32 platformId, string calldata userId) external view returns (address);
function resolveHandle(bytes32 platformId, string calldata handle) external view returns (address);
/// The handle's current owner, and whether `userId` resolves to
/// that same wallet.
function resolvePair(bytes32 platformId, string calldata handle, string calldata userId) external view returns (address wallet, bool idAgrees);
function reverseOf(address wallet, bytes32 platformId) external view returns (string memory);
function primaryOf(address wallet, bytes32 platformId) external view returns (string memory);
/// The platform's rules as configured now, for local normalization.
function rulesOf(bytes32 platformId) external view returns (Rules memory);
/// Whether `bind` can bind a holder on this platform
/// now: a keyspace, and a Proof Verifier that verifies it.
function acceptsBindings(bytes32 platformId) external view returns (bool);
/// `keccak256` of the normalized handle: what `HandleEscrow.deposit`
/// takes. Reverts `UnknownPlatform` or `UnusableHandle`.
function handleHashOf(bytes32 platformId, string calldata handle) external view returns (bytes32 handleHash);
/// The node a handle keys to now; reverts as `handleHashOf` does.
function nodeOf(bytes32 platformId, string calldata handle) external view returns (bytes32 handleNode);
/// The node of a handle given as its hash, as `bind` binds it.
function nodeOfHash(bytes32 platformId, bytes32 handleHash) external pure returns (bytes32);
/// How many accounts a wallet holds, on every platform together.
function accountCount(address wallet) external view returns (uint256);
/// A page of the accounts a wallet holds, on every platform
/// together: the indices `[from, from + limit)`, counted from
/// zero and clipped to the list. Order
/// is arbitrary and changes when an account leaves the list, so
/// a reader that needs every account reads `accountCount` and
/// the pages in one block.
function accountsOf(address wallet, uint256 from, uint256 limit) external view returns (Account[] memory);
/// Carries the ceremony version that proved the binding -- logged,
/// never stored, because nothing on chain acts on it and an
/// operator asking which bindings a version touched reads the log.
/// What the ceremony authenticated beyond the binding rides on
/// `CeremonyBound` instead.
event IdentityBound(
address indexed owner,
bytes32 indexed idNode,
bytes32 indexed handleNode,
bytes32 platformId,
string userId,
string handle,
uint64 observedAt,
bool published,
uint16 ceremonyVersion
);
/// A platform with no keyspace, or one nothing verifies and on
/// which nothing was ever bound.
error UnknownPlatform(bytes32 platformId);
/// Text the platform's rules refuse; `problem` is a
/// `HandleNormalizer.Problem`.
error UnusableHandle(uint8 problem);
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
// What `bind` can revert with: its own refusals, and the
// normalizer's, for a proved handle the rules refuse.
error ZeroAddress();
error ForeignOperationDomain(bytes32 operationDomain);
error DigestAlreadySpent(bytes32 digest);
error BadTransactionData(uint256 length);
error WrongBindValue(uint256 required, uint256 provided);
error WrongFeeValue(uint256 required, uint256 provided);
error NoncanonicalFee(uint256 amount, address receiver);
error FeeTransferFailed(address receiver, uint256 amount);
error NotProofTarget(address proved, address caller);
error NoObservationTime();
error NoUserId();
error StaleProof(uint64 observedAt, uint64 known);
error EmptyHandle();
error HandleTooLong();
error BadCharacter();
error BadShape();
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
error ReentrancyGuardReentrantCall();
event HandleRetired(bytes32 indexed platformId, bytes32 indexed handleNode, address indexed owner);
event PlatformConfigured(bytes32 indexed platformId);
event ProofVerifierConfigured(address verifier);
/// The service fee a binding's own Authorized Transaction Data named
/// was delivered. Emitted only when there is one.
event BindFeePaid(bytes32 indexed authorizationDigest, address indexed receiver, uint256 amount);
event NameUnpublished(address indexed owner, bytes32 indexed platformId);
/// The OAuth client a ceremony authenticated. Nothing stores it, so
/// "which application produced these bindings" is answerable only
/// from this log.
event CeremonyBound(
bytes32 indexed authorizationDigest,
address indexed owner,
bytes32 indexed platformId,
bytes clientIdentifier
);
}
}
}
pub use names_inner::IdentityNames;
#[cfg(test)]
mod tests {
use super::names_inner::IdentityNames;
use crate::bindings::drift::assert_binding_matches_artifact;
/// Inherited upgrade and initializer ABI, left to `proxy::IUUPSUpgradeable`.
const OMITTED: &[&str] = &[
"error AddressEmptyCode(address)",
"error ERC1967InvalidImplementation(address)",
"error ERC1967NonPayable()",
"error FailedCall()",
"error InvalidInitialization()",
"error NotInitializing()",
"error UUPSUnauthorizedCallContext()",
"error UUPSUnsupportedProxiableUUID(bytes32)",
"event Initialized(uint64)",
"event Upgraded(address)",
"function UPGRADE_INTERFACE_VERSION()",
"function proxiableUUID()",
"function upgradeToAndCall(address,bytes)",
];
#[test]
fn the_binding_matches_the_artifact_abi() {
assert_binding_matches_artifact(
"IdentityNames",
"IdentityNames",
&IdentityNames::abi::contract(),
OMITTED,
);
}
}