Skip to main content

libid_contracts/bindings/
identity.rs

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