dType Storage Extension - Decentralized Type System for EVM
ERC-2157 is proposing an optional storage extension for dType, a decentralized type system, that standardizes the ABI of the dType storage contracts, enabling easy navigation and retrieval of type data that is intended to be of public use. This enables a more effective on-chain and off-chain use of data and opens up possibilities for decentralized applications, enabling developers to build on top of public global data.
Video
Original
Simple Summary
This ERC is an extension of ERC-1900, proposing an optional storage extension for dType, a decentralized type system, specifying a general ABI for all storage contracts that contain type instances.
Abstract
The storage extension will enable easy navigation and retrieval of type data that is intended to be of public use. This is possible through standardizing the ABI of the dType storage contracts, with the effect of having a deterministic path to a type instance record. This standardization enables a more effective on-chain and off-chain use of data and opens up possibilities for decentralized applications, enabling developers to build on top of public global data.
Motivation
Currently, Ethereum does not have standardization of data addressability. This might not be needed for data that is meant to be quasi-private, however, it is needed for data that is meant for public consumption. ERC-1900 has started standardizing data types for increasing interoperability between projects, but this is not enough if we want to build a global ecosystem. Deterministic data addressability will enable anyone to build upon the same public data sets, off-chain or on-chain.
It is true that with ERC-1900, blockchain data analysis and type-specific data retrieval will be possible off-chain, but this implies relying on centralized data caches (blockchain explorers) or maintaining your own data cache. Moreover, this option does not allow on-chain standardization on data retrieval paths, therefore limiting the type of on-chain interoperable operations that can be done.
Having a clear way of retrieving data, instead of analyzing the blockchain for contracts that have a certain type in their ABI or bytecode, will make development easier and more decentralized for applications that target global data on specific types.
For example, a decentralized market place can be built on top of some marketplace-specific types, and by knowing exactly where the type data is stored, it is easy to create custom algorithms that provide the user with the product information they seek. Everyone has access to the data and the data path is standardized.
Moreover, by standardizing storage contract interfaces, ABI inference is possible. The common interface, together with the dType registry will provide all the data needed to reconstruct the ABI.
This system can be extended with access and mutability control later on, in a future proposal. Access and mutability control will be necessary for public-use global systems. Moreover, we can have a homogeneous application of permissions across system components. This is not detailed in the present proposal.
Another use case is data bridges between Ethereum shards or between Ethereum and other chains. Data syncing between shards/chains can be done programmatically, across data types (from various projects). Imagine a user having a public profile/identity contract on one chain, wishing to move that profile on Ethereum. By supporting the origin chain types and having a standardized storage mechanism, data moving processes will be the same.
This pattern of separating data type definitions and storage allows developers to create functional programming-like patterns on Ethereum, even though languages such as Solidity are not functional.
Specification
TypeRootContract
ERC-1900 defines a contractAddress
field in the type metadata. For the limited purpose of ERC-1900, this field contains the value of the Ethereum type library in which the type definition exists. For the purpose of this ERC, the contractAddress
will contain the Etherereum address of a TypeRootContract
.
contract TypeRootContract { address public libraryAddress; address public storageAddress; constructor(address _library, address _storage) public { libraryAddress = _library; storageAddress = _storage; } }
libraryAddress
- Ethereum address of the type definition library, from ERC-1900storageAddress
- Ethereum address of the type data storage contract
TypeStorageContract
This contract will use the type library to define the internal data stored in it. Each record will be a type instance, addressable by a primary identifier. The primary identifier is calculated by the type library's getIdentifier
function, based on the type instance values.
We propose a Solidity CRUD pattern, as described in https://medium.com/robhitchens/solidity-crud-part-1-824ffa69509a, where records can also be retrieved using their index - a monotonically increasing counter.
An stub implementation for the TypeStorageContract would look like:
import './TypeALib.sol'; contract TypeAStorage { using TypeALib for TypeALib.TypeA; bytes32[] public typeIndex; mapping(bytes32 => Type) public typeStruct; struct Type { TypeALib.TypeA data; uint256 index; } event LogNew(bytes32 indexed identifier, uint256 indexed index); event LogUpdate(bytes32 indexed identifier, uint256 indexed index); event LogRemove(bytes32 indexed identifier, uint256 indexed index); function insert(TypeALib.TypeA memory data) public returns (bytes32 identifier); function insertBytes(bytes memory data) public returns (bytes32 identifier); function remove(bytes32 identifier) public returns(uint256 index); function update(bytes32 identifier, TypeALib.TypeA memory data) public returns(bytes32 identifier) function isStored(bytes32 identifier) public view returns(bool stored); function getByHash(bytes32 identifier) public view returns(TypeALib.TypeA memory data); function getByIndex(uint256 index) public view returns(TypeALib.TypeA memory data); function count() public view returns(uint256 counter); }
Rationale
We are now thinking about a building block as a smart contract with an encapsulated object that contains state changing functions that are only understood from within. This is more akin to Object-Oriented Programming and poses interoperability and scalability issues. Not necessarily for an individual project, but for a global Ethereum OS. This is why we are proposing to separate data from business logic and data structure definitions.
When you have public aggregated data, categorized on each type, anyone can build tools on top of it. This is a radical change from the closed or dispersed data patterns that we find in web2.
We have chosen to define a TypeRootContract
instead of extending the dType registry with fields for the TypeStorage contract, because this approach enables easier interface updates in the future. It is more extensible.
The storage pattern used for dType itself and all the Type Storage contracts can be the same. This lowers the cost of building, testing and auditing the code.
The TypeStorageContract
pattern should ensure:
- type instance addressability by the primary identifier
- a way to retrieve all records from the contract
- counting the number of records
Backwards Compatibility
This proposal does not affect existent Ethereum standards or implementations. It uses the present experimental version of ABIEncoderV2.
Test Cases
Will be added.
Implementation
An in-work implementation can be found at https://github.com/pipeos-one/dType/tree/master/contracts/contracts. This proposal will be updated with an appropriate implementation when consensus is reached on the specifications.
Copyright
Copyright and related rights waived via CC0.
Adopted by projects
Not miss a beat of EIPs' update?
Subscribe EIPs Fun to receive the latest updates of EIPs Good for Buidlers to follow up.
View all