--- eip: 725 title: General key-value store and execution standard 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 smart contract based account with attachable key value store. ## Abstract 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 and deploy other smart contracts. `ERC725Y`: Can hold arbitrary data through a generic key/value store. ## Motivation 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 ERC165 identifier: `0x44c028fe` #### execute 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. ```solidity function execute(uint256 operationType, address to, uint256 value, bytes data) public ``` 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), [Executed](#executed) ### Events #### Executed MUST be triggered when `execute` creates a new call using any `operationType`. ```solidity event Executed(uint256 indexed _operation, address indexed _to, uint256 indexed _value, bytes _data); ``` #### ContractCreated MUST be triggered when `execute` creates a new contract using the `operationType` `2`, `3`. ```solidity event ContractCreated(address indexed contractAddress) ``` ### ERC725Y ERC165 identifier: `0x5a988c0f` #### getData Returns array of data at multiple keys. ```solidity function getData(bytes32[] calldata _keys) public view returns(bytes[] memory) ``` #### setData Sets array of data at multiple keys. MUST only be called by the current owner of the contract. **Triggers Event:** [DataChanged](#datachanged) ```solidity function setData(bytes32[] calldata _keys, bytes[] calldata _values) public ``` ### Events #### DataChanged MUST be triggered when `setData` was successfully called. ```solidity event DataChanged(bytes32 indexed key, bytes value) ``` ### Ownership This contract is controlled by an owner. The owner can be a smart contract or an external account. This standard requires [ERC173](./eip-173.md) and should implement the functions: - `owner() view` - `transferOwnership(address newOwner)` The event: - `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` ### Data keys Data keys, should be the keccak256 hash of a type name. e.g. `keccak256('ERCXXXMyNewKeyType')` is `0x6935a24ea384927f250ee0b954ed498cd9203fc5d2bf95c735e52e6ca675e047` 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. #### Default key values 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` | ##### ERC725Account 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. - `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. A full implementation of an `ERC725Account` can be found [found here](https://github.com/ERC725Alliance/ERC725/tree/master/implementations/contracts). ## 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 - [Latest implementation](https://github.com/ERC725Alliance/ERC725/tree/master/implementations/contracts) ### Solidity Interfaces ```solidity // SPDX-License-Identifier: CC0-1.0 pragma solidity >=0.5.0 <0.7.0; //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); function execute(uint256 operationType, address to, uint256 value, bytes memory data) external; } //ERC165 identifier: `0x5a988c0f` interface IERC725Y /* is ERC165, ERC173 */ { event DataChanged(bytes32 indexed key, bytes value); function getData(bytes32[] calldata _keys) external view returns(bytes[] memory); function setData(bytes32[] calldata _keys, bytes[] calldata _values) 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) - [In-contract claim VS claim registry](https://github.com/ethereum/wiki/wiki/ERC-735:-Claim-Holder-Registry-vs.-in-contract) - [Identity related reports](https://www.weboftrust.info/specs.html) - [W3C Verifiable Claims Use Cases](https://w3c.github.io/vc-use-cases/) - [Decentralised Identity Foundation](https://identity.foundation) - [Sovrin Foundation Self Sovereign Identity](https://sovrin.org/wp-content/uploads/2017/06/The-Inevitable-Rise-of-Self-Sovereign-Identity.pdf) ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).