The following describes two standards that allow for a generic data storage in a smart contract and a generic execution through a smart contract. These can be used separately or in conjunction and can serve as building blocks for smart contract accounts, upgradable metadata, and other means.
Motivation
The initial motivation came out of the need to create a smart contract account system that’s flexible enough to be viable long-term but also defined enough to be standardized. They are a generic set of two standardized building blocks to be used in all forms of smart contracts.
This standard consists of two sub-standards, a generic data key/value store (ERC725Y) and a generic execute function (ERC725X). Both of these in combination allow for a very flexible and long-lasting account system. The account version of ERC725 is standardized under LSP0-ERC725Account.
These standards (ERC725 X and Y) can also be used separately as ERC725Y can be used to enhance NFTs and Token metadata or other types of smart contracts. ERC725X allows for a generic execution through a smart contract, functioning as an account or actor.
Specification
Ownership
This contract is controlled by a single owner. The owner can be a smart contract or an external account.
This standard requires ERC-173 and SHOULD implement the functions:
ERC725X interface id according to ERC-165: 0x7545acac.
Smart contracts implementing the ERC725X standard MUST implement the ERC-165supportsInterface(..) function and MUST support the ERC165 and ERC725X interface ids.
ERC725X Methods
Smart contracts implementing the ERC725X standard SHOULD implement all of the functions listed below:
MUST be triggered when execute creates a new contract using the operationType1, 2.
ERC725Y
ERC725Y interface id according to ERC-165: 0x629aa694.
Smart contracts implementing the ERC725Y standard MUST implement the ERC-165supportsInterface(..) function and MUST support the ERC165 and ERC725Y interface ids.
ERC725Y Methods
Smart contracts implementing the ERC725Y standard MUST implement all of the functions listed below:
MUST be triggered when a data key was successfully set.
ERC725Y Data keys
Data keys, are the way to retrieve values via getData(). These bytes32 values can be freely chosen, or defined by a standard.
A common way to define data keys is the hash of a word, e.g. keccak256('ERCXXXMyNewKeyType') which results in: 0x6935a24ea384927f250ee0b954ed498cd9203fc5d2bf95c735e52e6ca675e047
The LSP2-ERC725JSONSchema standard is a more explicit ERC725Y data key standard, that defines key types and value types, and their encoding and decoding.
Rationale
The generic way of storing data keys with values was chosen to allow upgradability over time. Stored data values can be changed over time. Other smart contract protocols can then interpret this data in new ways and react to interactions from a ERC725 smart contract differently.
The data stored in an ERC725Y smart contract is not only readable/writable by off-chain applications, but also by other smart contracts. Function overloading was used to allow for the retrievable of single and multiple keys, to keep gas costs minimal for both use cases.
Backwards Compatibility
All contracts since ERC725v2 from 2018/19 should be compatible with the current version of the standard. Mainly interface ID and Event parameters have changed, while getData(bytes32[]) and setData(bytes32[], bytes[]) was added as an efficient way to set/get multiple keys at once. The same applies to execution, as execute(..[]) was added as an efficient way to batch calls.
From 2023 onward, overloading was removed from ERC-725 (including ERC725-X and ERC725-Y). This is because, while overloading is accommodated in Solidity, it isn’t broadly supported across most blockchain languages. In order to make the standard language-independent, it was decided to shift from overloading to simply attach the term “Batch” to the functions that accept an array as parameters.
Reference Implementation
Reference implementations can be found in ERC725.sol.
Security Considerations
This contract allows generic executions, therefore special care needs to be taken to prevent re-entrancy attacks and other forms of call chain attacks.
When using the operation type 4 for delegatecall, it is important to consider that the called contracts can alter the state of the calling contract and also change owner variables and ERC725Y data storage entries at will. Additionally calls to selfdestruct are possible and other harmful state-changing operations.
Solidity Interfaces
// SPDX-License-Identifier: CC0-1.0
pragmasolidity>=0.5.0<0.7.0;// ERC165 identifier: `0x7545acac`
interfaceIERC725X/* is ERC165, ERC173 */{eventExecuted(uint256indexedoperationType,addressindexedtarget,uint256indexedvalue,bytes4data);eventContractCreated(uint256indexedoperationType,addressindexedcontractAddress,uint256indexedvalue,bytes32salt);functionexecute(uint256operationType,addresstarget,uint256value,bytesmemorydata)externalpayablereturns(bytesmemory);functionexecuteBatch(uint256[]memoryoperationsType,address[]memorytargets,uint256[]memoryvalues,bytesmemorydatas)externalpayablereturns(bytes[]memory);}// ERC165 identifier: `0x629aa694`
interfaceIERC725Y/* is ERC165, ERC173 */{eventDataChanged(bytes32indexeddataKey,bytesdataValue);functiongetData(bytes32dataKey)externalviewreturns(bytesmemory);functiongetDataBatch(bytes32[]memorydataKeys)externalviewreturns(bytes[]memory);functionsetData(bytes32dataKey,bytesmemorydataValue)external;functionsetDataBatch(bytes32[]memorydataKeys,bytes[]memorydataValues)external;}interfaceIERC725/* is IERC725X, IERC725Y */{}
Fabian Vogelsteller (@frozeman), Tyler Yasaka (@tyleryasaka), "ERC-725: General data key/value store and execution [DRAFT]," Ethereum Improvement Proposals, no. 725, October 2017. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-725.