Skip to main content

LSP0 - ERC725 Account

Standard Document

Introduction​

Externally Owned Accounts (EOAs) are the primary type of account in Ethereum, controlled by a private key. If the private key is compromised, anyone can execute transactions from the account and access any assets it holds. EOAs have no built-in mechanism for attaching any information or data, making identifying the person or entity using the account challenging. They can only perform simple interactions using the CALL opcode and create contracts using the CREATE opcode.

These issues can be addressed by the ERC725 standard, which provides more operations to execute and a flexible way to attach data for the contract even after it has been deployed.

However, for a smart contract-based account to be viable in the long term, it should have much more functionalities than the ability to execute and to attach data. The features that makes a smart contract an account are:

  • the ability to verify signed messages
  • be notified of incoming tokens, followers, and other types of transactions,
  • be able to be extended after deployment to support functions and standards that will be adopted in the future.

Additionally, it should have a secure ownership management system to ensure the protection of valuable assets.

What does this standard represent ?​

An ERC725Account is a blockchain account system that can be utilized by individuals, machines, or other smart contracts. It is made up of various standards that enable the functionalities mentioned above. It is formed from:

  • ERC165 allows to register and detect the standard interfaces and standards that the contract implements, or will implement in the future.

  • ERC725X is a generic executor that enables calling external contracts with different operations such as CALL, STATICCALL and DELEGATECALL. It also allows deploying new contracts with CREATE or CREATE2, or transferring value to any address (EOA or smart contracts).

  • ERC725Y is a generic key-value store that enables it to attach any information to the smart contract even after it's been deployed.

  • ERC1271 helps to verify the validity of a message and signature.

  • LSP1-UniversalReceiver enables notifications about incoming or outgoing transactions and adds custom handling and behavior based on these transactions.

  • LSP14-Ownable2Step enables a secure ownership management system.

  • LSP17-ContractExtension enables the contract to be extended after deployment to support new standard and functionalities.

ERC725X - Generic Executor​

tip

See the ERC725 standard for more information.

Check the execute functions provided by ERC725X that allows the contract to execute multiple operations.

Check the javascript guides to know How to Send native tokens or How to Call other contract's function using the execute function.

The ERC725X standard enables the account to perform generic calls on other smart contracts, including transferring native tokens. External actions can be executed using the smart contract's generic execute(...) function and multi-calls can be done with the execute(..) batch function, but only the account owner can perform these operations.

Additionally, it also allows for the deployment of new smart contracts by providing the bytecode of the new contract to deploy as an argument to the execute(...) function. Contracts can be deployed using either the CREATE or CREATE2 opcodes.

The following types of calls (operation types) are available:

Operation numberOperation typeDescription
0CALLTransfer native tokens or calls smart contract functions.
1CREATECreate a new smart contract based on the contract address and nonce.
2CREATE2Create a new smart contract based on the contract address, bytecode and the salt. The address can be predetermined.
3STATICCALLCalls another smart contract while disallowing any modification to the state during the call.
4DELEGATECALLRuns the function from another contract, but use the context of the current contract.

Operation 0 - CALL​

ERC725X operation type CALL

Operation 1 - CREATE​

ERC725X operation type CREATE

Operation 2 - CREATE2​

ERC725X operation type CREATE2

Operation 3 - STATICCALL​

ERC725X operation type STATICCALL

Operation 4 - DELEGATECALL​

ERC725X operation type DELEGATECALL

ERC725Y - Generic Key-Value Store​

tip

See the ERC725 standard for more information.

Check the setData functions provided by ERC725Y that allows attaching data to the contract.

Check the javascript guides to know How to Edit a Profile (setData) or How to Read from a Profile (getData).

Once a smart contract is deployed with a specific set of variables containing data, it cannot be modified to include new variables. This can be a problem for smart contract based accounts that need to store more and more data in the future.

ERC725Y standardizes a mapping of data keys to data values to store data dynamically, and to have the ability to add or remove data across time without the need of redeploying the contract. It gives flexibility to the contract storage.

  • Data Keys are represented as bytes32 values.
  • Data Values under these keys are stored as bytes.

ERC725Y key-value store vs standard contract storage

Developers can access the data stored in the contract via data keys instead of referencing the storage slot where the data resides.

Thanks to ERC725Y, contracts become more interoperable, as their storage is represented in the same way. Contracts and interfaces can then read and write data from or to the storage in the same manner via the functions getData(...) and setData(...).

ERC1271​

tip

See the ERC1271 standard for more information.

Check the isValidSignature function documentation.

Unlike Externally Owned Accounts (EOAs), smart contracts cannot sign messages since they do not have private keys. This standard defines a way for contracts to verify if a signature and a message provided are valid according to the contract's logic. There will be many contracts that want to utilize signed messages to validate rights-to-move assets or other purposes.

The LSP0-ERC725Account implements the ERC1271 standard in a flexible way that allows for future upgradeability when different type of owners are set.

When the owner of the account is an EOA, the ECDSA algorithm is used to recover the address of the signer from the provided signature and message, and the function isValidSignature(..) will return valid if the recovered signer address matches the address of the owner.

When the owner is a smart contract, the isValidSignature(..) function will be called on the owner and return whether the signature and the message are valid according to the logic in isValidSignature(..) on the owner contract.

LSP1 - UniversalReceiver​

tip

See the LSP1-UniversalReceiver standard for more information.

Check the universalReceiver functions provided by LSP1 that allows notifying about incoming/ outgoing transactions.

Check the javascript guides to know How to set a UniversalReceiverDelegate built by LUKSO or How to set your own UniversalReceiverDelegate.

