diff --git a/EIPS/eip-725.md b/EIPS/eip-725.md index 8f10e69ea32a9c..8755537fd6cd58 100644 --- a/EIPS/eip-725.md +++ b/EIPS/eip-725.md @@ -1,55 +1,90 @@ --- eip: 725 -title: Proxy Account +title: ERC-725 Smart Contract Based Account author: Fabian Vogelsteller (@frozeman), Tyler Yasaka (@tyleryasaka) discussions-to: https://github.com/ethereum/EIPs/issues/725 status: Draft type: Standards Track category: ERC +requires: 165, 173 created: 2017-10-02 --- + ## Simple Summary -A standard interface for a simple proxy account. +A standard interface for a smart contract based account with attachable key value store. ## Abstract -The following describes standard functions for a unique identifiable proxy account to be used by humans, groups, organisations, objects and machines. The proxy has 2 abilities: (1) it can execute arbitrary contract calls, and (2) it can hold arbitrary data through a generic key/value store. One of these keys should hold the owner of the contract. The owner may be an address or a key manager contract for more complex management logic. Most importantly, this contract should be the reference point for a long-lasting identifiable profiles. +The following describes standard functions for a unique smart contract based account that can be used by humans, +groups, organisations, objects and machines. + +The standard is divided into two sub standards: + +`ERC725X`: +Can execute arbitrary smart contracts using and deploy other smart contracts. + +`ERC725Y`: +Can hold arbitrary data through a generic key/value store. ## Motivation -Standardizing a minimal interface for an proxy account allows third parties to interact with various proxy accounts contracts in a consistent manner. -the benefit is a persistent account that is independent from single keys and can attach an arbitrary amount of information to verifiy, or enhance the accounts purpose. +Standardizing a minimal interface for a smart contract based account allows any interface to operate through these account types. +Smart contact based accounts following this standard have the following advantages: + +- can hold any asset (native token, e.g. ERC20 like tokens) +- can execute any smart contract and deploy smart contracts +- have upgradeable security (through owner change, e.g. to a gnosis safe) +- are basic enough to work for for a long time +- are extensible though additional standardisation of the key/value data. +- can function as an owner/controller or proxy of other smart contracts + ## Specification +### ERC725X -### Methods +ERC165 identifier: `0x44c028fe` -#### owner +#### execute -Returns the current owner +Executes a call on any other smart contracts, transfers the blockchains native token, or deploys a new smart contract. +MUST only be called by the current owner of the contract. ```js -address public owner; +function execute(uint256 operationType, address to, uint256 value, bytes data) ``` -#### changeOwner +The `operationType` can execute the following operations: +- `0` for `call` +- `1` for `delegatecall` +- `2` for `create2` +- `3` for `create` + +Others may be added in the future. + +**Triggers Event:** [ContractCreated](#contractcreated) if a contract was created + +### Events + +#### ContractCreated -Changes the current owner. MUST only be called by the current owner of the contract. +MUST be triggered when `execute` creates a new contract using the `_operationType` `1`. ```js -function changeOwner(address _owner); +event ContractCreated(address indexed contractAddress) ``` -**Triggers Event:** [OwnerChanged](#ownerchanged) +### ERC725Y + +ERC165 identifier: `0x2bd57b73` #### getData Returns the data at the specified key. ```js -function getData(bytes32 _key) external view returns (bytes _value); +function getData(bytes32 key) external view returns(bytes value) ``` #### setData @@ -59,112 +94,109 @@ Sets the data at a specific key. MUST only be called by the current owner of the **Triggers Event:** [DataChanged](#datachanged) ```js -function setData(bytes32 _key, bytes _value) external; -``` - -#### execute - -Executes an action on other contracts or a transfer of the blockchains native cryptocurrency. MUST only be called by the current owner of the contract. - -```js -function execute(uint256 _operationType, address _to, uint256 _value, bytes _data) external; +function setData(bytes32 _key, bytes memory _value) external ``` -The `operationType` should represent the assembly operation as follows: -- `0` for `call` -- `1` for `create` - -Others may be added in the future. Inspired by [ERC-1077](./eip-1077.md) and [Gnosis](https://github.com/gnosis/safe-contracts/blob/master/contracts/Enum.sol#L7) - ### Events - #### DataChanged MUST be triggered when `setData` was successfully called. ```js -event DataChanged(bytes32 indexed key, bytes value); -``` - -#### ContractCreated - -MUST be triggered when `execute` creates a new contract using the `_operationType` `1`. - -```js -event ContractCreated(address indexed contractAddress); -``` - -#### OwnerChanged - -MUST be triggered when `changeOwner` was successfully called. - -```js -event OwnerChanged(address indexed ownerAddress); +event DataChanged(bytes32 indexed key, bytes value) ``` ### Ownership -This contract is controlled by the owner. The owner can be a smart contract or an address, or itself. +This contract is controlled by an owner. The owner can be a smart contract or an external account. +This standard requires [ERC173](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-173.md) and should implement the functions: + +- `owner() view` +- `transferOwnership(address newOwner)` +- and the Event `event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` ### Data keys Data keys, should be the keccak256 hash of a type name. -e.g. `myNewKeyType` is `0xa94996022594f93c34a730df0ae89d1ecd69dff98c17d0387e69ce58346323a4` +e.g. `keccak256('ERCXXXMyNewKeyType')` is `0x6935a24ea384927f250ee0b954ed498cd9203fc5d2bf95c735e52e6ca675e047` -#### Multiple keys of the same type +The [ERC725JSONSchema standard](https://github.com/lukso-network/LIPs/blob/master/LSPs/LSP-2-ERC725YJSONSchema.md) defines how keys should be named and generated. +This JSON schema can be used to auto decode ERC725Y values from smart contracts for application and smart contract interactions. -Multiple keys for the same key type must add a `keyTypeName-1` at the end of the key type. +#### Default key values -This would looks as follows for `myNewKeyType`: -version 0 `myNewKeyType`: `0xa94996022594f93c34a730df0ae89d1ecd69dff98c17d0387e69ce58346323a4` -version 1 `myNewKeyType-1`: `0xb6dace1ed14874742c4d1b8cd9b270305176f769e0ae22118a02c2db4e620f29` -version 2 `myNewKeyType-2`: `0x6cc96a01de588f4550e8c3a821aed065ae7897f8dfb61836c78c0389e499d9ed` -... +ERC725 key standards need to be defined within new standards, we suggest the following defaults: + +| Name | Description | Key | value | +| --- | --- | --- | --- | +| SupportedStandards:XYZ | Allows to determine standards supported by this contract | `0xeafec4d89fa9619884b6b89135626455000000000000000000000000xxxxxxxx`, where `xxxxxxxx` is the 4 bytes identifier of the standard supported | Value can be defined by the standard, by default it should be the 4 bytes identifier e.g. `0x7a30e6fc` | +| SupportedStandards:ERC725Account | Allows to determine standards supported by this contract | `0xeafec4d89fa9619884b6b89135626455000000000000000000000000afdeb5d6`, where `afdeb5d6` is the 4 bytes part of the hash of `keccak256('ERC725Account')` | Value is the 4 bytes identifier `0xafdeb5d6` | -Anyone that would like to standardize a new data key should make a pull request to update the table below. + +Other key examples COULD be: | Name | Description | Key | value | | --- | --- | --- | --- | -| owner | The owner of the proxy account | 0x0000000000000000000000000000000000000000000000000000000000000000 | left padded owner address, e.g. `0x000000000000000000000000de0B295669a9FD93d5F28D9Ec85E40f4cb697BAe` | -| 735 | The proxy accounts claim holder contract (per [ERC-735](https://github.com/ethereum/EIPs/issues/735)) | 0xb0f23aea7d77ce19f9393243a7b50a3bcaac893c7d68a5a309dea7cacf035fd0 | left padded address of the claim holder contract, e.g. `0x000000000000000000000000de0B295669a9FD93d5F28D9Ec85E40f4cb697BAe` | -| 780 | The proxy accounts claim holder contract (per [ERC-735](https://github.com/ethereum/EIPs/issues/735)) | 0xdaf52dba5981246bcf8fd7c6b00dce587fdcf5e2a95b281eea95dcd1376afdcd | left padded address of the claim registry contract, e.g. `0x000000000000000000000000de0B295669a9FD93d5F28D9Ec85E40f4cb697BAe` | +| ERC735 | A personal claim holder contract (per [ERC735](https://github.com/ethereum/EIPs/issues/735)) | `0x33f5765e0b3f726091f5ab06cd801c2bcd9bf89228534161c70fd7e257b8bfa3` | 20 bytes value `0xcafecafe69a9FD93d5F28D9Ec85E40f4cb69cafe` | +| ERC780 | A registry claim holder contract (per [ERC780](https://github.com/ethereum/EIPs/issues/780)) | `0x62db7b9279d03518c54464b4946aade7cafabff066a90c55b054d5c5ee04c371` | 20 bytes value `0xcafecafe69a9FD93d5F28D9Ec85E40f4cb69cafe` | -## Rationale +##### ERC725Account -The purpose of an identity proxy is to allow an entity to exist as a first-class citizen in Ethereum, with the ability to execute arbitrary contract calls. At that same time the proxy account should be managed by an arbitrary simple or complex logic. +An `SupportedStandards` > `ERC725Account` (See key > value above) is an ERC725 smart contract based account/profile for storing of assets and execution of other smart contracts. -It also opens up the possibility of [meta transactions](https://medium.com/@austin_48503/ethereum-meta-transactions-90ccf0859e84), where a third party can send a transaction to the owner contract, that then verifies the execution permission based on a signed message. +- `ERC173` to be controllable by an owner, that could be am external account, or smart contract +- `ERC725X` to interact with other smart contracts +- `ERC725Y` to attach data to the account for future extensibility +- COULD have [ERC1271](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1271.md) to be able to verify signatures by the owner (or owner contracts keys). +- Should fire the `event ValueReceived(address indexed sender, uint256 indexed value)` if ETH is received. -It further allows any information to be attached to that proxy accounts which can be in the forms of claims via [ERC-735](https://github.com/ethereum/EIPs/issues/735) or [ERC-780](https://github.com/ethereum/EIPs/issues/780), or any arbitrary new systems and protocols. +A full implementation of an `ERC725Account` can be found [found here](https://github.com/ERC725Alliance/ERC725/tree/master/implementations/contracts). -This specification was chosen to allow the most flexibility and experimentation around verifiable manageable accounts. +## Rationale +The purpose of an smart contract account is to allow an entity to exist as a first-class citizen with the ability to execute arbitrary contract calls. ## Implementation -- [Implementation by ERC725Alliance](https://github.com/ERC725Alliance/erc725/tree/master/contracts/contracts) +- [Latest implementation](https://github.com/ERC725Alliance/ERC725/tree/master/implementations/contracts) -### Solidity Interface -```js -pragma solidity ^0.5.4; +### Solidity Interfaces +```solidity +// SPDX-License-Identifier: CC0-1.0 +pragma solidity >=0.5.0 <0.7.0; -interface ERC725 { - event DataChanged(bytes32 indexed key, bytes32 indexed value); - event OwnerChanged(address indexed ownerAddress); +//ERC165 identifier: `0x44c028fe` +interface IERC725X /* is ERC165, ERC173 */ { event ContractCreated(address indexed contractAddress); + event Executed(uint256 indexed operation, address indexed to, uint256 indexed value, bytes data); - // address public owner; + function execute(uint256 operationType, address to, uint256 value, bytes memory data) external; +} + +//ERC165 identifier: `0x2bd57b73` +interface IERC725Y /* is ERC165, ERC173 */ { + event DataChanged(bytes32 indexed key, bytes value); - function changeOwner(address _owner) external; - function getData(bytes32 _key) external view returns (bytes32 _value); - function setData(bytes32 _key, bytes32 _value) external; - function execute(uint256 _operationType, address _to, uint256 _value, bytes calldata _data) external; + function getData(bytes32 key) external view returns (bytes memory value); + function setData(bytes32 key, bytes memory value) external; +} + +interface IERC725 /* is IERC725X, IERC725Y */ { + +} + +interface IERC725Account /* is IERC725, IERC725Y, IERC1271 */ { + event ValueReceived(address indexed sender, uint256 indexed value); } ``` +## Flow chart + +![ERC725v2-flow](https://user-images.githubusercontent.com/232662/57334038-996a8b00-70ec-11e9-9179-4dda3f30e09d.PNG) + ## Additional References - [Slides of the ERC Identity presentation](https://www.slideshare.net/FabianVogelsteller/erc-725-identity)