mirror of https://github.com/status-im/EIPs.git
Automatically merged updates to draft EIP(s) 1484
Hi, I'm a bot! This change was automatically merged because: - It only modifies existing Draft or Last Call EIP(s) - The PR was approved or written by at least one author of each modified EIP - The build is passing
This commit is contained in:
parent
2fc626317d
commit
6f0683552f
313
EIPS/eip-1484.md
313
EIPS/eip-1484.md
|
@ -14,65 +14,74 @@ requires: 191
|
|||
A protocol for aggregating digital identity information that's broadly interoperable with existing, proposed, and hypothetical future digital identity standards.
|
||||
|
||||
## Abstract
|
||||
This EIP proposes an identity management and aggregation framework on the Ethereum blockchain. It allows entities to claim an identity via a singular `Identity Registry` smart contract, associate this `Identity` with Ethereum addresses in a variety of meaningful ways, and use it to interface with smart contracts. This enables arbitrarily complex identity-related functionality. Notably (among other features) this proposal is [DID compliant](https://github.com/hydrogen-dev/ERC-1484/blob/master/best-practices/DID-Method.md), can natively support [ERC-725](https://github.com/hydrogen-dev/ERC-1484/tree/master/contracts/examples/Resolvers/ERC725) and [ERC-1056](https://github.com/hydrogen-dev/ERC-1484/tree/master/contracts/examples/Resolvers/ERC1056) identities, and lays a robust foundation for [meta-transactions](https://github.com/hydrogen-dev/ERC-1484/tree/master/contracts/examples/Providers/MetaTransactions).
|
||||
This EIP proposes an identity management and aggregation framework on the Ethereum blockchain. It allows entities to claim an `Identity` via a singular `Identity Registry` smart contract, associate it with Ethereum addresses in a variety of meaningful ways, and use it to interact with smart contracts. This enables arbitrarily complex identity-related functionality. Notably (among other features) ERC-1484 `Identities`: are self-sovereign, can natively support [ERC-725](https://github.com/hydrogen-dev/ERC-1484/tree/master/contracts/examples/Resolvers/ERC725) and [ERC-1056](https://github.com/hydrogen-dev/ERC-1484/tree/master/contracts/examples/Resolvers/ERC1056) identities, are [DID compliant](https://github.com/hydrogen-dev/ERC-1484/blob/master/best-practices/DID-Method.md), and can be fully powered by [meta-transactions](https://github.com/hydrogen-dev/ERC-1484/tree/master/contracts/examples/Providers/MetaTransactions).
|
||||
|
||||
## Motivation
|
||||
Emerging identity standards and related frameworks proposed by the Ethereum community (including ERCs/EIPs [725](https://github.com/ethereum/EIPs/issues/725), [735](https://github.com/ethereum/EIPs/issues/735), [780](https://github.com/ethereum/EIPs/issues/780), [1056](https://github.com/ethereum/EIPs/issues/1056), etc.) define and instrumentalize digital identity in a variety of ways. As existing approaches mature, new standards emerge, and isolated, non-standard approaches to identity develop, managing multiple identities will become increasingly burdensome and involve the unnecessary duplication of work.
|
||||
Emerging identity standards and related frameworks proposed by the Ethereum community (including ERCs/EIPs [725](https://github.com/ethereum/EIPs/issues/725), [735](https://github.com/ethereum/EIPs/issues/735), [780](https://github.com/ethereum/EIPs/issues/780), [1056](https://github.com/ethereum/EIPs/issues/1056), etc.) define and instrumentalize digital identity in a variety of ways. As existing approaches mature, new standards emerge, and isolated, non-standard approaches to identity develop, coordinating on identity will become increasingly burdensome for blockchain users and developers, and involve the unnecessary duplication of work.
|
||||
|
||||
The proliferation of on-chain identity solutions can be traced back to the fact that each codifies a notion of identity and links it to specific aspects of Ethereum (claims protocols, per-identity smart contracts, signature verification schemes, etc.). This proposal eschews that approach, instead introducing a protocol layer in between the Ethereum network and individual identity applications. This solves identity management and interoperability challenges by enabling any identity-driven application to leverage an un-opinionated identity management protocol.
|
||||
|
||||
## Definitions
|
||||
- `Identity Registry`: A single smart contract which is the hub for all `Identities`. The primary responsibility of the `Registry` is to enforce a global namespace for `Identities`, which are individually denominated by Ethereum Identification Numbers (EINs).
|
||||
- `Identity Registry`: A single smart contract which is the hub for all `Identities`. The primary responsibility of the `Registry` is to define and enforce the rules of a global namespace for `Identities`, which are individually denominated by Ethereum Identification Numbers (EINs).
|
||||
|
||||
- `Identity`: A data structure containing all the information relevant to a particular identity. They are denominated by EINs (incrementing `uint`s), which are unique but uninformative.
|
||||
- `Identity`: A data structure containing all the core information relevant to an identity, namely: a `Recovery Address`, an `Associated Addresses` set, a `Providers` set, and a `Resolvers` set. `Identities` are denominated by EINs (incrementing `uint` identifiers starting at 1), which are unique but otherwise uninformative. Each `Identity` is a Solidity struct:
|
||||
|
||||
- `Associated Address`: An Ethereum address publicly associated with an `Identity`. In order for an address to become an `Associated Address` for an `Identity`, the `Identity` must produce signed messages from the candidate address and an existing `Associated Address` indicating this intent. Identities can remove an `Associated Address` by producing an appropriately signed message indicating intent to disassociate itself from the `Identity`. An address may only be an `Associated Address` for one `Identity` at any given time.
|
||||
```solidity
|
||||
struct Identity {
|
||||
address recoveryAddress;
|
||||
AddressSet.Set associatedAddresses;
|
||||
AddressSet.Set providers;
|
||||
AddressSet.Set resolvers;
|
||||
}
|
||||
```
|
||||
|
||||
- `Provider`: An Ethereum address (typically but not by definition a smart contract) authorized to add and remove `Associated Addresses`, `Providers`, and `Resolvers` from `Identities` who have authorized the `Provider` to act on their behalf. `Providers` exist to facilitate user adoption, and make it easier to manage `Identities`.
|
||||
- `Associated Address`: An Ethereum address publicly associated with an `Identity`. In order for an address to become an `Associated Address`, an `Identity` must either transact from or produce an appropriately signed message from the candidate address and an existing `Associated Address`, indicating intent to associate. An `Associated Address` can be removed from an `Identity` by transacting/producing a signature indicating intent to disassociate. A given address may only be an `Associated Address` for one `Identity` at any given time.
|
||||
|
||||
- `Provider`: An Ethereum address (typically but not by definition a smart contract) authorized to act on behalf of `Identities` who have authorized them to do so. This includes but is not limited to managing the `Associated Address`, `Provider`, and `Resolver` sets for an `Identity`. `Providers` exist to facilitate user adoption by making it easier to manage `Identities`.
|
||||
|
||||
- `Resolver`: A smart contract containing arbitrary information pertaining to `Identities`. A resolver may implement an identity standard, such as ERC-725, or may consist of a smart contract leveraging or declaring identifying information about `Identities`. These could be simple attestation structures or more sophisticated financial dApps, social media dApps, etc. Each `Resolver` added to an `Identity` makes the `Identity` more informative.
|
||||
|
||||
- `Recovery Address`: An Ethereum address (either an account or smart contract) that can be used to recover lost identities as outlined in the [Recovery](#recovery) section.
|
||||
- `Recovery Address`: An Ethereum address (either an account or smart contract) that can be used to recover lost `Identities` as outlined in the [Recovery](#recovery) section.
|
||||
|
||||
- `Poison Pill`: In the event of irrecoverable control of an `Identity`, the `Poison Pill` offers a contingency measure to permanently disable the `Identity`. It removes all `Associated Addresses` and `Providers` while preserving the `Identity` (and optionally, `Resolvers`). Evidence of the existence of the `Identity` persists, while control over the `Identity` is nullified.
|
||||
- `Destruction`: In the event of irrecoverable loss of control of an `Identity`, `Destruction` is a contingency measure to permanently disable the `Identity`. It removes all `Associated Addresses`, `Providers`, and optionally `Resolvers` while preserving the `Identity`. Evidence of the existence of the `Identity` persists, while control over the `Identity` is nullified.
|
||||
|
||||
## Specification
|
||||
A digital identity in this proposal can be viewed as an omnibus account, containing more information about an identity than any individual identity application could. This omnibus identity is resolvable to an unlimited number of sub-identities called `Resolvers`. This allows an atomic entity, the `Identity`, to be resolvable to abstract data structures, the `Resolvers`. `Resolvers` recognize `Identities` by any of their `Associated Addresses`, or by their `EIN`.
|
||||
|
||||
The protocol revolves around claiming an `Identity` and managing `Associated Addresses` and `Resolvers`. Identities delegate much of this responsibility to one or more `Providers`. `Provider` smart contracts or addresses may add and remove `Resolvers` and `Providers` indiscriminately, but may only add and remove `Associated Addresses` with the appropriate permissions.
|
||||
The protocol revolves around claiming an `Identity` and managing `Associated Addresses`, `Providers` and `Resolvers`. Identities can delegate much or all of this responsibility to one or more `Providers`, or perform it directly from an `Associated Address`. `Associated Addresses`/`Providers` may add and remove `Resolvers` and `Providers` indiscriminately. `Associated Addresses` may only be added or removed with the appropriate permission.
|
||||
|
||||
### Identity Registry
|
||||
The `Identity Registry` contains functionality to create new `Identities` and for existing `Identities` to manage their `Providers`, `Associated Addresses`, and `Resolvers`. It is important to note that this registry fundamentally requires transactions for every aspect of building out an `Identity`. However, recognizing the importance of accessibility to dApps and identity applications, we empower `Providers` to build out `Identities` on the behalf of users, without requiring users to pay gas costs. An example of this pattern, often referred to as a meta transactions, can be [seen in the reference implementation](https://github.com/hydrogen-dev/ERC-1484/tree/master/contracts/examples/Providers/MetaTransactions).
|
||||
The `Identity Registry` contains functionality to create new `Identities` and for existing `Identities` to manage their `Associated Addresses`, `Providers`, and `Resolvers`. It is important to note that this registry fundamentally requires transactions for every aspect of building out an `Identity`. However, recognizing the importance of accessibility to dApps and identity applications, we empower `Providers` to build out `Identities` on the behalf of users, without requiring users to pay gas costs. An example of this pattern, often referred to as a meta transactions, can be [seen in the reference implementation](https://github.com/hydrogen-dev/ERC-1484/tree/master/contracts/examples/Providers/MetaTransactions).
|
||||
|
||||
Due to the fact that multiple addresses can be associated with a given identity (though not the reverse), `Identities` are denominated by `EIN`s. This `uint` identifier can be encoded in QR format or transformed into more user-intuitive formats, such as a `string`, in registries at the `Provider` or `Resolver` level.
|
||||
Due to the fact that multiple addresses can be associated with a given identity (though not the reverse), `Identities` are denominated by `EIN`. This `uint` identifier can be encoded in QR format or mapped to more user-friendly formats, such as a `string`, in registries at the `Provider` or `Resolver` level.
|
||||
|
||||
### Address Management
|
||||
The address management function consists of trustlessly connecting multiple user-owned `Associated Addresses` to an `Identity`. It does not give special status to any particular `Associated Address`, rather leaving this specification to identity applications built on top of the protocol - for instance, `management`, `action`, `claim` and `encryption` keys denominated in the ERC-725 standard, or `identifiers` and `delegates` as denominated in ERC-1056. This allows a user to access common identity data from multiple wallets while still:
|
||||
The address management function consists of trustlessly connecting multiple user-owned `Associated Addresses` to an `Identity`. It does not give special status to any particular `Associated Address`, rather leaving this (optional) specification to identity applications built on top of the protocol - for instance, `management`, `action`, `claim` and `encryption` keys denominated in the ERC-725 standard, or `identifiers` and `delegates` as denominated in ERC-1056. This allows a user to access common identity data from multiple wallets while still:
|
||||
|
||||
- retaining flexibility to interact with contracts outside of their identity
|
||||
- retaining the ability to interact with contracts outside of their identity
|
||||
- taking advantage of address-specific permissions established at the application layer of a user's identity.
|
||||
|
||||
Trustlessness in the address management function is achieved through a signature and verification scheme that requires two signatures - one from an address already within the registry and one from the address to be claimed. Importantly, the transaction need not come from the original user, which allows third parties (entities, governments, etc.) to bear the overhead of creating core identities. To prevent a compromised `Associated Address` from unilaterally removing other `Associated Addresses`, removal of an `Associated Address` also requires a signature from the address to be removed.
|
||||
Trustlessness in the address management function is achieved through a robust permissioning scheme. To add an `Associated Address` to an `Identity`, implicit permission from a transaction sender or explicit permission from a signature is required from 1) an address already within the registry and 2) an address to be claimed. Importantly, the transaction need not come from any particular address, as long as permission is established, which allows not only users but third parties (companies, governments, etc.) to bear the overhead of managing identities. To prevent a compromised `Associated Address` from unilaterally removing other `Associated Addresses`, it's only possible to remove an `Associated Address` by transacting or producing a signature from it.
|
||||
|
||||
All signatures required in ERC-1484 are designed per the [ERC-191](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-191.md) v0 specification. To avoid replay attacks, all signatures must include a timestamp within a rolling lagged window of the current `block.timestamp`. For more information, see this [best practices document](https://github.com/hydrogen-dev/ERC-1484/blob/master/best-practices/VerifyingSignatures.md) in the reference implementation.
|
||||
|
||||
### Provider Management
|
||||
While the protocol allows users to directly call identity management functions, it also aims to be more robust and future-proof by allowing `Providers`, typically arbitrary smart contracts, to perform identity management functions on a user's behalf. A `Provider` set by an identity can perform address management and resolver management functions by passing a user's `EIN` in function calls. In order to prevent `Identities` from adding an initial `Provider` that does not implement the functionality to add other `Providers` (this leaving the `Identity` 'stuck'), identities may add `Providers` directly from the `Identity Registry`.
|
||||
While the protocol allows users to directly call identity management functions, it also aims to be more robust and future-proof by allowing `Providers`, typically smart contracts, to perform identity management functions on a user's behalf. A `Provider` set by an `Identity` can perform address management and resolver management functions by passing a user's `EIN` in function calls.
|
||||
|
||||
### Resolver Management
|
||||
A `Resolver` is any smart contract that encodes information which resolves to an `Identity`. We remain agnostic about the specific information that can be encoded in a resolver and the functionality that this enables. The existence of resolvers is primarily what makes this ERC an identity *protocol* rather than an identity *application*. `Resolvers` resolve abstract data in smart contracts to an atomic entity, the `Identity`.
|
||||
A `Resolver` is any smart contract that encodes information which resolves to an `Identity`. We remain agnostic about the specific information that can be encoded in a resolver and the functionality that this enables. The existence of `Resolvers` is primarily what makes this ERC an identity *protocol* rather than an identity *application*. `Resolvers` resolve abstract data in smart contracts to an atomic entity, the `Identity`.
|
||||
|
||||
### Recovery
|
||||
The specification includes a `Recovery Address` for instances when users lose control over an `Associated Address`. Upon `Identity` creation, the public `Recovery Address` is passed as a parameter by the creator. Recovery functionality is triggered in three scenarios:
|
||||
If users lose control over an `Associated Address`, the `Recovery Address` provides a fallback mechanism. Upon `Identity` creation, a `Recovery Address` is passed as a parameter by the creator. Recovery functionality is triggered in three scenarios:
|
||||
|
||||
**1. Changing Recovery Address**: If a recovery key is lost, a `Provider` can [triggerRecoveryAddressChangeFor](#triggerRecoveryAddressChangeFor) through a `Provider`. To prevent malicious behavior from someone who has gained control of an `Associated Address` or `Provider` and is changing the `Recovery Address` to one under their control, this action triggers a 14 day challenge period during which the old `Recovery Address` may reject the change. If the `Recovery Address` does not reject the change within 14 days, the `Recovery Address` is changed. Old `Recovery Address` reject the change by can dispute the change request by calling [triggerRecovery](#triggerrecovery).
|
||||
**1. Changing Recovery Address**: If a recovery key is lost, an `Associated Address`/`Provider` can [triggerRecoveryAddressChange](#triggerRecoveryAddressChange)/[triggerRecoveryAddressChangeFor](#triggerRecoveryAddressChangeFor). To prevent malicious behavior from someone who has gained control of an `Associated Address` or `Provider` and is changing the `Recovery Address` to one under their control, this action triggers a 14 day challenge period during which the old `Recovery Address` may reject the change by [triggering recovery](#triggerRecovery). If the `Recovery Address` does not reject the change within 14 days, the `Recovery Address` is changed.
|
||||
|
||||
**2. Recovery**: Recovery occurs when a user recognizes that an `Associated Address` or the `Recovery Address` belonging to the user is lost or stolen. In this instance a `Recovery Address` must call [triggerRecovery](#triggerrecovery). This removes all `Associated Addresses` and `Providers` from the corresponding `Identity` and replaces them with an address passed in the function call. The `Identity` and associated `Resolvers` maintain integrity. The user is now responsible for adding the appropriate un-compromised addresses back to their `Identity`.
|
||||
**2. Recovery**: Recovery occurs when a user recognizes that an `Associated Address` or the `Recovery Address` belonging to the user is lost or stolen. In this instance the `Recovery Address` must call [triggerRecovery](#triggerRecovery). This removes all `Associated Addresses` and `Providers` from the corresponding `Identity` and replaces them with an address passed in the function call. The `Identity` and associated `Resolvers` maintain integrity. The user is now responsible for adding the appropriate un-compromised addresses back to their `Identity`.
|
||||
|
||||
*Importantly, the `Recovery Address` can be a user-controlled wallet or another address such as a multisig wallet or smart contract. This allows for arbitrarily sophisticated recovery logic! This includes the potential for recovery to be fully compliant with standards such as [DID](https://decentralized.id/).*
|
||||
*Importantly, the `Recovery Address` can be a user-controlled wallet or another address, such as a multisig wallet or smart contract. This allows for arbitrarily sophisticated recovery logic! This includes the potential for recovery to be fully compliant with standards such as [DID](https://decentralized.id/).*
|
||||
|
||||
**3. Poison Pill**
|
||||
The Recovery scheme offers considerable power to a `Recovery Address`; accordingly, the `Poison Pill` is a nuclear option to combat malicious control over an `Identity` when a `Recovery Address` is compromised. If a malicious actor compromises a user's `Recovery Address` and triggers recovery, any address removed in the `Recovery` process can call [triggerPoisonPill](#triggerPoisonPill) within 14 days to permanently disable the `Identity`. The user would then need to create a new `Identity`, and would be responsible for engaging in recovery schemes for any identity applications built in the `Resolver` or `Provider` layers.
|
||||
**3. Destruction**
|
||||
The Recovery scheme offers considerable power to a `Recovery Address`; accordingly, `Destruction` is a nuclear option to combat malicious control over an `Identity` when a `Recovery Address` is compromised. If a malicious actor compromises a user's `Recovery Address` and triggers recovery, any address removed in the `Recovery` process can call [triggerDestruction](#triggerDestruction) within 14 days to permanently disable the `Identity`. The user would then need to create a new `Identity`, and would be responsible for engaging in recovery schemes for any identity applications built in the `Resolver` or `Provider` layers.
|
||||
|
||||
#### Alternative Recovery Considerations
|
||||
We considered many possible alternatives when devising the Recovery process outlined above. We ultimately selected the scheme that was most un-opinionated, modular, and consistent with the philosophy behind the `Associated Address`, `Provider`, and `Resolver` components. Still, we feel that it is important to highlight some of the other recovery options we considered, to provide a rationale as to how we settled on what we did.
|
||||
|
@ -87,12 +96,12 @@ This approach would allow any `Associated Address` to destroy an `Identity` when
|
|||
- It would increase the frequency of recovery requests to identity applications due to its unforgiving nature.
|
||||
|
||||
**Alternative 2: Unilateral Address Removal via Providers**
|
||||
This would allow `Providers` to remove an `Associated Address` without a signature from said address. This implementation would allow `Providers` to include arbitrarily sophisticated schemes for removing a rogue address - for instance, multi-sig requirements, centralized off-chain verification, user controlled master addresses, deferral to a jurisdictional contract, and more. To prevent a compromised `Associated Address` from simply setting a malicious `Provider` to remove un-compromised addresses, it would have required a waiting period between when a `Provider` is set and when they would be able to remove an `Associated Address`. We dismissed this approach because we felt it placed too high of a burden on `Providers`. If a `Provider` offered a sophisticated range of functionality to a user, but post-deployment a threat was found in the Recovery logic of the provider, `Provider`-specific infrastructure would need to be rebuilt. We also considered including a flag that would allow a user to decide whether or not a `Provider` may remove `Associated Addresses` unilaterally. Ultimately, we concluded that only allowing removal of `Associated Addresses` via the `Recovery Address` enables equally sophisticated recovery logic while separating the functionality from `Providers`, leaving less room for users to relinquish control to potentially flawed implementations.
|
||||
This would allow `Associated Addresses`/`Providers` to remove `Associated Addresses` without a signature from said address. This implementation would allow `Providers` to include arbitrarily sophisticated schemes for removing a rogue address - for instance, multi-sig requirements, centralized off-chain verification, user controlled master addresses, deferral to a jurisdictional contract, and more. To prevent a compromised `Associated Address` from simply setting a malicious `Provider` to remove un-compromised addresses, it would have required a waiting period between when a `Provider` is set and when they would be able to remove an `Associated Address`. We dismissed this approach because we felt it placed too high of a burden on `Providers`. If a `Provider` offered a sophisticated range of functionality to a user, but post-deployment a threat was found in the Recovery logic of the provider, `Provider`-specific infrastructure would need to be rebuilt. We also considered including a flag that would allow a user to decide whether or not a `Provider` may remove `Associated Addresses` unilaterally. Ultimately, we concluded that only allowing removal of `Associated Addresses` via the `Recovery Address` enables equally sophisticated recovery logic while separating the functionality from `Providers`, leaving less room for users to relinquish control to potentially flawed implementations.
|
||||
|
||||
## Rationale
|
||||
We find that at a protocol layer, identities should not rely on specific claim or attestation structures, but should instead be a part of a trustless framework upon which arbitrarily sophisticated claim and attestation structures may be built.
|
||||
|
||||
The main criticism of existing identity solutions is that they're overly restrictive. We aim to limit requirements, keep identities modular and future-proof, and remain un-opinionated regarding any functionality a particular identity component may have. This proposal gives users the option to interact on the blockchain using an arbitrarily robust `Identity` rather than just an address.
|
||||
The main criticism of existing identity solutions is that they're overly restrictive. We aim to limit requirements, keep identities modular and future-proof, and remain un-opinionated regarding any functionality a particular identity component may have. This proposal gives users the option to interact on the blockchain using an robust `Identity` rather than just an address.
|
||||
|
||||
## Implementation
|
||||
**The reference implementation for ERC-1484 may be found in [hydrogen-dev/ERC-1484](https://github.com/hydrogen-dev/ERC-1484).**
|
||||
|
@ -151,52 +160,82 @@ Returns the `recoveryAddress`, `associatedAddresses`, `providers` and `resolvers
|
|||
|
||||
```solidity
|
||||
function getIdentity(uint ein) public view
|
||||
returns (address recoveryAddress, address[] associatedAddresses, address[] providers, address[] resolvers);
|
||||
returns (
|
||||
address recoveryAddress,
|
||||
address[] memory associatedAddresses, address[] memory providers, address[] memory resolvers
|
||||
);
|
||||
```
|
||||
|
||||
#### createIdentity
|
||||
|
||||
Creates an `Identity`, setting the `Provider` to the `msg.sender`. Returns the `EIN` of the new `Identity`.
|
||||
Creates an `Identity`, setting the `msg.sender` as the sole `Associated Address`. Returns the `EIN` of the new `Identity`.
|
||||
|
||||
```solidity
|
||||
function createIdentity(address recoveryAddress, address provider, address[] resolvers) public returns (uint ein);
|
||||
function createIdentity(address recoveryAddress, address[] memory providers, address[] memory resolvers)
|
||||
public returns (uint ein);
|
||||
```
|
||||
|
||||
Triggers event: [IdentityCreated](#identitycreated)
|
||||
|
||||
#### createIdentityDelegated
|
||||
|
||||
Preforms the same logic as `createIdentity`, but is called by a `Provider`. This function requires a signature for the `associatedAddress` to confirm their consent.
|
||||
Preforms the same logic as `createIdentity`, but can be called by any address. This function requires a signature from the `associatedAddress` to ensure their consent.
|
||||
|
||||
```solidity
|
||||
function createIdentityDelegated(
|
||||
address recoveryAddress, address associatedAddress, address[] resolvers,
|
||||
address recoveryAddress, address associatedAddress, address[] memory providers, address[] memory resolvers,
|
||||
uint8 v, bytes32 r, bytes32 s, uint timestamp
|
||||
) public returns (uint ein);
|
||||
)
|
||||
public returns (uint ein);
|
||||
```
|
||||
|
||||
Triggers event: [IdentityCreated](#identitycreated)
|
||||
|
||||
#### addAssociatedAddress
|
||||
|
||||
Adds the `addressToAdd` to the `EIN` of the `approvingAddress`. The `msg.sender` must be either of the `approvingAddress` or the `addressToAdd`, and the signature must be from the other one.
|
||||
|
||||
```solidity
|
||||
function addAssociatedAddress(
|
||||
address approvingAddress, address addressToAdd, uint8 v, bytes32 r, bytes32 s, uint timestamp
|
||||
)
|
||||
public
|
||||
```
|
||||
|
||||
Triggers event: [AssociatedAddressAdded](#associatedaddressadded)
|
||||
|
||||
#### addAssociatedAddressDelegated
|
||||
|
||||
Adds the `addressToAdd` to the `EIN` of the `approvingAddress`. Requires signatures from both the `approvingAddress` and the `addressToAdd`.
|
||||
|
||||
```solidity
|
||||
function addAssociatedAddressDelegated(
|
||||
address approvingAddress, address addressToAdd, uint8[2] v, bytes32[2] r, bytes32[2] s, uint[2] timestamp
|
||||
) public;
|
||||
address approvingAddress, address addressToAdd,
|
||||
uint8[2] memory v, bytes32[2] memory r, bytes32[2] memory s, uint[2] memory timestamp
|
||||
)
|
||||
public
|
||||
```
|
||||
|
||||
Triggers event: [AssociatedAddressAdded](#associatedaddressadded)
|
||||
|
||||
#### removeAssociatedAddress
|
||||
|
||||
Removes the `msg.sender` as an `Associated Address` from its `EIN`.
|
||||
|
||||
```solidity
|
||||
function removeAssociatedAddress() public;
|
||||
```
|
||||
|
||||
Triggers event: [AssociatedAddressRemoved](#associatedaddressremoved)
|
||||
|
||||
|
||||
#### removeAssociatedAddressDelegated
|
||||
|
||||
Removes the `addressToRemove` from its associated `EIN`. Requires a signature from the `addressToRemove`.
|
||||
|
||||
```solidity
|
||||
function removeAssociatedAddressDelegated(
|
||||
address addressToRemove, uint8 v, bytes32 r, bytes32 s, uint timestamp
|
||||
) public;
|
||||
function removeAssociatedAddressDelegated(address addressToRemove, uint8 v, bytes32 r, bytes32 s, uint timestamp)
|
||||
public;
|
||||
```
|
||||
|
||||
Triggers event: [AssociatedAddressRemoved](#associatedaddressremoved)
|
||||
|
@ -206,17 +245,17 @@ Triggers event: [AssociatedAddressRemoved](#associatedaddressremoved)
|
|||
Adds an array of `Providers` to the `Identity` of the `msg.sender`.
|
||||
|
||||
```solidity
|
||||
function addProviders(address[] providers) public;
|
||||
function addProviders(address[] memory providers) public;
|
||||
```
|
||||
|
||||
Triggers event: [ProviderAdded](#provideradded)
|
||||
|
||||
#### addProvidersFor
|
||||
|
||||
Preforms the same logic as `addProviders`, but is called by a `Provider`.
|
||||
Preforms the same logic as `addProviders`, but must be called by a `Provider`.
|
||||
|
||||
```solidity
|
||||
function addProvidersFor(uint ein, address[] providers) public;
|
||||
function addProvidersFor(uint ein, address[] memory providers) public;
|
||||
```
|
||||
|
||||
Triggers event: [ProviderAdded](#provideradded)
|
||||
|
@ -226,7 +265,7 @@ Triggers event: [ProviderAdded](#provideradded)
|
|||
Removes an array of `Providers` from the `Identity` of the `msg.sender`.
|
||||
|
||||
```solidity
|
||||
function removeProviders(address[] providers) public;
|
||||
function removeProviders(address[] memory providers) public;
|
||||
```
|
||||
|
||||
Triggers event: [ProviderRemoved](#providerremoved)
|
||||
|
@ -237,32 +276,62 @@ Triggers event: [ProviderRemoved](#providerremoved)
|
|||
Preforms the same logic as `removeProviders`, but is called by a `Provider`.
|
||||
|
||||
```solidity
|
||||
function removeProvidersFor(uint ein, address[] providers) public;
|
||||
function removeProvidersFor(uint ein, address[] memory providers) public;
|
||||
```
|
||||
|
||||
Triggers event: [ProviderRemoved](#providerremoved)
|
||||
|
||||
|
||||
#### addResolversFor
|
||||
#### addResolvers
|
||||
|
||||
Adds an array of `Resolvers` to the passed `EIN`. This must be called by a `Provider`.
|
||||
Adds an array of `Resolvers` to the `EIN` of the `msg.sender`.
|
||||
|
||||
```solidity
|
||||
function addResolversFor(uint ein, address[] resolvers) public;
|
||||
function addResolvers(address[] memory resolvers) public;
|
||||
```
|
||||
|
||||
Triggers event: [ResolverAdded](#resolveradded)
|
||||
|
||||
#### removeResolversFor
|
||||
#### addResolversFor
|
||||
|
||||
Removes an array of `Resolvers` from the passed `EIN`. This must be called by a `Provider`.
|
||||
Preforms the same logic as `addResolvers`, but must be called by a `Provider`.
|
||||
|
||||
```solidity
|
||||
function removeResolversFor(uint ein, address[] resolvers) public;
|
||||
function addResolversFor(uint ein, address[] memory resolvers) public;
|
||||
```
|
||||
|
||||
Triggers event: [ResolverAdded](#resolveradded)
|
||||
|
||||
#### removeResolvers
|
||||
|
||||
Removes an array of `Resolvers` from the `EIN` of the `msg.sender`.
|
||||
|
||||
```solidity
|
||||
function removeResolvers(address[] memory resolvers) public;
|
||||
```
|
||||
|
||||
Triggers event: [ResolverRemoved](#resolverremoved)
|
||||
|
||||
#### removeResolversFor
|
||||
|
||||
Preforms the same logic as `removeResolvers`, but must be called by a `Provider`.
|
||||
|
||||
```solidity
|
||||
function removeResolversFor(uint ein, address[] memory resolvers) public;
|
||||
```
|
||||
|
||||
Triggers event: [ResolverRemoved](#resolverremoved)
|
||||
|
||||
#### triggerRecoveryAddressChange
|
||||
|
||||
Initiates a change in the current `recoveryAddress` for the `EIN` of the `msg.sender`.
|
||||
|
||||
```solidity
|
||||
function triggerRecoveryAddressChange(address newRecoveryAddress) public;
|
||||
```
|
||||
|
||||
Triggers event: [RecoveryAddressChangeTriggered](#RecoveryAddressChangeTriggered)
|
||||
|
||||
#### triggerRecoveryAddressChangeFor
|
||||
|
||||
Initiates a change in the current `recoveryAddress` for a given `EIN`.
|
||||
|
@ -281,17 +350,18 @@ Triggers `EIN` recovery from the current `recoveryAddress`, or the old `recovery
|
|||
function triggerRecovery(uint ein, address newAssociatedAddress, uint8 v, bytes32 r, bytes32 s, uint timestamp) public;
|
||||
```
|
||||
|
||||
Triggers event: [RecoveryTriggered](#recoverytriggered)
|
||||
Triggers event: [RecoveryTriggered](#RecoveryTriggered)
|
||||
|
||||
#### triggerPoisonPill
|
||||
#### triggerDestruction
|
||||
|
||||
Triggers the poison pill on an `EIN`. This renders the `Identity` permanently unusable.
|
||||
Triggers destruction of an `EIN`. This renders the `Identity` permanently unusable.
|
||||
|
||||
```solidity
|
||||
function triggerPoisonPill(uint ein, address[] firstChunk, address[] lastChunk, bool clearResolvers) public;
|
||||
function triggerDestruction(uint ein, address[] memory firstChunk, address[] memory lastChunk, bool clearResolvers)
|
||||
public;
|
||||
```
|
||||
|
||||
Triggers event: [IdentityPoisoned](#IdentityPoisoned)
|
||||
Triggers event: [IdentityDestroyed](#IdentityDestroyed)
|
||||
|
||||
### Events
|
||||
|
||||
|
@ -301,8 +371,8 @@ MUST be triggered when an `Identity` is created.
|
|||
|
||||
```solidity
|
||||
event IdentityCreated(
|
||||
address indexed initiator, uint indexed ein,
|
||||
address recoveryAddress, address associatedAddress, address provider, address[] resolvers, bool delegated
|
||||
address indexed initiator, uint indexed ein,
|
||||
address recoveryAddress, address associatedAddress, address[] providers, address[] resolvers, bool delegated
|
||||
);
|
||||
```
|
||||
|
||||
|
@ -312,7 +382,7 @@ MUST be triggered when an address is added to an `Identity`.
|
|||
|
||||
```solidity
|
||||
event AssociatedAddressAdded(
|
||||
address indexed initiator, uint indexed ein, address approvingAddress, address addedAddress
|
||||
address indexed initiator, uint indexed ein, address approvingAddress, address addedAddress, bool delegated
|
||||
);
|
||||
```
|
||||
|
||||
|
@ -321,7 +391,7 @@ event AssociatedAddressAdded(
|
|||
MUST be triggered when an address is removed from an `Identity`.
|
||||
|
||||
```solidity
|
||||
event AssociatedAddressRemoved(address indexed initiator, uint indexed ein, address removedAddress);
|
||||
event AssociatedAddressRemoved(address indexed initiator, uint indexed ein, address removedAddress, bool delegated);
|
||||
```
|
||||
|
||||
#### ProviderAdded
|
||||
|
@ -345,7 +415,7 @@ event ProviderRemoved(address indexed initiator, uint indexed ein, address provi
|
|||
MUST be triggered when a resolver is added.
|
||||
|
||||
```solidity
|
||||
event ResolverAdded(address indexed initiator, uint indexed ein, address resolvers);
|
||||
event ResolverAdded(address indexed initiator, uint indexed ein, address resolvers, bool delegated);
|
||||
```
|
||||
|
||||
#### ResolverRemoved
|
||||
|
@ -353,7 +423,7 @@ event ResolverAdded(address indexed initiator, uint indexed ein, address resolve
|
|||
MUST be triggered when a resolver is removed.
|
||||
|
||||
```solidity
|
||||
event ResolverRemoved(address indexed initiator, uint indexed ein, address resolvers);
|
||||
event ResolverRemoved(address indexed initiator, uint indexed ein, address resolvers, bool delegated);
|
||||
```
|
||||
|
||||
#### RecoveryAddressChangeTriggered
|
||||
|
@ -362,7 +432,8 @@ MUST be triggered when a recovery address change is triggered.
|
|||
|
||||
```solidity
|
||||
event RecoveryAddressChangeTriggered(
|
||||
address indexed initiator, uint indexed ein, address oldRecoveryAddress, address newRecoveryAddress
|
||||
address indexed initiator, uint indexed ein,
|
||||
address oldRecoveryAddress, address newRecoveryAddress, bool delegated
|
||||
);
|
||||
```
|
||||
|
||||
|
@ -372,73 +443,91 @@ MUST be triggered when recovery is triggered.
|
|||
|
||||
```solidity
|
||||
event RecoveryTriggered(
|
||||
address indexed initiator, uint indexed ein, address[] oldAssociatedAddresses, address newAssociatedAddress
|
||||
address indexed initiator, uint indexed ein, address[] oldAssociatedAddresses, address newAssociatedAddress
|
||||
);
|
||||
```
|
||||
|
||||
#### IdentityPoisoned
|
||||
#### IdentityDestroyed
|
||||
|
||||
MUST be triggered when an `Identity` is poisoned.
|
||||
MUST be triggered when an `Identity` is destroyed.
|
||||
|
||||
```solidity
|
||||
event IdentityPoisoned(address indexed initiator, uint indexed ein, address recoveryAddress, bool resolversReset);
|
||||
event IdentityDestroyed(address indexed initiator, uint indexed ein, address recoveryAddress, bool resolversReset);
|
||||
```
|
||||
|
||||
### Solidity Interface
|
||||
```solidity
|
||||
interface ERC1484 {
|
||||
// Identity View Functions /////////////////////////////////////////////////////////////////////////////////////////
|
||||
function identityExists(uint ein) external view returns (bool);
|
||||
function hasIdentity(address _address) external view returns (bool);
|
||||
function getEIN(address _address) external view returns (uint ein);
|
||||
function isAssociatedAddressFor(uint ein, address _address) external view returns (bool);
|
||||
function isProviderFor(uint ein, address provider) external view returns (bool);
|
||||
function isResolverFor(uint ein, address resolver) external view returns (bool);
|
||||
function getIdentity(uint ein) external view
|
||||
returns (address recoveryAddress, address[] associatedAddresses, address[] providers, address[] resolvers);
|
||||
interface IdentityRegistryInterface {
|
||||
function isSigned(address _address, bytes32 messageHash, uint8 v, bytes32 r, bytes32 s)
|
||||
external pure returns (bool);
|
||||
|
||||
// Identity Management Functions ///////////////////////////////////////////////////////////////////////////////////
|
||||
function createIdentity(address recoveryAddress, address provider, address[] resolvers) external returns (uint ein);
|
||||
function createIdentityDelegated(
|
||||
address recoveryAddress, address associatedAddress, address[] resolvers,
|
||||
uint8 v, bytes32 r, bytes32 s, uint timestamp
|
||||
) external returns (uint ein);
|
||||
function addAssociatedAddressDelegated(
|
||||
address approvingAddress, address addressToAdd, uint8[2] v, bytes32[2] r, bytes32[2] s, uint[2] timestamp
|
||||
) external;
|
||||
function removeAssociatedAddressDelegated(
|
||||
address addressToRemove, uint8 v, bytes32 r, bytes32 s, uint timestamp
|
||||
) external;
|
||||
function addProviders(address[] providers) external;
|
||||
function addProvidersFor(uint ein, address[] providers) external;
|
||||
function removeProviders(address[] providers) external;
|
||||
function removeProvidersFor(uint ein, address[] providers) external;
|
||||
function addResolversFor(uint ein, address[] resolvers) external;
|
||||
function removeResolversFor(uint ein, address[] resolvers) external;
|
||||
// Identity View Functions /////////////////////////////////////////////////////////////////////////////////////////
|
||||
function identityExists(uint ein) external view returns (bool);
|
||||
function hasIdentity(address _address) external view returns (bool);
|
||||
function getEIN(address _address) external view returns (uint ein);
|
||||
function isAssociatedAddressFor(uint ein, address _address) external view returns (bool);
|
||||
function isProviderFor(uint ein, address provider) external view returns (bool);
|
||||
function isResolverFor(uint ein, address resolver) external view returns (bool);
|
||||
function getIdentity(uint ein) external view returns (
|
||||
address recoveryAddress,
|
||||
address[] memory associatedAddresses, address[] memory providers, address[] memory resolvers
|
||||
);
|
||||
|
||||
// Recovery Management Functions ///////////////////////////////////////////////////////////////////////////////////
|
||||
function triggerRecoveryAddressChangeFor(uint ein, address newRecoveryAddress) external;
|
||||
function triggerRecovery(uint ein, address newAssociatedAddress, uint8 v, bytes32 r, bytes32 s) external;
|
||||
function triggerPoisonPill(uint ein, address[] firstChunk, address[] lastChunk, bool clearResolvers) external;
|
||||
// Identity Management Functions ///////////////////////////////////////////////////////////////////////////////////
|
||||
function createIdentity(address recoveryAddress, address[] calldata providers, address[] calldata resolvers)
|
||||
external returns (uint ein);
|
||||
function createIdentityDelegated(
|
||||
address recoveryAddress, address associatedAddress, address[] calldata providers, address[] calldata resolvers,
|
||||
uint8 v, bytes32 r, bytes32 s, uint timestamp
|
||||
) external returns (uint ein);
|
||||
function addAssociatedAddress(
|
||||
address approvingAddress, address addressToAdd, uint8 v, bytes32 r, bytes32 s, uint timestamp
|
||||
) external;
|
||||
function addAssociatedAddressDelegated(
|
||||
address approvingAddress, address addressToAdd,
|
||||
uint8[2] calldata v, bytes32[2] calldata r, bytes32[2] calldata s, uint[2] calldata timestamp
|
||||
) external;
|
||||
function removeAssociatedAddress() external;
|
||||
function removeAssociatedAddressDelegated(address addressToRemove, uint8 v, bytes32 r, bytes32 s, uint timestamp)
|
||||
external;
|
||||
function addProviders(address[] calldata providers) external;
|
||||
function addProvidersFor(uint ein, address[] calldata providers) external;
|
||||
function removeProviders(address[] calldata providers) external;
|
||||
function removeProvidersFor(uint ein, address[] calldata providers) external;
|
||||
function addResolvers(address[] calldata resolvers) external;
|
||||
function addResolversFor(uint ein, address[] calldata resolvers) external;
|
||||
function removeResolvers(address[] calldata resolvers) external;
|
||||
function removeResolversFor(uint ein, address[] calldata resolvers) external;
|
||||
|
||||
// Events //////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
event IdentityCreated(
|
||||
address indexed initiator, uint indexed ein,
|
||||
address recoveryAddress, address associatedAddress, address provider, address[] resolvers, bool delegated
|
||||
);
|
||||
event AssociatedAddressAdded (address indexed initiator, uint indexed ein, address approvingAddress, address addedAddress);
|
||||
event AssociatedAddressRemoved (address indexed initiator, uint indexed ein, address removedAddress);
|
||||
event ProviderAdded (address indexed initiator, uint indexed ein, address provider, bool delegated);
|
||||
event ProviderRemoved (address indexed initiator, uint indexed ein, address provider, bool delegated);
|
||||
event ResolverAdded (address indexed initiator, uint indexed ein, address resolvers);
|
||||
event ResolverRemoved (address indexed initiator, uint indexed ein, address resolvers);
|
||||
event RecoveryAddressChangeTriggered(
|
||||
address indexed initiator, uint indexed ein, address oldRecoveryAddress, address newRecoveryAddress
|
||||
);
|
||||
event RecoveryTriggered(
|
||||
address indexed initiator, uint indexed ein, address[] oldAssociatedAddresses, address newAssociatedAddress
|
||||
);
|
||||
event IdentityPoisoned (address indexed initiator, uint indexed ein, address recoveryAddress, bool resolversReset);
|
||||
// Recovery Management Functions ///////////////////////////////////////////////////////////////////////////////////
|
||||
function triggerRecoveryAddressChange(address newRecoveryAddress) external;
|
||||
function triggerRecoveryAddressChangeFor(uint ein, address newRecoveryAddress) external;
|
||||
function triggerRecovery(uint ein, address newAssociatedAddress, uint8 v, bytes32 r, bytes32 s, uint timestamp)
|
||||
external;
|
||||
function triggerDestruction(
|
||||
uint ein, address[] calldata firstChunk, address[] calldata lastChunk, bool resetResolvers
|
||||
) external;
|
||||
|
||||
// Events //////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
event IdentityCreated(
|
||||
address indexed initiator, uint indexed ein,
|
||||
address recoveryAddress, address associatedAddress, address[] providers, address[] resolvers, bool delegated
|
||||
);
|
||||
event AssociatedAddressAdded(
|
||||
address indexed initiator, uint indexed ein, address approvingAddress, address addedAddress
|
||||
);
|
||||
event AssociatedAddressRemoved(address indexed initiator, uint indexed ein, address removedAddress);
|
||||
event ProviderAdded(address indexed initiator, uint indexed ein, address provider, bool delegated);
|
||||
event ProviderRemoved(address indexed initiator, uint indexed ein, address provider, bool delegated);
|
||||
event ResolverAdded(address indexed initiator, uint indexed ein, address resolvers);
|
||||
event ResolverRemoved(address indexed initiator, uint indexed ein, address resolvers);
|
||||
event RecoveryAddressChangeTriggered(
|
||||
address indexed initiator, uint indexed ein, address oldRecoveryAddress, address newRecoveryAddress
|
||||
);
|
||||
event RecoveryTriggered(
|
||||
address indexed initiator, uint indexed ein, address[] oldAssociatedAddresses, address newAssociatedAddress
|
||||
);
|
||||
event IdentityDestroyed(address indexed initiator, uint indexed ein, address recoveryAddress, bool resolversReset);
|
||||
}
|
||||
```
|
||||
|
||||
|
|
Loading…
Reference in New Issue