This standard enables the account to be notified of incoming transactions such as token transfer, vault transfer, information transfer, etc. Notifications are handy for situations where users want to customize how their account contract reacts to certain tokens by either rejecting them or operating a specific call on each token received.

The LSP0-ERC725Account implements the universalReceiver(..) function that:

Emits an UniversalReceiver event with the typeId and data, as well as additional parameters such as the amount sent to the function, the caller of the function, and the return value of the delegate contracts.

The typeId is a bytes32 value that represents the type of action being notified about. For instance, if you want to notify an account about a specific type of token, you could hash the word "TOKENXX" which would result in a bytes32, and then use it as a typeId.

The data field can contain relevant information related to the typeId used when the universalReceiver(...) function was called. In the case of token transfers, it could be any encoded information such as the recipient balance, time, royalties, etc.

The typeId provides a unique identifier for the type of notification, while the data field provides the specific information related to the notification. This allows for efficient and effective communication of information related to the token, without the need for extensive parsing or decoding of data.

The universalReceiver(...) function and its UniversalReceiver event are the mechanisms through which an LSP0-ERC725Account can receive notifications. Websites can monitor and listen to the event and previous events to understand what the account has been notified about.

LSP0 being notified

This innovation is particularly beneficial for all type of contracts that have a connection with the account, especially token standards, as it streamlines the blockchain user experience by allowing the recipient of a token to be notified directly.

Currently, determining which tokens an address owns requires going through all events of all token contracts on the blockchain network and filtering out the tokens that the address owns based on the events of those contracts.

However, with the UniversalReceiver event, contracts can call the universalReceiver(..) function and emit the event on the account itself. This way, to determine which tokens an account holds, one would simply listen to the UniversalReceiver event emitted on that account. This method is much simpler and more efficient.

LSP0 being notified

In addition to the UniversalReceiver event, the account owner has the ability to set in the storage of the account the addresses of contracts labeled as UniversalReceiverDelegates (URD). These contracts can be chosen to run on each call to the universalReceiver(..) function or on a specific typeId passed to the function.

This provides a way to react to calls, not just to be informed. For example, if the account receives any type of token, regardless of the typeId, it could specify in the main UniversalReceiverDelegate that the transfer should be automatically reverted.

Or, for a specific type of token represented by a specific typeId, account could specify in the MappedUniversalReceiverDelegate (Mapped to a specific typeId) that the token should be automatically forwarded to a vault that the account own.

LSP0 reacting

The UniversalReceiverDelegate contracts provides optional interactions that allows the account to go beyond simply being informed and provides a way to actively respond to different types of notifications as they occur.

LSP14 - Ownable2Step​

tip

See the LSP14 - Ownable2Step standard for more information.

Check the LSP14 functions allowing 2 step ownership transfers.

Check the javascript guides to know How to transferOwnership of a Profile.

An account that holds valuable assets and represents your digital identity should be secure to prevent mistakes that may result in losing it. Therefore, a safe and secure ownership management system should be in place for this account.

LSP14-Ownable2Step is a standard that allows for the ownership of an account to be transferred or renounced through a 2-step process, making it more resistant to phishing attacks. This standard allows for any address, such as an EOA or smart contract, to be the owner of the account. The owner can be a voting contract, or a multisig, or a KeyManager that allow for permission-based access control. (Check LSP6-KeyManager)

ERC725Y key-value store vs standard contract storage

The transfer of ownership is conducted in two stages, where a pending owner is designated and then in another transaction the pending owner must confirm their acceptance of ownership. In the process of ownership transfer, the 2 parties are notified using LSP1-UniversalReceiver standard.

Initiate the transfer​

ERC725Y key-value store vs standard contract storage

Accept ownership​

ERC725Y key-value store vs standard contract storage

Transfer Finalized​

ERC725Y key-value store vs standard contract storage

The process for renouncing ownership follows a similar structure, where an initial call is made, followed by a waiting period and a specific timeframe during which the ownership can be renounced before the process is reset.

Renounce Ownership

LSP17 - Contract Extension​

tip

See the LSP17 - ContractExtension standard for more information.

Check the fallback function that allows calls for the extensions.

Once a smart contract based account is deployed on the blockchain, it is not possible to modify the contract to add new native functions or change the behavior of existing ones. This can be a limitation for these accounts, that may need to support new use cases, functions, and standards that may be adopted in the future.

LSP17-ContractExtension defines a mechanism for extending a contract to support new standard and functions through the use of extensions.

Support New Functions​

The LSP0-ERC725Account contains basic functionality for interacting with other addresses, storing and retrieving data, verifying signatures, handling transactions, managing ownership, and checking interface support with the functions listed below.

LSP0 base functions

To ensure the longevity and continued evolution of the LSP0 as a blockchain account, it is important for it to support new functions that will become standardized in the future. This can be accomplished through the use of extension contracts, which allow the account owner to add new functionality not natively supported by the LSP0.

LSP0 extended with onERC721Received and validateUserOp functions

For example, in the figure above, the LSP0 was extended with the onERC721Received(..) function which will allow the contract to receive safe ERC721 transfers.

By utilizing these extensions, the account can be updated with new features and remain adaptable to changes in the blockchain ecosystem.

Support New Standards​

The ability to add new functions to the LSP0 is crucial for its extendibility post-deployment, but it is also important for the LSP0 to be able to support the new interface IDs of any standards that are added through extensions. Initially, the LSP0 supports a set of interfaces at the time of deployment:

LSP0 base interfaceIds

However, the account can declare support for new interface IDs after it has been extended. This is especially beneficial for contracts that check if a contract supports a specific interface ID before interacting with it.

LSP0 Extended interfaceIds