| Contract | Interface ID | Description | | :-------------------------------- | :----------: | :------------------------------------------------------------------------------------------------------------------------------------------------------- | | **ERC165** | `0x01ffc9a7` | Standard Interface Detection. | | **ERC1271** | `0x1626ba7e` | Standard Signature Validation Method for Contracts. | | **ERC725X** | `0x7545acac` | General executor. | | **ERC725Y** | `0x629aa694` | General Data key-value store. | | **LSP0ERC725Account** | `0x24871b3d` | Interface of the [LSP-0-ERC725Account] standard, an account based smart contract that represents an identity on-chain. | | **LSP1UniversalReceiver** | `0x6bb56a14` | Interface of the LSP1 - Universal Receiver standard, an entry function for a contract to receive arbitrary information. | | **LSP1UniversalReceiverDelegate** | `0xa245bbda` | Interface of the LSP1 - Universal Receiver Delegate standard. | | **LSP6KeyManager** | `0x23f34c62` | Interface of the LSP6 - Key Manager standard, a contract acting as a controller of an ERC725 Account using predefined permissions. | | **LSP7DigitalAsset** | `0xb3c4928f` | Interface of the LSP7 - Digital Asset standard, a fungible digital asset. | | **LSP8IdentifiableDigitalAsset** | `0x3a271706` | Interface of the LSP8 - Identifiable Digital Asset standard, a non-fungible digital asset. | | **LSP9Vault** | `0x28af17e6` | Interface of LSP9 - Vault standard, a blockchain vault that can hold assets and interact with other smart contracts. | | **LSP11BasicSocialRecovery** | `0x049a28f1` | Interface of the LSP11 - Basic Social Recovery standard, a contract to recover access control into an account. | | **LSP14Ownable2Step** | `0x94be5999` | Interface of the LSP14 - Ownable 2-step standard, an extension of the [EIP173] (Ownable) standard with 2-step process to transfer or renounce ownership. | | **LSP17Extendable** | `0xa918fa6b` | Module to add more functionalities to a contract using extensions. | | **LSP17Extension** | `0xcee78b40` | Module to create a contract that can act as an extension. | | **LSP20CallVerification** | `0x1a0eb6a5` | Implementation of a contract calling the verification functions according to LSP20 - Call Verification standard. | | **LSP20CallVerifier** | `0x0d6ecac7` | Interface for the LSP20 Call Verification standard, a set of functions intended to perform verifications on behalf of another contract. | | **LSP25ExecuteRelayCall** | `0x5ac79908` | | | **LSP26FollowerSystem** | `0x2b299cea` | LSP26 Follower System provides a robust foundation for building social features into blockchain applications. | --- [ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # ERC725 :::info Standard Specifications [`ERC-725`](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md) ::: :::info Solidity implementation [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) ::: > ERC725 bundle. Bundle ERC725X and ERC725Y together into one smart contract. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#constructor) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) ::: ```solidity constructor(address initialOwner); ``` _Deploying an ERC725 smart contract and setting address `initialOwner` as the contract owner._ Deploy a new ERC725 contract with the provided `initialOwner` as the contract [`owner`](#owner).
**Requirements:** - `initialOwner` CANNOT be the zero address.
#### Parameters | Name | Type | Description | | -------------- | :-------: | -------------------------- | | `initialOwner` | `address` | the owner of the contract. |
### execute :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#execute) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `execute(uint256,address,uint256,bytes)` - Function selector: `0x44c028fe` ::: ```solidity function execute( uint256 operationType, address target, uint256 value, bytes data ) external payable returns (bytes); ``` _Calling address `target` using `operationType`, transferring `value` wei and data: `data`._ Generic executor function to: - send native tokens to any address. - interact with any contract by passing an abi-encoded function call in the `data` parameter. - deploy a contract by providing its creation bytecode in the `data` parameter.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract. - if a `value` is provided, the contract MUST have at least this amount to transfer to `target` from its balance and execute successfully. - if the operation type is `STATICCALL` (`3`) or `DELEGATECALL` (`4`), `value` transfer is disallowed and SHOULD be 0. - `target` SHOULD be `address(0)` when deploying a new contract via `operationType` `CREATE` (`1`), or `CREATE2` (`2`).
**Emitted events:** - [`Executed`](#executed) event when a call is made with `operationType` 0 (CALL), 3 (STATICCALL) or 4 (DELEGATECALL). - [`ContractCreated`](#contractcreated) event when deploying a new contract with `operationType` 1 (CREATE) or 2 (CREATE2).
#### Parameters | Name | Type | Description | | --------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `operationType` | `uint256` | The operation type used: CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4 | | `target` | `address` | The address of the EOA or smart contract. (unused if a contract is created via operation type 1 or 2) | | `value` | `uint256` | The amount of native tokens to transfer (in Wei) | | `data` | `bytes` | The call data, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-----: | ----------- | | `0` | `bytes` | - |
### executeBatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#executebatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `executeBatch(uint256[],address[],uint256[],bytes[])` - Function selector: `0x31858452` ::: :::caution Warning - The `msg.value` should not be trusted for any method called with `operationType`: `DELEGATECALL` (4). ::: ```solidity function executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) external payable returns (bytes[]); ``` _Calling multiple addresses `targets` using `operationsType`, transferring `values` wei and data: `datas`._ Batch executor function that behaves the same as [`execute`](#execute) but allowing multiple operations in the same transaction.
**Requirements:** - All the array parameters provided MUST be equal and have the same length. - SHOULD only be callable by the [`owner`](#owner) of the contract. - The contract MUST have in its balance **at least the sum of all the `values`** to transfer and execute successfully each calldata payloads.
**Emitted events:** - [`Executed`](#executed) event, when a call is made with `operationType` 0 (CALL), 3 (STATICCALL) or 4 (DELEGATECALL) - [`ContractCreated`](#contractcreated) event, when deploying a contract with `operationType` 1 (CREATE) or 2 (CREATE2)
#### Parameters | Name | Type | Description | | ---------------- | :---------: | --------------------------------------------------------------------------------------------------------------- | | `operationsType` | `uint256[]` | The list of operations type used: `CALL = 0`; `CREATE = 1`; `CREATE2 = 2`; `STATICCALL = 3`; `DELEGATECALL = 4` | | `targets` | `address[]` | The list of addresses to call. `targets` will be unused if a contract is created (operation types 1 and 2). | | `values` | `uint256[]` | The list of native token amounts to transfer (in Wei). | | `datas` | `bytes[]` | The list of calldata, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `bytes[]` | - |
### getData :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#getdata) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#getdatabatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### owner :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#owner) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#renounceownership) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### setData :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#setdata) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#setdatabatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#supportsinterface) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### transferOwnership :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#transferownership) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_execute ```solidity function _execute( uint256 operationType, address target, uint256 value, bytes data ) internal nonpayable returns (bytes); ``` check the `operationType` provided and perform the associated low-level opcode after checking for requirements (see [`execute`](#execute)).
### \_executeBatch ```solidity function _executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) internal nonpayable returns (bytes[]); ``` check each `operationType` provided in the batch and perform the associated low-level opcode after checking for requirements (see [`executeBatch`](#executebatch)).
### \_executeCall ```solidity function _executeCall( address target, uint256 value, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level call (operation type = 0) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------- | | `target` | `address` | The address on which call is executed | | `value` | `uint256` | The value to be sent with the call | | `data` | `bytes` | The data to be sent with the call | #### Returns | Name | Type | Description | | -------- | :-----: | ---------------------- | | `result` | `bytes` | The data from the call |
### \_executeStaticCall ```solidity function _executeStaticCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level staticcall (operation type = 3) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------- | | `target` | `address` | The address on which staticcall is executed | | `data` | `bytes` | The data to be sent with the staticcall | #### Returns | Name | Type | Description | | -------- | :-----: | ------------------------------------- | | `result` | `bytes` | The data returned from the staticcall |
### \_executeDelegateCall :::caution Warning The `msg.value` should not be trusted for any method called with `operationType`: `DELEGATECALL` (4). ::: ```solidity function _executeDelegateCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level delegatecall (operation type = 4) #### Parameters | Name | Type | Description | | -------- | :-------: | --------------------------------------------- | | `target` | `address` | The address on which delegatecall is executed | | `data` | `bytes` | The data to be sent with the delegatecall | #### Returns | Name | Type | Description | | -------- | :-----: | --------------------------------------- | | `result` | `bytes` | The data returned from the delegatecall |
### \_deployCreate ```solidity function _deployCreate( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE` opcode (operation type = 1) #### Parameters | Name | Type | Description | | -------------- | :-------: | ---------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_deployCreate2 ```solidity function _deployCreate2( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE2` opcode (operation type = 2) #### Parameters | Name | Type | Description | | -------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) and a bytes32 salt | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` Write a `dataValue` to the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ```
**Emitted events:** - [`DataChanged`](#datachanged) event emitted after a successful `setData` call.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to write the associated `bytes` value to the store. | | `dataValue` | `bytes` | The `bytes` value to associate with the given `dataKey` in the ERC725Y storage. |
## Events ### ContractCreated :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#contractcreated) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Event signature: `ContractCreated(uint256,address,uint256,bytes32)` - Event topic hash: `0xa1fb700aaee2ae4a2ff6f91ce7eba292f89c2f5488b8ec4c5c5c8150692595c3` ::: ```solidity event ContractCreated( uint256 indexed operationType, address indexed contractAddress, uint256 value, bytes32 indexed salt ); ``` _Deployed new contract at address `contractAddress` and funded with `value` wei (deployed using opcode: `operationType`)._ Emitted when a new contract was created and deployed. #### Parameters | Name | Type | Description | | ------------------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The opcode used to deploy the contract (`CREATE` or `CREATE2`). | | `contractAddress` **`indexed`** | `address` | The created contract address. | | `value` | `uint256` | The amount of native tokens (in Wei) sent to fund the created contract on deployment. | | `salt` **`indexed`** | `bytes32` | The salt used to deterministically deploy the contract (`CREATE2` only). If `CREATE` opcode is used, the salt value will be `bytes32(0)`. |
### DataChanged :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#datachanged) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Executed :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#executed) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Event signature: `Executed(uint256,address,uint256,bytes4)` - Event topic hash: `0x4810874456b8e6487bd861375cf6abd8e1c8bb5858c8ce36a86a04dabfac199e` ::: ```solidity event Executed( uint256 indexed operationType, address indexed target, uint256 value, bytes4 indexed selector ); ``` _Called address `target` using `operationType` with `value` wei and `data`._ Emitted when calling an address `target` (EOA or contract) with `value`. #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ---------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The low-level call opcode used to call the `target` address (`CALL`, `STATICALL` or `DELEGATECALL`). | | `target` **`indexed`** | `address` | The address to call. `target` will be unused if a contract is created (operation types 1 and 2). | | `value` | `uint256` | The amount of native tokens transferred along the call (in Wei). | | `selector` **`indexed`** | `bytes4` | The first 4 bytes (= function selector) of the data sent with the call. |
### OwnershipTransferred :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#ownershiptransferred) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
## Errors ### ERC725X_ContractDeploymentFailed :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_contractdeploymentfailed) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_ContractDeploymentFailed()` - Error hash: `0x0b07489b` ::: ```solidity error ERC725X_ContractDeploymentFailed(); ``` Reverts when contract deployment failed via [`execute`](#execute) or [`executeBatch`](#executebatch) functions, This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_CreateOperationsRequireEmptyRecipientAddress :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_createoperationsrequireemptyrecipientaddress) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_CreateOperationsRequireEmptyRecipientAddress()` - Error hash: `0x3041824a` ::: ```solidity error ERC725X_CreateOperationsRequireEmptyRecipientAddress(); ``` Reverts when passing a `to` address that is not `address(0)` (= address zero) while deploying a contract via [`execute`](#execute) or [`executeBatch`](#executebatch) functions. This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_ExecuteParametersEmptyArray :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_executeparametersemptyarray) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_ExecuteParametersEmptyArray()` - Error hash: `0xe9ad2b5f` ::: ```solidity error ERC725X_ExecuteParametersEmptyArray(); ``` Reverts when one of the array parameter provided to the [`executeBatch`](#executebatch) function is an empty array.
### ERC725X_ExecuteParametersLengthMismatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_executeparameterslengthmismatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_ExecuteParametersLengthMismatch()` - Error hash: `0x3ff55f4d` ::: ```solidity error ERC725X_ExecuteParametersLengthMismatch(); ``` Reverts when there is not the same number of elements in the `operationTypes`, `targets` addresses, `values`, and `datas` array parameters provided when calling the [`executeBatch`](#executebatch) function.
### ERC725X_InsufficientBalance :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_insufficientbalance) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_InsufficientBalance(uint256,uint256)` - Error hash: `0x0df9a8f8` ::: ```solidity error ERC725X_InsufficientBalance(uint256 balance, uint256 value); ``` Reverts when trying to send more native tokens `value` than available in current `balance`. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `balance` | `uint256` | The balance of native tokens of the ERC725X smart contract. | | `value` | `uint256` | The amount of native tokens sent via `ERC725X.execute(...)`/`ERC725X.executeBatch(...)` that is greater than the contract's `balance`. |
### ERC725X_MsgValueDisallowedInDelegateCall :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_msgvaluedisallowedindelegatecall) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_MsgValueDisallowedInDelegateCall()` - Error hash: `0x5ac83135` ::: ```solidity error ERC725X_MsgValueDisallowedInDelegateCall(); ``` Reverts when trying to send native tokens (`value` / `values[]` parameter of [`execute`](#execute) or [`executeBatch`](#executebatch) functions) while making a `delegatecall` (`operationType == 4`). Sending native tokens via `staticcall` is not allowed because `msg.value` is persisting.
### ERC725X_MsgValueDisallowedInStaticCall :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_msgvaluedisallowedinstaticcall) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_MsgValueDisallowedInStaticCall()` - Error hash: `0x72f2bc6a` ::: ```solidity error ERC725X_MsgValueDisallowedInStaticCall(); ``` Reverts when trying to send native tokens (`value` / `values[]` parameter of [`execute`](#execute) or [`executeBatch`](#executebatch) functions) while making a `staticcall` (`operationType == 3`). Sending native tokens via `staticcall` is not allowed because it is a state changing operation.
### ERC725X_NoContractBytecodeProvided :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_nocontractbytecodeprovided) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_NoContractBytecodeProvided()` - Error hash: `0xb81cd8d9` ::: ```solidity error ERC725X_NoContractBytecodeProvided(); ``` Reverts when no contract bytecode was provided as parameter when trying to deploy a contract via [`execute`](#execute) or [`executeBatch`](#executebatch). This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_UnknownOperationType :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_unknownoperationtype) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_UnknownOperationType(uint256)` - Error hash: `0x7583b3bc` ::: ```solidity error ERC725X_UnknownOperationType(uint256 operationTypeProvided); ``` Reverts when the `operationTypeProvided` is none of the default operation types available. (CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4) #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ------------------------------------------------------------------------------------------------------ | | `operationTypeProvided` | `uint256` | The unrecognised operation type number provided to `ERC725X.execute(...)`/`ERC725X.executeBatch(...)`. |
### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### OwnableCallerNotTheOwner :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#ownablecallernottheowner) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
--- # ERC725 :::info Standard Specifications [`ERC-725`](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md) ::: :::info Solidity implementation [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) ::: > ERC725 bundle. Bundle ERC725X and ERC725Y together into one smart contract. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#constructor) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) ::: ```solidity constructor(address initialOwner); ``` _Deploying an ERC725 smart contract and setting address `initialOwner` as the contract owner._ Deploy a new ERC725 contract with the provided `initialOwner` as the contract [`owner`](#owner).
**Requirements:** - `initialOwner` CANNOT be the zero address.
#### Parameters | Name | Type | Description | | -------------- | :-------: | -------------------------- | | `initialOwner` | `address` | the owner of the contract. |
### execute :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#execute) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `execute(uint256,address,uint256,bytes)` - Function selector: `0x44c028fe` ::: ```solidity function execute( uint256 operationType, address target, uint256 value, bytes data ) external payable returns (bytes); ``` _Calling address `target` using `operationType`, transferring `value` wei and data: `data`._ Generic executor function to: - send native tokens to any address. - interact with any contract by passing an abi-encoded function call in the `data` parameter. - deploy a contract by providing its creation bytecode in the `data` parameter.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract. - if a `value` is provided, the contract MUST have at least this amount to transfer to `target` from its balance and execute successfully. - if the operation type is `STATICCALL` (`3`) or `DELEGATECALL` (`4`), `value` transfer is disallowed and SHOULD be 0. - `target` SHOULD be `address(0)` when deploying a new contract via `operationType` `CREATE` (`1`), or `CREATE2` (`2`).
**Emitted events:** - [`Executed`](#executed) event when a call is made with `operationType` 0 (CALL), 3 (STATICCALL) or 4 (DELEGATECALL). - [`ContractCreated`](#contractcreated) event when deploying a new contract with `operationType` 1 (CREATE) or 2 (CREATE2).
#### Parameters | Name | Type | Description | | --------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `operationType` | `uint256` | The operation type used: CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4 | | `target` | `address` | The address of the EOA or smart contract. (unused if a contract is created via operation type 1 or 2) | | `value` | `uint256` | The amount of native tokens to transfer (in Wei) | | `data` | `bytes` | The call data, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-----: | ----------- | | `0` | `bytes` | - |
### executeBatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#executebatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `executeBatch(uint256[],address[],uint256[],bytes[])` - Function selector: `0x31858452` ::: :::caution Warning - The `msg.value` should not be trusted for any method called with `operationType`: `DELEGATECALL` (4). ::: ```solidity function executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) external payable returns (bytes[]); ``` _Calling multiple addresses `targets` using `operationsType`, transferring `values` wei and data: `datas`._ Batch executor function that behaves the same as [`execute`](#execute) but allowing multiple operations in the same transaction.
**Requirements:** - All the array parameters provided MUST be equal and have the same length. - SHOULD only be callable by the [`owner`](#owner) of the contract. - The contract MUST have in its balance **at least the sum of all the `values`** to transfer and execute successfully each calldata payloads.
**Emitted events:** - [`Executed`](#executed) event, when a call is made with `operationType` 0 (CALL), 3 (STATICCALL) or 4 (DELEGATECALL) - [`ContractCreated`](#contractcreated) event, when deploying a contract with `operationType` 1 (CREATE) or 2 (CREATE2)
#### Parameters | Name | Type | Description | | ---------------- | :---------: | --------------------------------------------------------------------------------------------------------------- | | `operationsType` | `uint256[]` | The list of operations type used: `CALL = 0`; `CREATE = 1`; `CREATE2 = 2`; `STATICCALL = 3`; `DELEGATECALL = 4` | | `targets` | `address[]` | The list of addresses to call. `targets` will be unused if a contract is created (operation types 1 and 2). | | `values` | `uint256[]` | The list of native token amounts to transfer (in Wei). | | `datas` | `bytes[]` | The list of calldata, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `bytes[]` | - |
### getData :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#getdata) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#getdatabatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### owner :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#owner) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#renounceownership) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### setData :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#setdata) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#setdatabatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#supportsinterface) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### transferOwnership :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#transferownership) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_execute ```solidity function _execute( uint256 operationType, address target, uint256 value, bytes data ) internal nonpayable returns (bytes); ``` check the `operationType` provided and perform the associated low-level opcode after checking for requirements (see [`execute`](#execute)).
### \_executeBatch ```solidity function _executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) internal nonpayable returns (bytes[]); ``` check each `operationType` provided in the batch and perform the associated low-level opcode after checking for requirements (see [`executeBatch`](#executebatch)).
### \_executeCall ```solidity function _executeCall( address target, uint256 value, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level call (operation type = 0) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------- | | `target` | `address` | The address on which call is executed | | `value` | `uint256` | The value to be sent with the call | | `data` | `bytes` | The data to be sent with the call | #### Returns | Name | Type | Description | | -------- | :-----: | ---------------------- | | `result` | `bytes` | The data from the call |
### \_executeStaticCall ```solidity function _executeStaticCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level staticcall (operation type = 3) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------- | | `target` | `address` | The address on which staticcall is executed | | `data` | `bytes` | The data to be sent with the staticcall | #### Returns | Name | Type | Description | | -------- | :-----: | ------------------------------------- | | `result` | `bytes` | The data returned from the staticcall |
### \_executeDelegateCall :::caution Warning The `msg.value` should not be trusted for any method called with `operationType`: `DELEGATECALL` (4). ::: ```solidity function _executeDelegateCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level delegatecall (operation type = 4) #### Parameters | Name | Type | Description | | -------- | :-------: | --------------------------------------------- | | `target` | `address` | The address on which delegatecall is executed | | `data` | `bytes` | The data to be sent with the delegatecall | #### Returns | Name | Type | Description | | -------- | :-----: | --------------------------------------- | | `result` | `bytes` | The data returned from the delegatecall |
### \_deployCreate ```solidity function _deployCreate( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE` opcode (operation type = 1) #### Parameters | Name | Type | Description | | -------------- | :-------: | ---------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_deployCreate2 ```solidity function _deployCreate2( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE2` opcode (operation type = 2) #### Parameters | Name | Type | Description | | -------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) and a bytes32 salt | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` Write a `dataValue` to the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ```
**Emitted events:** - [`DataChanged`](#datachanged) event emitted after a successful `setData` call.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to write the associated `bytes` value to the store. | | `dataValue` | `bytes` | The `bytes` value to associate with the given `dataKey` in the ERC725Y storage. |
## Events ### ContractCreated :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#contractcreated) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Event signature: `ContractCreated(uint256,address,uint256,bytes32)` - Event topic hash: `0xa1fb700aaee2ae4a2ff6f91ce7eba292f89c2f5488b8ec4c5c5c8150692595c3` ::: ```solidity event ContractCreated(uint256 indexed operationType, address indexed contractAddress, uint256 value, bytes32 indexed salt); ``` _Deployed new contract at address `contractAddress` and funded with `value` wei (deployed using opcode: `operationType`)._ Emitted when a new contract was created and deployed. #### Parameters | Name | Type | Description | | ------------------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The opcode used to deploy the contract (`CREATE` or `CREATE2`). | | `contractAddress` **`indexed`** | `address` | The created contract address. | | `value` | `uint256` | The amount of native tokens (in Wei) sent to fund the created contract on deployment. | | `salt` **`indexed`** | `bytes32` | The salt used to deterministically deploy the contract (`CREATE2` only). If `CREATE` opcode is used, the salt value will be `bytes32(0)`. |
### DataChanged :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#datachanged) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Executed :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#executed) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Event signature: `Executed(uint256,address,uint256,bytes4)` - Event topic hash: `0x4810874456b8e6487bd861375cf6abd8e1c8bb5858c8ce36a86a04dabfac199e` ::: ```solidity event Executed(uint256 indexed operationType, address indexed target, uint256 value, bytes4 indexed selector); ``` _Called address `target` using `operationType` with `value` wei and `data`._ Emitted when calling an address `target` (EOA or contract) with `value`. #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ---------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The low-level call opcode used to call the `target` address (`CALL`, `STATICALL` or `DELEGATECALL`). | | `target` **`indexed`** | `address` | The address to call. `target` will be unused if a contract is created (operation types 1 and 2). | | `value` | `uint256` | The amount of native tokens transferred along the call (in Wei). | | `selector` **`indexed`** | `bytes4` | The first 4 bytes (= function selector) of the data sent with the call. |
### OwnershipTransferred :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#ownershiptransferred) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
## Errors ### ERC725X_ContractDeploymentFailed :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_contractdeploymentfailed) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_ContractDeploymentFailed()` - Error hash: `0x0b07489b` ::: ```solidity error ERC725X_ContractDeploymentFailed(); ``` Reverts when contract deployment failed via [`execute`](#execute) or [`executeBatch`](#executebatch) functions, This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_CreateOperationsRequireEmptyRecipientAddress :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_createoperationsrequireemptyrecipientaddress) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_CreateOperationsRequireEmptyRecipientAddress()` - Error hash: `0x3041824a` ::: ```solidity error ERC725X_CreateOperationsRequireEmptyRecipientAddress(); ``` Reverts when passing a `to` address that is not `address(0)` (= address zero) while deploying a contract via [`execute`](#execute) or [`executeBatch`](#executebatch) functions. This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_ExecuteParametersEmptyArray :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_executeparametersemptyarray) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_ExecuteParametersEmptyArray()` - Error hash: `0xe9ad2b5f` ::: ```solidity error ERC725X_ExecuteParametersEmptyArray(); ``` Reverts when one of the array parameter provided to the [`executeBatch`](#executebatch) function is an empty array.
### ERC725X_ExecuteParametersLengthMismatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_executeparameterslengthmismatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_ExecuteParametersLengthMismatch()` - Error hash: `0x3ff55f4d` ::: ```solidity error ERC725X_ExecuteParametersLengthMismatch(); ``` Reverts when there is not the same number of elements in the `operationTypes`, `targets` addresses, `values`, and `datas` array parameters provided when calling the [`executeBatch`](#executebatch) function.
### ERC725X_InsufficientBalance :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_insufficientbalance) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_InsufficientBalance(uint256,uint256)` - Error hash: `0x0df9a8f8` ::: ```solidity error ERC725X_InsufficientBalance(uint256 balance, uint256 value); ``` Reverts when trying to send more native tokens `value` than available in current `balance`. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `balance` | `uint256` | The balance of native tokens of the ERC725X smart contract. | | `value` | `uint256` | The amount of native tokens sent via `ERC725X.execute(...)`/`ERC725X.executeBatch(...)` that is greater than the contract's `balance`. |
### ERC725X_MsgValueDisallowedInDelegateCall :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_msgvaluedisallowedindelegatecall) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_MsgValueDisallowedInDelegateCall()` - Error hash: `0x5ac83135` ::: ```solidity error ERC725X_MsgValueDisallowedInDelegateCall(); ``` Reverts when trying to send native tokens (`value` / `values[]` parameter of [`execute`](#execute) or [`executeBatch`](#executebatch) functions) while making a `delegatecall` (`operationType == 4`). Sending native tokens via `staticcall` is not allowed because `msg.value` is persisting.
### ERC725X_MsgValueDisallowedInStaticCall :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_msgvaluedisallowedinstaticcall) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_MsgValueDisallowedInStaticCall()` - Error hash: `0x72f2bc6a` ::: ```solidity error ERC725X_MsgValueDisallowedInStaticCall(); ``` Reverts when trying to send native tokens (`value` / `values[]` parameter of [`execute`](#execute) or [`executeBatch`](#executebatch) functions) while making a `staticcall` (`operationType == 3`). Sending native tokens via `staticcall` is not allowed because it is a state changing operation.
### ERC725X_NoContractBytecodeProvided :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_nocontractbytecodeprovided) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_NoContractBytecodeProvided()` - Error hash: `0xb81cd8d9` ::: ```solidity error ERC725X_NoContractBytecodeProvided(); ``` Reverts when no contract bytecode was provided as parameter when trying to deploy a contract via [`execute`](#execute) or [`executeBatch`](#executebatch). This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_UnknownOperationType :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x_unknownoperationtype) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725X_UnknownOperationType(uint256)` - Error hash: `0x7583b3bc` ::: ```solidity error ERC725X_UnknownOperationType(uint256 operationTypeProvided); ``` Reverts when the `operationTypeProvided` is none of the default operation types available. (CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4) #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ------------------------------------------------------------------------------------------------------ | | `operationTypeProvided` | `uint256` | The unrecognised operation type number provided to `ERC725X.execute(...)`/`ERC725X.executeBatch(...)`. |
### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### OwnableCallerNotTheOwner :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#ownablecallernottheowner) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**ERC-725**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`ERC725.sol`](https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP0ERC725Account :::info Standard Specifications [`LSP-0-ERC725Account`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md) ::: :::info Solidity implementation [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) ::: > Deployable Implementation of [LSP-0-ERC725Account] Standard. A smart contract account including basic functionalities such as: - Detecting supported standards using [ERC-165] - Executing several operation on other addresses including creating contracts using [ERC-725X] - A generic data key-value store using [ERC-725Y] - Validating signatures using [ERC-1271] - Receiving notification and react on them using [LSP-1-UniversalReceiver] - Safer ownership management through 2-steps transfer using [LSP-14-Ownable2Step] - Extending the account with new functions and interfaceIds of future standards using [LSP-17-ContractExtension] - Verifying calls on the owner to make it easier to interact with the account directly using [LSP-20-CallVerification] ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#constructor) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) ::: ```solidity constructor(address initialOwner); ``` _Deploying a LSP0ERC725Account contract with owner set to address `initialOwner`._ Set `initialOwner` as the contract owner. - The `constructor` also allows funding the contract on deployment. - The `initialOwner` will then be allowed to call protected functions marked with the `onlyOwner` modifier.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event when funding the contract on deployment. - [`OwnershipTransferred`](#ownershiptransferred) event when `initialOwner` is set as the contract [`owner`](#owner).
#### Parameters | Name | Type | Description | | -------------- | :-------: | -------------------------- | | `initialOwner` | `address` | The owner of the contract. |
### fallback :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#fallback) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) ::: :::info Whenever the call is associated with native tokens, the function will delegate the handling of native tokens internally to the [`universalReceiver`](#universalreceiver) function passing `_TYPEID_LSP0_VALUE_RECEIVED` as typeId and the calldata as received data, except when the native token will be sent directly to the extension. ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens with some calldata. 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), return.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens and extension function selector is not found or not payable.

### receive :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#receive) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) ::: :::info This function internally delegates the handling of native tokens to the [`universalReceiver`](#universalreceiver) function passing `_TYPEID_LSP0_VALUE_RECEIVED` as typeId and an empty bytes array as received data. ::: ```solidity receive() external payable; ``` Executed: - When receiving some native tokens without any additional data. - On empty calls to the contract.
**Emitted events:** - Emits a [`UniversalReceiver`](#universalreceiver) event when the `universalReceiver` logic is executed upon receiving native tokens.

### RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#renounce_ownership_confirmation_delay) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY()` - Function selector: `0xead3fbdf` ::: ```solidity function RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY() external view returns (uint256); ``` #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `uint256` | - |
### RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#renounce_ownership_confirmation_period) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD()` - Function selector: `0x01bfba61` ::: ```solidity function RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD() external view returns (uint256); ``` #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `uint256` | - |
### VERSION :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#version) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `VERSION()` - Function selector: `0xffa1ad74` ::: ```solidity function VERSION() external view returns (string); ``` _Contract version._ #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `string` | - |
### acceptOwnership :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `acceptOwnership()` - Function selector: `0x79ba5097` ::: ```solidity function acceptOwnership() external nonpayable; ``` _`msg.sender` is accepting ownership of contract: `address(this)`._ Transfer ownership of the contract from the current [`owner()`](#owner) to the [`pendingOwner()`](#pendingowner). Once this function is called: - The current [`owner()`](#owner) will lose access to the functions restricted to the [`owner()`](#owner) only. - The [`pendingOwner()`](#pendingowner) will gain access to the functions restricted to the [`owner()`](#owner) only.
**Requirements:** - Only the [`pendingOwner`](#pendingowner) can call this function. - When notifying the previous owner via LSP1, the typeId used must be the `keccak256(...)` hash of [LSP0OwnershipTransferred_SenderNotification]. - When notifying the new owner via LSP1, the typeId used must be the `keccak256(...)` hash of [LSP0OwnershipTransferred_RecipientNotification].

### batchCalls :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#batchcalls) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### execute :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#execute) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `execute(uint256,address,uint256,bytes)` - Function selector: `0x44c028fe` ::: ```solidity function execute( uint256 operationType, address target, uint256 value, bytes data ) external payable returns (bytes); ``` _Calling address `target` using `operationType`, transferring `value` wei and data: `data`._ Generic executor function to: - send native tokens to any address. - interact with any contract by passing an abi-encoded function call in the `data` parameter. - deploy a contract by providing its creation bytecode in the `data` parameter.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner. - If a `value` is provided, the contract must have at least this amount in its balance to execute successfully. - If the operation type is `CREATE` (1) or `CREATE2` (2), `target` must be `address(0)`. - If the operation type is `STATICCALL` (3) or `DELEGATECALL` (4), `value` transfer is disallowed and must be 0.
**Emitted events:** - [`Executed`](#executed) event for each call that uses under `operationType`: `CALL` (0), `STATICCALL` (3) and `DELEGATECALL` (4). - [`ContractCreated`](#contractcreated) event, when a contract is created under `operationType`: `CREATE` (1) and `CREATE2` (2). - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens.
#### Parameters | Name | Type | Description | | --------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `operationType` | `uint256` | The operation type used: CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4 | | `target` | `address` | The address of the EOA or smart contract. (unused if a contract is created via operation type 1 or 2) | | `value` | `uint256` | The amount of native tokens to transfer (in Wei) | | `data` | `bytes` | The call data, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-----: | ----------- | | `0` | `bytes` | - |
### executeBatch :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#executebatch) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `executeBatch(uint256[],address[],uint256[],bytes[])` - Function selector: `0x31858452` ::: :::caution Warning - The `msg.value` should not be trusted for any method called within the batch with `operationType`: `DELEGATECALL` (4). ::: ```solidity function executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) external payable returns (bytes[]); ``` _Calling multiple addresses `targets` using `operationsType`, transferring `values` wei and data: `datas`._ Batch executor function that behaves the same as [`execute`](#execute) but allowing multiple operations in the same transaction.
**Requirements:** - The length of the parameters provided must be equal. - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner. - If a `value` is provided, the contract must have at least this amount in its balance to execute successfully. - If the operation type is `CREATE` (1) or `CREATE2` (2), `target` must be `address(0)`. - If the operation type is `STATICCALL` (3) or `DELEGATECALL` (4), `value` transfer is disallowed and must be 0.
**Emitted events:** - [`Executed`](#executed) event for each call that uses under `operationType`: `CALL` (0), `STATICCALL` (3) and `DELEGATECALL` (4). (each iteration) - [`ContractCreated`](#contractcreated) event, when a contract is created under `operationType`: `CREATE` (1) and `CREATE2` (2) (each iteration) - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens.
#### Parameters | Name | Type | Description | | ---------------- | :---------: | --------------------------------------------------------------------------------------------------------------- | | `operationsType` | `uint256[]` | The list of operations type used: `CALL = 0`; `CREATE = 1`; `CREATE2 = 2`; `STATICCALL = 3`; `DELEGATECALL = 4` | | `targets` | `address[]` | The list of addresses to call. `targets` will be unused if a contract is created (operation types 1 and 2). | | `values` | `uint256[]` | The list of native token amounts to transfer (in Wei). | | `datas` | `bytes[]` | The list of calldata, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `bytes[]` | - |
### getData :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#getdata) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#getdatabatch) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### isValidSignature :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#isvalidsignature) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `isValidSignature(bytes32,bytes)` - Function selector: `0x1626ba7e` ::: :::caution Warning This function does not enforce by default the inclusion of the address of this contract in the signature digest. It is recommended that protocols or applications using this contract include the targeted address (= this contract) in the data to sign. To ensure that a signature is valid for a specific LSP0ERC725Account and prevent signatures from the same EOA to be replayed across different LSP0ERC725Accounts. ::: ```solidity function isValidSignature( bytes32 dataHash, bytes signature ) external view returns (bytes4 returnedStatus); ``` _Achieves the goal of [EIP-1271] by validating signatures of smart contracts according to their own logic._ Handles two cases: 1. If the owner is an EOA, recovers an address from the hash and the signature provided: - Returns the `_ERC1271_SUCCESSVALUE` if the address recovered is the same as the owner, indicating that it was a valid signature. - If the address is different, it returns the `_ERC1271_FAILVALUE` indicating that the signature is not valid. 2. If the owner is a smart contract, it forwards the call of [`isValidSignature()`](#isvalidsignature) to the owner contract: - If the contract fails or returns the `_ERC1271_FAILVALUE`, the [`isValidSignature()`](#isvalidsignature) on the account returns the `_ERC1271_FAILVALUE`, indicating that the signature is not valid. - If the [`isValidSignature()`](#isvalidsignature) on the owner returned the `_ERC1271_SUCCESSVALUE`, the [`isValidSignature()`](#isvalidsignature) on the account returns the `_ERC1271_SUCCESSVALUE`, indicating that it's a valid signature. #### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------------------------ | | `dataHash` | `bytes32` | The hash of the data to be validated. | | `signature` | `bytes` | A signature that can validate the previous parameter (Hash). | #### Returns | Name | Type | Description | | ---------------- | :------: | ----------------------------------------------------------------- | | `returnedStatus` | `bytes4` | A `bytes4` value that indicates if the signature is valid or not. |
### owner :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#owner) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### pendingOwner :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#pendingowner) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `pendingOwner()` - Function selector: `0xe30c3978` ::: :::info If no ownership transfer is in progress, the pendingOwner will be `address(0).`. ::: ```solidity function pendingOwner() external view returns (address); ``` The address that ownership of the contract is transferred to. This address may use [`acceptOwnership()`](#acceptownership) to gain ownership of the contract. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#renounceownership) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: :::danger Leaves the contract without an owner. Once ownership of the contract has been renounced, any functions that are restricted to be called by the owner or an address allowed by the owner will be permanently inaccessible, making these functions not callable anymore and unusable. ::: ```solidity function renounceOwnership() external nonpayable; ``` _`msg.sender` is renouncing ownership of contract `address(this)`._ Renounce ownership of the contract in a 2-step process. 1. The first call will initiate the process of renouncing ownership. 2. The second call is used as a confirmation and will leave the contract without an owner.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner.

### setData :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#setdata) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens. - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#setdatabatch) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens. - [`DataChanged`](#datachanged) event. (on each iteration of setting data)
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#supportsinterface) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` _Checking if this contract supports the interface defined by the `bytes4` interface ID `interfaceId`._ Achieves the goal of [ERC-165] to detect supported interfaces and [LSP-17-ContractExtension] by checking if the interfaceId being queried is supported on another linked extension. If the contract doesn't support the `interfaceId`, it forwards the call to the `supportsInterface` extension according to [LSP-17-ContractExtension], and checks if the extension implements the interface defined by `interfaceId`. #### Parameters | Name | Type | Description | | ------------- | :------: | ------------------------------------------------------ | | `interfaceId` | `bytes4` | The interface ID to check if the contract supports it. | #### Returns | Name | Type | Description | | ---- | :----: | --------------------------------------------------------------------------------------------- | | `0` | `bool` | `true` if this contract implements the interface defined by `interfaceId`, `false` otherwise. |
### transferOwnership :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address pendingNewOwner) external nonpayable; ``` _Transfer ownership initiated by `newOwner`._ Initiate the process of transferring ownership of the contract by setting the new owner as the pending owner. If the new owner is a contract that supports + implements LSP1, this will also attempt to notify the new owner that ownership has been transferred to them by calling the [`universalReceiver()`](#universalreceiver) function on the `newOwner` contract.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner. - When notifying the new owner via LSP1, the `typeId` used must be the `keccak256(...)` hash of [LSP0OwnershipTransferStarted]. - Pending owner cannot accept ownership in the same tx via the LSP1 hook.
#### Parameters | Name | Type | Description | | ----------------- | :-------: | ----------- | | `pendingNewOwner` | `address` | - |
### universalReceiver :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#universalreceiver) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Function signature: `universalReceiver(bytes32,bytes)` - Function selector: `0x6bb56a14` ::: ```solidity function universalReceiver( bytes32 typeId, bytes receivedData ) external payable returns (bytes returnedValues); ``` _Notifying the contract by calling its `universalReceiver` function with the following information: typeId: `typeId`; data: `data`._ Achieves the goal of [LSP-1-UniversalReceiver] by allowing the account to be notified about incoming/outgoing transactions and enabling reactions to these actions. The reaction is achieved by having two external contracts ([LSP1UniversalReceiverDelegate]) that react on the whole transaction and on the specific typeId, respectively. The function performs the following steps: 1. Query the [ERC-725Y] storage with the data key [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]. - If there is an address stored under the data key, check if this address supports the LSP1 interfaceId. - If yes, call this address with the typeId and data (params), along with additional calldata consisting of 20 bytes of `msg.sender` and 32 bytes of `msg.value`. If not, continue the execution of the function. 2. Query the [ERC-725Y] storage with the data key [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX] + `bytes32(typeId)`. (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is an address stored under the data key, check if this address supports the LSP1 interfaceId. - If yes, call this address with the typeId and data (params), along with additional calldata consisting of 20 bytes of `msg.sender` and 32 bytes of `msg.value`. If not, continue the execution of the function. This function delegates internally the handling of native tokens to the [`universalReceiver`](#universalreceiver) function itself passing `_TYPEID_LSP0_VALUE_RECEIVED` as typeId and the calldata as received data.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) when receiving native tokens. - [`UniversalReceiver`](#universalreceiver) event with the function parameters, call options, and the response of the UniversalReceiverDelegates (URD) contract that was called.
#### Parameters | Name | Type | Description | | -------------- | :-------: | -------------------------- | | `typeId` | `bytes32` | The type of call received. | | `receivedData` | `bytes` | The data received. | #### Returns | Name | Type | Description | | ---------------- | :-----: | ------------------------------------------------------------------------------------------------------- | | `returnedValues` | `bytes` | The ABI encoded return value of the LSP1UniversalReceiverDelegate call and the LSP1TypeIdDelegate call. |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_execute ```solidity function _execute( uint256 operationType, address target, uint256 value, bytes data ) internal nonpayable returns (bytes); ``` check the `operationType` provided and perform the associated low-level opcode after checking for requirements (see [`execute`](#execute)).
### \_executeBatch ```solidity function _executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) internal nonpayable returns (bytes[]); ``` check each `operationType` provided in the batch and perform the associated low-level opcode after checking for requirements (see [`executeBatch`](#executebatch)).
### \_executeCall ```solidity function _executeCall( address target, uint256 value, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level call (operation type = 0) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------- | | `target` | `address` | The address on which call is executed | | `value` | `uint256` | The value to be sent with the call | | `data` | `bytes` | The data to be sent with the call | #### Returns | Name | Type | Description | | -------- | :-----: | ---------------------- | | `result` | `bytes` | The data from the call |
### \_executeStaticCall ```solidity function _executeStaticCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level staticcall (operation type = 3) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------- | | `target` | `address` | The address on which staticcall is executed | | `data` | `bytes` | The data to be sent with the staticcall | #### Returns | Name | Type | Description | | -------- | :-----: | ------------------------------------- | | `result` | `bytes` | The data returned from the staticcall |
### \_executeDelegateCall :::caution Warning The `msg.value` should not be trusted for any method called with `operationType`: `DELEGATECALL` (4). ::: ```solidity function _executeDelegateCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level delegatecall (operation type = 4) #### Parameters | Name | Type | Description | | -------- | :-------: | --------------------------------------------- | | `target` | `address` | The address on which delegatecall is executed | | `data` | `bytes` | The data to be sent with the delegatecall | #### Returns | Name | Type | Description | | -------- | :-----: | --------------------------------------- | | `result` | `bytes` | The data returned from the delegatecall |
### \_deployCreate ```solidity function _deployCreate( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE` opcode (operation type = 1) #### Parameters | Name | Type | Description | | -------------- | :-------: | ---------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_deployCreate2 ```solidity function _deployCreate2( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE2` opcode (operation type = 2) #### Parameters | Name | Type | Description | | -------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) and a bytes32 salt | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` Write a `dataValue` to the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ```
**Emitted events:** - [`DataChanged`](#datachanged) event emitted after a successful `setData` call.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to write the associated `bytes` value to the store. | | `dataValue` | `bytes` | The `bytes` value to associate with the given `dataKey` in the ERC725Y storage. |
### \_transferOwnership ```solidity function _transferOwnership(address newOwner) internal nonpayable; ``` Set the pending owner of the contract and cancel any renounce ownership process that was previously started.
**Requirements:** - `newOwner` cannot be the address of the contract itself.
#### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------- | | `newOwner` | `address` | The address of the new pending owner. |
### \_acceptOwnership ```solidity function _acceptOwnership() internal nonpayable; ``` Set the pending owner of the contract as the new owner.
### \_renounceOwnership ```solidity function _renounceOwnership() internal nonpayable; ``` Initiate or confirm the process of renouncing ownership after a specific delay of blocks have passed.
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address and the boolean indicating whether to forward the value received to the extension, stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0). - If the stored value is 20 bytes, return false for the boolean
### \_fallbackLSP17Extendable :::tip Hint If you would like to forward the `msg.value` to the extension contract, you should store an additional `0x01` byte after the address of the extension under the corresponding LSP17 data key. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the `address(0)` will be returned. Forwards the value sent with the call to the extension if the function selector is mapped to a payable extension. Reverts if there is no extension for the function being called, except for the `bytes4(0)` function selector, which passes even if there is no extension for it. If there is an extension for the function selector being called, it calls the extension with the `CALL` opcode, passing the `msg.data` appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the `msg.value`.
### \_verifyCall ```solidity function _verifyCall( address logicVerifier ) internal nonpayable returns (bool verifyAfter); ``` Calls [`lsp20VerifyCall`](#lsp20verifycall) function on the logicVerifier.
### \_verifyCallResult ```solidity function _verifyCallResult( address logicVerifier, bytes callResult ) internal nonpayable; ``` Calls [`lsp20VerifyCallResult`](#lsp20verifycallresult) function on the logicVerifier.
### \_revertWithLSP20DefaultError ```solidity function _revertWithLSP20DefaultError( bool postCall, bytes returnedData ) internal pure; ```
## Events ### ContractCreated :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#contractcreated) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Event signature: `ContractCreated(uint256,address,uint256,bytes32)` - Event topic hash: `0xa1fb700aaee2ae4a2ff6f91ce7eba292f89c2f5488b8ec4c5c5c8150692595c3` ::: ```solidity event ContractCreated( uint256 indexed operationType, address indexed contractAddress, uint256 value, bytes32 indexed salt ); ``` _Deployed new contract at address `contractAddress` and funded with `value` wei (deployed using opcode: `operationType`)._ Emitted when a new contract was created and deployed. #### Parameters | Name | Type | Description | | ------------------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The opcode used to deploy the contract (`CREATE` or `CREATE2`). | | `contractAddress` **`indexed`** | `address` | The created contract address. | | `value` | `uint256` | The amount of native tokens (in Wei) sent to fund the created contract on deployment. | | `salt` **`indexed`** | `bytes32` | The salt used to deterministically deploy the contract (`CREATE2` only). If `CREATE` opcode is used, the salt value will be `bytes32(0)`. |
### DataChanged :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#datachanged) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Executed :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#executed) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Event signature: `Executed(uint256,address,uint256,bytes4)` - Event topic hash: `0x4810874456b8e6487bd861375cf6abd8e1c8bb5858c8ce36a86a04dabfac199e` ::: ```solidity event Executed( uint256 indexed operationType, address indexed target, uint256 value, bytes4 indexed selector ); ``` _Called address `target` using `operationType` with `value` wei and `data`._ Emitted when calling an address `target` (EOA or contract) with `value`. #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ---------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The low-level call opcode used to call the `target` address (`CALL`, `STATICALL` or `DELEGATECALL`). | | `target` **`indexed`** | `address` | The address to call. `target` will be unused if a contract is created (operation types 1 and 2). | | `value` | `uint256` | The amount of native tokens transferred along the call (in Wei). | | `selector` **`indexed`** | `bytes4` | The first 4 bytes (= function selector) of the data sent with the call. |
### OwnershipRenounced :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#ownershiprenounced) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Event signature: `OwnershipRenounced()` - Event topic hash: `0xd1f66c3d2bc1993a86be5e3d33709d98f0442381befcedd29f578b9b2506b1ce` ::: ```solidity event OwnershipRenounced(); ``` _Successfully renounced ownership of the contract. This contract is now owned by anyone, it's owner is `address(0)`._ Emitted when the ownership of the contract has been renounced.
### OwnershipTransferStarted :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#ownershiptransferstarted) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Event signature: `OwnershipTransferStarted(address,address)` - Event topic hash: `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` ::: ```solidity event OwnershipTransferStarted( address indexed previousOwner, address indexed newOwner ); ``` _The transfer of ownership of the contract was initiated. Pending new owner set to: `newOwner`._ Emitted when [`transferOwnership(..)`](#transferownership) was called and the first step of transferring ownership completed successfully which leads to [`pendingOwner`](#pendingowner) being updated. #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ---------------------------------- | | `previousOwner` **`indexed`** | `address` | The address of the previous owner. | | `newOwner` **`indexed`** | `address` | The address of the new owner. |
### OwnershipTransferred :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#ownershiptransferred) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### RenounceOwnershipStarted :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#renounceownershipstarted) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Event signature: `RenounceOwnershipStarted()` - Event topic hash: `0x81b7f830f1f0084db6497c486cbe6974c86488dcc4e3738eab94ab6d6b1653e7` ::: ```solidity event RenounceOwnershipStarted(); ``` _Ownership renouncement initiated._ Emitted when starting the [`renounceOwnership(..)`](#renounceownership) 2-step process.
### UniversalReceiver :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#universalreceiver) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Event signature: `UniversalReceiver(address,uint256,bytes32,bytes,bytes)` - Event topic hash: `0x9c3ba68eb5742b8e3961aea0afc7371a71bf433c8a67a831803b64c064a178c2` ::: ```solidity event UniversalReceiver( address indexed from, uint256 indexed value, bytes32 indexed typeId, bytes receivedData, bytes returnedValue ); ``` \*Address `from` called the `universalReceiver(...)` function while sending `value` LYX. Notification type (typeId): `typeId` - Data received: `receivedData`.\* Emitted when the [`universalReceiver`](#universalreceiver) function was called with a specific `typeId` and some `receivedData` #### Parameters | Name | Type | Description | | ---------------------- | :-------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` **`indexed`** | `address` | The address of the EOA or smart contract that called the [`universalReceiver(...)`](#universalreceiver) function. | | `value` **`indexed`** | `uint256` | The amount sent to the [`universalReceiver(...)`](#universalreceiver) function. | | `typeId` **`indexed`** | `bytes32` | A `bytes32` unique identifier (= _"hook"_)that describe the type of notification, information or transaction received by the contract. Can be related to a specific standard or a hook. | | `receivedData` | `bytes` | Any arbitrary data that was sent to the [`universalReceiver(...)`](#universalreceiver) function. | | `returnedValue` | `bytes` | The value returned by the [`universalReceiver(...)`](#universalreceiver) function. |
## Errors ### ERC725X_ContractDeploymentFailed :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_contractdeploymentfailed) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725X_ContractDeploymentFailed()` - Error hash: `0x0b07489b` ::: ```solidity error ERC725X_ContractDeploymentFailed(); ``` Reverts when contract deployment failed via [`execute`](#execute) or [`executeBatch`](#executebatch) functions, This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_CreateOperationsRequireEmptyRecipientAddress :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_createoperationsrequireemptyrecipientaddress) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725X_CreateOperationsRequireEmptyRecipientAddress()` - Error hash: `0x3041824a` ::: ```solidity error ERC725X_CreateOperationsRequireEmptyRecipientAddress(); ``` Reverts when passing a `to` address that is not `address(0)` (= address zero) while deploying a contract via [`execute`](#execute) or [`executeBatch`](#executebatch) functions. This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_ExecuteParametersEmptyArray :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_executeparametersemptyarray) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725X_ExecuteParametersEmptyArray()` - Error hash: `0xe9ad2b5f` ::: ```solidity error ERC725X_ExecuteParametersEmptyArray(); ``` Reverts when one of the array parameter provided to the [`executeBatch`](#executebatch) function is an empty array.
### ERC725X_ExecuteParametersLengthMismatch :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_executeparameterslengthmismatch) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725X_ExecuteParametersLengthMismatch()` - Error hash: `0x3ff55f4d` ::: ```solidity error ERC725X_ExecuteParametersLengthMismatch(); ``` Reverts when there is not the same number of elements in the `operationTypes`, `targets` addresses, `values`, and `datas` array parameters provided when calling the [`executeBatch`](#executebatch) function.
### ERC725X_InsufficientBalance :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_insufficientbalance) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725X_InsufficientBalance(uint256,uint256)` - Error hash: `0x0df9a8f8` ::: ```solidity error ERC725X_InsufficientBalance(uint256 balance, uint256 value); ``` Reverts when trying to send more native tokens `value` than available in current `balance`. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `balance` | `uint256` | The balance of native tokens of the ERC725X smart contract. | | `value` | `uint256` | The amount of native tokens sent via `ERC725X.execute(...)`/`ERC725X.executeBatch(...)` that is greater than the contract's `balance`. |
### ERC725X_MsgValueDisallowedInDelegateCall :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_msgvaluedisallowedindelegatecall) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725X_MsgValueDisallowedInDelegateCall()` - Error hash: `0x5ac83135` ::: ```solidity error ERC725X_MsgValueDisallowedInDelegateCall(); ``` Reverts when trying to send native tokens (`value` / `values[]` parameter of [`execute`](#execute) or [`executeBatch`](#executebatch) functions) while making a `delegatecall` (`operationType == 4`). Sending native tokens via `staticcall` is not allowed because `msg.value` is persisting.
### ERC725X_MsgValueDisallowedInStaticCall :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_msgvaluedisallowedinstaticcall) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725X_MsgValueDisallowedInStaticCall()` - Error hash: `0x72f2bc6a` ::: ```solidity error ERC725X_MsgValueDisallowedInStaticCall(); ``` Reverts when trying to send native tokens (`value` / `values[]` parameter of [`execute`](#execute) or [`executeBatch`](#executebatch) functions) while making a `staticcall` (`operationType == 3`). Sending native tokens via `staticcall` is not allowed because it is a state changing operation.
### ERC725X_NoContractBytecodeProvided :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_nocontractbytecodeprovided) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725X_NoContractBytecodeProvided()` - Error hash: `0xb81cd8d9` ::: ```solidity error ERC725X_NoContractBytecodeProvided(); ``` Reverts when no contract bytecode was provided as parameter when trying to deploy a contract via [`execute`](#execute) or [`executeBatch`](#executebatch). This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_UnknownOperationType :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_unknownoperationtype) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725X_UnknownOperationType(uint256)` - Error hash: `0x7583b3bc` ::: ```solidity error ERC725X_UnknownOperationType(uint256 operationTypeProvided); ``` Reverts when the `operationTypeProvided` is none of the default operation types available. (CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4) #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ------------------------------------------------------------------------------------------------------ | | `operationTypeProvided` | `uint256` | The unrecognised operation type number provided to `ERC725X.execute(...)`/`ERC725X.executeBatch(...)`. |
### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### LSP14CallerNotPendingOwner :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp14callernotpendingowner) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `LSP14CallerNotPendingOwner(address)` - Error hash: `0x451e4528` ::: ```solidity error LSP14CallerNotPendingOwner(address caller); ``` Reverts when the `caller` that is trying to accept ownership of the contract is not the pending owner. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------- | | `caller` | `address` | The address that tried to accept ownership. |
### LSP14CannotTransferOwnershipToSelf :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp14cannottransferownershiptoself) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `LSP14CannotTransferOwnershipToSelf()` - Error hash: `0xe052a6f8` ::: ```solidity error LSP14CannotTransferOwnershipToSelf(); ``` _Cannot transfer ownership to the address of the contract itself._ Reverts when trying to transfer ownership to the `address(this)`.
### LSP14MustAcceptOwnershipInSeparateTransaction :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp14mustacceptownershipinseparatetransaction) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `LSP14MustAcceptOwnershipInSeparateTransaction()` - Error hash: `0x5758dd07` ::: ```solidity error LSP14MustAcceptOwnershipInSeparateTransaction(); ``` _Cannot accept ownership in the same transaction with [`transferOwnership(...)`](#transferownership)._ Reverts when pending owner accept ownership in the same transaction of transferring ownership.
### LSP14NotInRenounceOwnershipInterval :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp14notinrenounceownershipinterval) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `LSP14NotInRenounceOwnershipInterval(uint256,uint256)` - Error hash: `0x1b080942` ::: ```solidity error LSP14NotInRenounceOwnershipInterval( uint256 renounceOwnershipStart, uint256 renounceOwnershipEnd ); ``` _Cannot confirm ownership renouncement yet. The ownership renouncement is allowed from: `renounceOwnershipStart` until: `renounceOwnershipEnd`._ Reverts when trying to renounce ownership before the initial confirmation delay. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ----------------------------------------------------------------------- | | `renounceOwnershipStart` | `uint256` | The start timestamp when one can confirm the renouncement of ownership. | | `renounceOwnershipEnd` | `uint256` | The end timestamp when one can confirm the renouncement of ownership. |
### LSP20CallVerificationFailed :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp20callverificationfailed) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `LSP20CallVerificationFailed(bool,bytes4)` - Error hash: `0x9d6741e3` ::: ```solidity error LSP20CallVerificationFailed(bool postCall, bytes4 returnedStatus); ``` reverts when the call to the owner does not return the LSP20 success value #### Parameters | Name | Type | Description | | ---------------- | :------: | ------------------------------------------------------- | | `postCall` | `bool` | True if the execution call was done, False otherwise | | `returnedStatus` | `bytes4` | The bytes4 decoded data returned by the logic verifier. |
### LSP20CallingVerifierFailed :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp20callingverifierfailed) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `LSP20CallingVerifierFailed(bool)` - Error hash: `0x8c6a8ae3` ::: ```solidity error LSP20CallingVerifierFailed(bool postCall); ``` reverts when the call to the owner fail with no revert reason #### Parameters | Name | Type | Description | | ---------- | :----: | ---------------------------------------------------- | | `postCall` | `bool` | True if the execution call was done, False otherwise |
### LSP20EOACannotVerifyCall :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp20eoacannotverifycall) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `LSP20EOACannotVerifyCall(address)` - Error hash: `0x0c392301` ::: ```solidity error LSP20EOACannotVerifyCall(address logicVerifier); ``` Reverts when the logic verifier is an Externally Owned Account (EOA) that cannot return the LSP20 success value. #### Parameters | Name | Type | Description | | --------------- | :-------: | --------------------------------- | | `logicVerifier` | `address` | The address of the logic verifier |
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-0-ERC725Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP0ERC725Account.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP11BasicSocialRecovery :::info Standard Specifications [`LSP-11-BasicSocialRecovery`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md) ::: :::info Solidity implementation [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) ::: > Implementation of LSP11 - Social Recovery standard Sets permission for a controller address after a recovery process to interact with an ERC725 contract via the LSP6KeyManager ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) ::: ```solidity constructor(address _owner, address target_); ``` _Sets the target and the owner addresses_ #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------- | | `_owner` | `address` | The owner of the LSP11 contract | | `target_` | `address` | The address of the ER725 contract to recover |
### addGuardian :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#addguardian) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `addGuardian(address)` - Function selector: `0xa526d83b` ::: ```solidity function addGuardian(address newGuardian) external nonpayable; ``` Adds a guardian of the targetCan be called only by the owner #### Parameters | Name | Type | Description | | ------------- | :-------: | -------------------------------- | | `newGuardian` | `address` | The address to add as a guardian |
### getGuardianChoice :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#getguardianchoice) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `getGuardianChoice(address)` - Function selector: `0xf6a22f02` ::: ```solidity function getGuardianChoice(address guardian) external view returns (address); ``` Returns the address of a controller that a `guardian` selected for in order to recover the target #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------ | | `guardian` | `address` | the address of a guardian to query his selection | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------ | | `0` | `address` | the address that `guardian` selected |
### getGuardians :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#getguardians) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `getGuardians()` - Function selector: `0x0665f04b` ::: ```solidity function getGuardians() external view returns (address[]); ``` Returns the addresses of all guardians The guardians will select an address to be added as a controller key for the linked `target` if he reaches the guardian threshold and provide the correct string that produce the secretHash #### Returns | Name | Type | Description | | ---- | :---------: | ----------- | | `0` | `address[]` | - |
### getGuardiansThreshold :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#getguardiansthreshold) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `getGuardiansThreshold()` - Function selector: `0x187c5348` ::: ```solidity function getGuardiansThreshold() external view returns (uint256); ``` Returns the guardian threshold The guardian threshold represents the minimum number of selection by guardians required for an address to start a recovery process #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `uint256` | - |
### getRecoveryCounter :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#getrecoverycounter) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `getRecoveryCounter()` - Function selector: `0xf79c8b77` ::: ```solidity function getRecoveryCounter() external view returns (uint256); ``` Returns the current recovery counter When a recovery process is successfully finished the recovery counter is incremented #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `uint256` | - |
### getRecoverySecretHash :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#getrecoverysecrethash) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `getRecoverySecretHash()` - Function selector: `0x8f9083bb` ::: ```solidity function getRecoverySecretHash() external view returns (bytes32); ``` Returns the recovery secret hash #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `bytes32` | - |
### isGuardian :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#isguardian) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `isGuardian(address)` - Function selector: `0x0c68ba21` ::: ```solidity function isGuardian(address _address) external view returns (bool); ``` Returns TRUE if the address provided is a guardian, FALSE otherwise #### Parameters | Name | Type | Description | | ---------- | :-------: | -------------------- | | `_address` | `address` | The address to query | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### owner :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#owner) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### recoverOwnership :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#recoverownership) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `recoverOwnership(address,string,bytes32)` - Function selector: `0xae8481b2` ::: ```solidity function recoverOwnership( address recoverer, string plainSecret, bytes32 newSecretHash ) external nonpayable; ``` Recovers the ownership permissions of an address in the linked target and increment the recover counter Requirements - the address of the recoverer must have a selection equal or higher than the threshold defined in `getGuardiansThreshold(...)` - must have provided the right `plainSecret` that produces the secret Hash #### Parameters | Name | Type | Description | | --------------- | :-------: | -------------------------------------------- | | `recoverer` | `address` | The address of the recoverer | | `plainSecret` | `string` | The secret word that produce the secret Hash | | `newSecretHash` | `bytes32` | - |
### removeGuardian :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#removeguardian) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `removeGuardian(address)` - Function selector: `0x71404156` ::: ```solidity function removeGuardian(address existingGuardian) external nonpayable; ``` Removes a guardian of the targetCan be called only by the owner #### Parameters | Name | Type | Description | | ------------------ | :-------: | ----------- | | `existingGuardian` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#renounceownership) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### selectNewController :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#selectnewcontroller) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `selectNewController(address)` - Function selector: `0xaa7806d6` ::: ```solidity function selectNewController(address addressSelected) external nonpayable; ``` select an address to be a potential controller address if he reaches the guardian threshold and provide the correct secret string Requirements: - only guardians can select an address #### Parameters | Name | Type | Description | | ----------------- | :-------: | ------------------------------------ | | `addressSelected` | `address` | The address selected by the guardian |
### setGuardiansThreshold :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#setguardiansthreshold) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `setGuardiansThreshold(uint256)` - Function selector: `0x6bfed20b` ::: ```solidity function setGuardiansThreshold(uint256 newThreshold) external nonpayable; ``` Sets the minimum number of selection by the guardians required so that an address can recover ownershipCan be called only by the owner #### Parameters | Name | Type | Description | | -------------- | :-------: | ----------- | | `newThreshold` | `uint256` | - |
### setRecoverySecretHash :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#setrecoverysecrethash) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `setRecoverySecretHash(bytes32)` - Function selector: `0xf799e38d` ::: ```solidity function setRecoverySecretHash( bytes32 newRecoverSecretHash ) external nonpayable; ``` Throws if hash provided is bytes32(0) #### Parameters | Name | Type | Description | | ---------------------- | :-------: | ------------------------------------------------------------------------------- | | `newRecoverSecretHash` | `bytes32` | The hash of the secret string Requirements: - `secretHash` cannot be bytes32(0) |
### supportsInterface :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#supportsinterface) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 _interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | -------------- | :------: | ----------- | | `_interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### target :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#target) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `target()` - Function selector: `0xd4b83992` ::: ```solidity function target() external view returns (address); ``` The address of an ERC725 contract where we want to recover and set permissions for a controller address #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### transferOwnership :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#transferownership) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_validateRequirements ```solidity function _validateRequirements( address recoverer, uint256 currentRecoveryCounter, string plainSecret, bytes32 newHash, address[] guardians ) internal view; ``` The number of guardians should be reasonable, as the validation method is using a loop to check the selection of each guardian Throws if: - The address trying to recover didn't reach the guardiansThreshold - The new hash being set is bytes32(0) - The secret word provided is incorrect
### \_cleanStorage ```solidity function _cleanStorage( uint256 recoveryCounter, uint256 guardiansLength, address[] guardians ) internal nonpayable; ``` Remove the guardians choice after a successful recovery process To avoid keeping unnecessary state
## Events ### GuardianAdded :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#guardianadded) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Event signature: `GuardianAdded(address)` - Event topic hash: `0x038596bb31e2e7d3d9f184d4c98b310103f6d7f5830e5eec32bffe6f1728f969` ::: ```solidity event GuardianAdded(address indexed newGuardian); ``` _Emitted when setting a new guardian for the target_ #### Parameters | Name | Type | Description | | --------------------------- | :-------: | --------------------------------- | | `newGuardian` **`indexed`** | `address` | The address of the added guardian |
### GuardianRemoved :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#guardianremoved) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Event signature: `GuardianRemoved(address)` - Event topic hash: `0xb8107d0c6b40be480ce3172ee66ba6d64b71f6b1685a851340036e6e2e3e3c52` ::: ```solidity event GuardianRemoved(address indexed removedGuardian); ``` _Emitted when removing an existing guardian for the target_ #### Parameters | Name | Type | Description | | ------------------------------- | :-------: | ----------------------------------- | | `removedGuardian` **`indexed`** | `address` | The address of the guardian removed |
### GuardiansThresholdChanged :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#guardiansthresholdchanged) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Event signature: `GuardiansThresholdChanged(uint256)` - Event topic hash: `0x7146d20a2c7b7c75c203774c9f241b61698fac43a4a81ccd828f0d8162392790` ::: ```solidity event GuardiansThresholdChanged(uint256 indexed guardianThreshold); ``` _Emitted when changing the guardian threshold_ #### Parameters | Name | Type | Description | | --------------------------------- | :-------: | ----------------------------------------------------------------------------------------------- | | `guardianThreshold` **`indexed`** | `uint256` | The minimum number of selection by guardians needed by a controller to start a recovery process |
### OwnershipTransferred :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#ownershiptransferred) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### RecoveryProcessSuccessful :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#recoveryprocesssuccessful) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Event signature: `RecoveryProcessSuccessful(uint256,address,bytes32,address[])` - Event topic hash: `0xf4ff8803d6b43af46d48c200977209829c2f42f19f27eda1c89dbf26a28009cd` ::: ```solidity event RecoveryProcessSuccessful( uint256 indexed recoveryCounter, address indexed newController, bytes32 indexed newSecretHash, address[] guardians ); ``` _Emitted when the recovery process is finished by the controller who reached the guardian threshold and submitted the string that produce the secretHash_ #### Parameters | Name | Type | Description | | ------------------------------- | :---------: | -------------------------------------------------------------------------- | | `recoveryCounter` **`indexed`** | `uint256` | The current recovery process | | `newController` **`indexed`** | `address` | The address of the new controller controlling the target by the KeyManager | | `newSecretHash` **`indexed`** | `bytes32` | - | | `guardians` | `address[]` | The array of addresses containing the guardians of the target |
### SecretHashChanged :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#secrethashchanged) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Event signature: `SecretHashChanged(bytes32)` - Event topic hash: `0x2e8c5419a62207ade549fe0b66c1c85c16f5e1ed654815dee3a3f3ac41770df3` ::: ```solidity event SecretHashChanged(bytes32 indexed secretHash); ``` _Emitted when changing the secret hash_ #### Parameters | Name | Type | Description | | -------------------------- | :-------: | --------------------------------------------------- | | `secretHash` **`indexed`** | `bytes32` | The secret hash used to finish the recovery process |
### SelectedNewController :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#selectednewcontroller) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Event signature: `SelectedNewController(uint256,address,address)` - Event topic hash: `0xe43f3c1093c69ab76b2cf6246090acb2f8eab7f19ba9942dfc8b8ec446e3a3de` ::: ```solidity event SelectedNewController( uint256 indexed recoveryCounter, address indexed guardian, address indexed addressSelected ); ``` _Emitted when a guardian select a new potential controller address for the target_ #### Parameters | Name | Type | Description | | ------------------------------- | :-------: | ------------------------------------ | | `recoveryCounter` **`indexed`** | `uint256` | The current recovery process counter | | `guardian` **`indexed`** | `address` | The address of the guardian | | `addressSelected` **`indexed`** | `address` | The address selected by the guardian |
## Errors ### AddressZeroNotAllowed :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#addresszeronotallowed) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `AddressZeroNotAllowed()` - Error hash: `0x0855380c` ::: ```solidity error AddressZeroNotAllowed(); ``` reverts when the address zero calls `recoverOwnership(..)` function
### CallerIsNotGuardian :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#callerisnotguardian) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `CallerIsNotGuardian(address)` - Error hash: `0x5560e16d` ::: ```solidity error CallerIsNotGuardian(address caller); ``` reverts when the caller is not a guardian #### Parameters | Name | Type | Description | | -------- | :-------: | ----------- | | `caller` | `address` | - |
### GuardianAlreadyExist :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#guardianalreadyexist) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `GuardianAlreadyExist(address)` - Error hash: `0xd52858db` ::: ```solidity error GuardianAlreadyExist(address addressToAdd); ``` reverts when adding an already existing guardian #### Parameters | Name | Type | Description | | -------------- | :-------: | ----------- | | `addressToAdd` | `address` | - |
### GuardianDoNotExist :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#guardiandonotexist) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `GuardianDoNotExist(address)` - Error hash: `0x3d8e524e` ::: ```solidity error GuardianDoNotExist(address addressToRemove); ``` reverts when removing a non-existing guardian #### Parameters | Name | Type | Description | | ----------------- | :-------: | ----------- | | `addressToRemove` | `address` | - |
### GuardiansNumberCannotGoBelowThreshold :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#guardiansnumbercannotgobelowthreshold) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `GuardiansNumberCannotGoBelowThreshold(uint256)` - Error hash: `0x27113777` ::: ```solidity error GuardiansNumberCannotGoBelowThreshold(uint256 guardianThreshold); ``` reverts when removing a guardian and the threshold is equal to the number of guardians #### Parameters | Name | Type | Description | | ------------------- | :-------: | ----------- | | `guardianThreshold` | `uint256` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#ownablecallernottheowner) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
### SecretHashCannotBeZero :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#secrethashcannotbezero) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `SecretHashCannotBeZero()` - Error hash: `0x7f617002` ::: ```solidity error SecretHashCannotBeZero(); ``` reverts when the secret hash provided is equal to bytes32(0)
### ThresholdCannotBeHigherThanGuardiansNumber :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#thresholdcannotbehigherthanguardiansnumber) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `ThresholdCannotBeHigherThanGuardiansNumber(uint256,uint256)` - Error hash: `0xe3db80bd` ::: ```solidity error ThresholdCannotBeHigherThanGuardiansNumber( uint256 thresholdGiven, uint256 guardianNumber ); ``` reverts when setting the guardians threshold to a number higher than the guardians number #### Parameters | Name | Type | Description | | ---------------- | :-------: | ----------- | | `thresholdGiven` | `uint256` | - | | `guardianNumber` | `uint256` | - |
### ThresholdNotReachedForRecoverer :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#thresholdnotreachedforrecoverer) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `ThresholdNotReachedForRecoverer(address,uint256,uint256)` - Error hash: `0xf78f0507` ::: ```solidity error ThresholdNotReachedForRecoverer( address recoverer, uint256 selections, uint256 guardiansThreshold ); ``` reverts when `recoverOwnership(..)` is called with a recoverer that didn't reach the guardians threshold #### Parameters | Name | Type | Description | | -------------------- | :-------: | ------------------------------------------------ | | `recoverer` | `address` | The address of the recoverer | | `selections` | `uint256` | The number of selections that the recoverer have | | `guardiansThreshold` | `uint256` | The minimum number of selection needed |
### WrongPlainSecret :::note References - Specification details: [**LSP-11-BasicSocialRecovery**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-11-BasicSocialRecovery.md#wrongplainsecret) - Solidity implementation: [`LSP11BasicSocialRecovery.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp11-contracts/contracts/LSP11SocialRecovery.sol) - Error signature: `WrongPlainSecret()` - Error hash: `0x6fa723c3` ::: ```solidity error WrongPlainSecret(); ``` reverts when the plain secret produce a different hash than the secret hash originally set
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP14Ownable2Step :::info Standard Specifications [`LSP-14-Ownable2Step`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md) ::: :::info Solidity implementation [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) ::: > LSP14Ownable2Step This contract is a modified version of the [`OwnableUnset.sol`] implementation, where transferring and renouncing ownership works as a 2-step process. This can be used as a confirmation mechanism to prevent potential mistakes when transferring ownership of the contract, where the control of the contract could be lost forever. (_e.g: providing the wrong address as a parameter to the function, transferring ownership to an EOA for which the user lost its private key, etc..._) ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#renounce_ownership_confirmation_delay) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Function signature: `RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY()` - Function selector: `0xead3fbdf` ::: ```solidity function RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY() external view returns (uint256); ``` The number of block that MUST pass before one is able to confirm renouncing ownership. #### Returns | Name | Type | Description | | ---- | :-------: | ----------------- | | `0` | `uint256` | Number of blocks. |
### RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#renounce_ownership_confirmation_period) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Function signature: `RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD()` - Function selector: `0x01bfba61` ::: ```solidity function RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD() external view returns (uint256); ``` The number of blocks during which one can renounce ownership. #### Returns | Name | Type | Description | | ---- | :-------: | ----------------- | | `0` | `uint256` | Number of blocks. |
### acceptOwnership :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#acceptownership) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Function signature: `acceptOwnership()` - Function selector: `0x79ba5097` ::: ```solidity function acceptOwnership() external nonpayable; ``` _`msg.sender` is accepting ownership of contract: `address(this)`._ Transfer ownership of the contract from the current [`owner()`](#owner) to the [`pendingOwner()`](#pendingowner). Once this function is called: - The current [`owner()`](#owner) will lose access to the functions restricted to the [`owner()`](#owner) only. - The [`pendingOwner()`](#pendingowner) will gain access to the functions restricted to the [`owner()`](#owner) only.
**Requirements:** - This function can only be called by the [`pendingOwner()`](#pendingowner).

### owner :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#owner) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### pendingOwner :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#pendingowner) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Function signature: `pendingOwner()` - Function selector: `0xe30c3978` ::: :::info If no ownership transfer is in progress, the pendingOwner will be `address(0).`. ::: ```solidity function pendingOwner() external view returns (address); ``` The address that ownership of the contract is transferred to. This address may use [`acceptOwnership()`](#acceptownership) to gain ownership of the contract. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#renounceownership) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: :::danger Leaves the contract without an owner. Once ownership of the contract has been renounced, any function that is restricted to be called only by the owner will be permanently inaccessible, making these functions not callable anymore and unusable. ::: ```solidity function renounceOwnership() external nonpayable; ``` _`msg.sender` is renouncing ownership of contract `address(this)`._ Renounce ownership of the contract in a 2-step process. 1. The first call will initiate the process of renouncing ownership. 2. The second call is used as a confirmation and will leave the contract without an owner.
### transferOwnership :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#transferownership) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` _Transfer ownership initiated by `newOwner`._ Initiate the process of transferring ownership of the contract by setting the new owner as the pending owner. If the new owner is a contract that supports + implements LSP1, this will also attempt to notify the new owner that ownership has been transferred to them by calling the [`universalReceiver()`](#universalreceiver) function on the `newOwner` contract.
**Requirements:** - `newOwner` cannot accept ownership of the contract in the same transaction. (For instance, via a callback from its [`universalReceiver(...)`](#universalreceiver) function).
#### Parameters | Name | Type | Description | | ---------- | :-------: | ----------------------------- | | `newOwner` | `address` | The address of the new owner. |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_transferOwnership ```solidity function _transferOwnership(address newOwner) internal nonpayable; ``` Set the pending owner of the contract and cancel any renounce ownership process that was previously started.
**Requirements:** - `newOwner` cannot be the address of the contract itself.
#### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------- | | `newOwner` | `address` | The address of the new pending owner. |
### \_acceptOwnership ```solidity function _acceptOwnership() internal nonpayable; ``` Set the pending owner of the contract as the new owner.
### \_renounceOwnership ```solidity function _renounceOwnership() internal nonpayable; ``` Initiate or confirm the process of renouncing ownership after a specific delay of blocks have passed.
## Events ### OwnershipRenounced :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#ownershiprenounced) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Event signature: `OwnershipRenounced()` - Event topic hash: `0xd1f66c3d2bc1993a86be5e3d33709d98f0442381befcedd29f578b9b2506b1ce` ::: ```solidity event OwnershipRenounced(); ``` _Successfully renounced ownership of the contract. This contract is now owned by anyone, it's owner is `address(0)`._ Emitted when the ownership of the contract has been renounced.
### OwnershipTransferStarted :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#ownershiptransferstarted) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Event signature: `OwnershipTransferStarted(address,address)` - Event topic hash: `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` ::: ```solidity event OwnershipTransferStarted( address indexed previousOwner, address indexed newOwner ); ``` _The transfer of ownership of the contract was initiated. Pending new owner set to: `newOwner`._ Emitted when [`transferOwnership(..)`](#transferownership) was called and the first step of transferring ownership completed successfully which leads to [`pendingOwner`](#pendingowner) being updated. #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ---------------------------------- | | `previousOwner` **`indexed`** | `address` | The address of the previous owner. | | `newOwner` **`indexed`** | `address` | The address of the new owner. |
### OwnershipTransferred :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#ownershiptransferred) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### RenounceOwnershipStarted :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#renounceownershipstarted) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Event signature: `RenounceOwnershipStarted()` - Event topic hash: `0x81b7f830f1f0084db6497c486cbe6974c86488dcc4e3738eab94ab6d6b1653e7` ::: ```solidity event RenounceOwnershipStarted(); ``` _Ownership renouncement initiated._ Emitted when starting the [`renounceOwnership(..)`](#renounceownership) 2-step process.
## Errors ### LSP14CallerNotPendingOwner :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#lsp14callernotpendingowner) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Error signature: `LSP14CallerNotPendingOwner(address)` - Error hash: `0x451e4528` ::: ```solidity error LSP14CallerNotPendingOwner(address caller); ``` Reverts when the `caller` that is trying to accept ownership of the contract is not the pending owner. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------- | | `caller` | `address` | The address that tried to accept ownership. |
### LSP14CannotTransferOwnershipToSelf :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#lsp14cannottransferownershiptoself) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Error signature: `LSP14CannotTransferOwnershipToSelf()` - Error hash: `0xe052a6f8` ::: ```solidity error LSP14CannotTransferOwnershipToSelf(); ``` _Cannot transfer ownership to the address of the contract itself._ Reverts when trying to transfer ownership to the `address(this)`.
### LSP14MustAcceptOwnershipInSeparateTransaction :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#lsp14mustacceptownershipinseparatetransaction) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Error signature: `LSP14MustAcceptOwnershipInSeparateTransaction()` - Error hash: `0x5758dd07` ::: ```solidity error LSP14MustAcceptOwnershipInSeparateTransaction(); ``` _Cannot accept ownership in the same transaction with [`transferOwnership(...)`](#transferownership)._ Reverts when pending owner accept ownership in the same transaction of transferring ownership.
### LSP14NotInRenounceOwnershipInterval :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#lsp14notinrenounceownershipinterval) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Error signature: `LSP14NotInRenounceOwnershipInterval(uint256,uint256)` - Error hash: `0x1b080942` ::: ```solidity error LSP14NotInRenounceOwnershipInterval( uint256 renounceOwnershipStart, uint256 renounceOwnershipEnd ); ``` _Cannot confirm ownership renouncement yet. The ownership renouncement is allowed from: `renounceOwnershipStart` until: `renounceOwnershipEnd`._ Reverts when trying to renounce ownership before the initial confirmation delay. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ----------------------------------------------------------------------- | | `renounceOwnershipStart` | `uint256` | The start timestamp when one can confirm the renouncement of ownership. | | `renounceOwnershipEnd` | `uint256` | The end timestamp when one can confirm the renouncement of ownership. |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-14-Ownable2Step**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md#ownablecallernottheowner) - Solidity implementation: [`LSP14Ownable2Step.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP16UniversalFactory :::info Standard Specifications [`LSP-16-UniversalFactory`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md) ::: :::info Solidity implementation [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) ::: > LSP16 Universal Factory Factory contract to deploy different types of contracts using the CREATE2 opcode standardized as LSP16 - UniversalFactory: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md The UniversalFactory will be deployed using Nick's Factory (0x4e59b44847b379578588920ca78fbf26c0b4956c) The deployed address can be found in the LSP16 specification. Please refer to the LSP16 Specification to obtain the exact creation bytecode and salt that should be used to produce the address of the UniversalFactory on different chains. This factory contract is designed to deploy contracts at the same address on multiple chains. The UniversalFactory can deploy 2 types of contracts: - non-initializable (normal deployment) - initializable (external call after deployment, e.g: proxy contracts) The `providedSalt` parameter given by the deployer is not used directly as the salt by the CREATE2 opcode. Instead, it is used along with these parameters: - `initializable` boolean - `initializeCalldata` (when the contract is initializable and `initializable` is set to `true`). These three parameters are concatenated together and hashed to generate the final salt for CREATE2. See [`generateSalt`](#generatesalt) function for more details. The constructor and `initializeCalldata` SHOULD NOT include any network-specific parameters (e.g: chain-id, a local token contract address), otherwise the deployed contract will not be recreated at the same address across different networks, thus defeating the purpose of the UniversalFactory. One way to solve this problem is to set an EOA owner in the `initializeCalldata`/constructor that can later call functions that set these parameters as variables in the contract. The UniversalFactory must be deployed at the same address on different chains to successfully deploy contracts at the same address across different chains. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### computeAddress :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#computeaddress) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Function signature: `computeAddress(bytes32,bytes32,bool,bytes)` - Function selector: `0x3b315680` ::: ```solidity function computeAddress( bytes32 creationBytecodeHash, bytes32 providedSalt, bool initializable, bytes initializeCalldata ) external view returns (address); ``` Computes the address of a contract to be deployed using CREATE2, based on the input parameters. Any change in one of these parameters will result in a different address. When the `initializable` boolean is set to `false`, `initializeCalldata` will not affect the function output. #### Parameters | Name | Type | Description | | ---------------------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `creationBytecodeHash` | `bytes32` | The keccak256 hash of the creation bytecode to be deployed | | `providedSalt` | `bytes32` | The salt provided by the deployer, which will be used to generate the final salt that will be used by the `CREATE2` opcode for contract deployment | | `initializable` | `bool` | A boolean that indicates whether an external call should be made to initialize the contract after deployment | | `initializeCalldata` | `bytes` | The calldata to be executed on the created contract if `initializable` is set to `true` | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------------- | | `0` | `address` | The address where the contract will be deployed |
### computeERC1167Address :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#computeerc1167address) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Function signature: `computeERC1167Address(address,bytes32,bool,bytes)` - Function selector: `0xe888edcb` ::: ```solidity function computeERC1167Address( address implementationContract, bytes32 providedSalt, bool initializable, bytes initializeCalldata ) external view returns (address); ``` Computes the address of an ERC1167 proxy contract based on the input parameters. Any change in one of these parameters will result in a different address. When the `initializable` boolean is set to `false`, `initializeCalldata` will not affect the function output. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `implementationContract` | `address` | The contract to create a clone of according to ERC1167 | | `providedSalt` | `bytes32` | The salt provided by the deployer, which will be used to generate the final salt that will be used by the `CREATE2` opcode for contract deployment | | `initializable` | `bool` | A boolean that indicates whether an external call should be made to initialize the proxy contract after deployment | | `initializeCalldata` | `bytes` | The calldata to be executed on the created contract if `initializable` is set to `true` | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------------- | | `0` | `address` | The address where the ERC1167 proxy contract will be deployed |
### deployCreate2 :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#deploycreate2) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Function signature: `deployCreate2(bytes,bytes32)` - Function selector: `0x26736355` ::: ```solidity function deployCreate2( bytes creationBytecode, bytes32 providedSalt ) external payable returns (address); ``` _Deploys a smart contract._ Deploys a contract using the CREATE2 opcode. The address where the contract will be deployed can be known in advance via the [`computeAddress`](#computeaddress) function. This function deploys contracts without initialization (external call after deployment). The `providedSalt` parameter is not used directly as the salt by the CREATE2 opcode. Instead, it is hashed with keccak256: `keccak256(abi.encodePacked(false, providedSalt))`. See [`generateSalt`](#generatesalt) function for more details. Using the same `creationBytecode` and `providedSalt` multiple times will revert, as the contract cannot be deployed twice at the same address. If the constructor of the contract to deploy is payable, value can be sent to this function to fund the created contract. However, sending value to this function while the constructor is not payable will result in a revert. #### Parameters | Name | Type | Description | | ------------------ | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `creationBytecode` | `bytes` | The creation bytecode of the contract to be deployed | | `providedSalt` | `bytes32` | The salt provided by the deployer, which will be used to generate the final salt that will be used by the `CREATE2` opcode for contract deployment | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------ | | `0` | `address` | The address of the deployed contract |
### deployCreate2AndInitialize :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#deploycreate2andinitialize) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Function signature: `deployCreate2AndInitialize(bytes,bytes32,bytes,uint256,uint256)` - Function selector: `0xcdbd473a` ::: ```solidity function deployCreate2AndInitialize( bytes creationBytecode, bytes32 providedSalt, bytes initializeCalldata, uint256 constructorMsgValue, uint256 initializeCalldataMsgValue ) external payable returns (address); ``` _Deploys a smart contract and initializes it._ Deploys a contract using the CREATE2 opcode. The address where the contract will be deployed can be known in advance via the [`computeAddress`](#computeaddress) function. This function deploys contracts with initialization (external call after deployment). The `providedSalt` parameter is not used directly as the salt by the CREATE2 opcode. Instead, it is hashed with keccak256: `keccak256(abi.encodePacked(true, initializeCalldata, providedSalt))`. See [`generateSalt`](#generatesalt) function for more details. Using the same `creationBytecode`, `providedSalt` and `initializeCalldata` multiple times will revert, as the contract cannot be deployed twice at the same address. If the constructor or the initialize function of the contract to deploy is payable, value can be sent along with the deployment/initialization to fund the created contract. However, sending value to this function while the constructor/initialize function is not payable will result in a revert. Will revert if the `msg.value` sent to the function is not equal to the sum of `constructorMsgValue` and `initializeCalldataMsgValue`. #### Parameters | Name | Type | Description | | ---------------------------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `creationBytecode` | `bytes` | The creation bytecode of the contract to be deployed | | `providedSalt` | `bytes32` | The salt provided by the deployer, which will be used to generate the final salt that will be used by the `CREATE2` opcode for contract deployment | | `initializeCalldata` | `bytes` | The calldata to be executed on the created contract | | `constructorMsgValue` | `uint256` | The value sent to the contract during deployment | | `initializeCalldataMsgValue` | `uint256` | The value sent to the contract during initialization | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------ | | `0` | `address` | The address of the deployed contract |
### deployERC1167Proxy :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#deployerc1167proxy) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Function signature: `deployERC1167Proxy(address,bytes32)` - Function selector: `0x49d8abed` ::: ```solidity function deployERC1167Proxy( address implementationContract, bytes32 providedSalt ) external nonpayable returns (address); ``` _Deploys a proxy smart contract._ Deploys an ERC1167 minimal proxy contract using the CREATE2 opcode. The address where the contract will be deployed can be known in advance via the [`computeERC1167Address`](#computeerc1167address) function. This function deploys contracts without initialization (external call after deployment). The `providedSalt` parameter is not used directly as the salt by the CREATE2 opcode. Instead, it is hashed with keccak256: `keccak256(abi.encodePacked(false, providedSalt))`. See [`generateSalt`](#generatesalt) function for more details. Using the same `implementationContract` and `providedSalt` multiple times will revert, as the contract cannot be deployed twice at the same address. Sending value to the contract created is not possible since the constructor of the ERC1167 minimal proxy is not payable. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `implementationContract` | `address` | The contract address to use as the base implementation behind the proxy that will be deployed | | `providedSalt` | `bytes32` | The salt provided by the deployer, which will be used to generate the final salt that will be used by the `CREATE2` opcode for contract deployment | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------- | | `0` | `address` | The address of the minimal proxy deployed |
### deployERC1167ProxyAndInitialize :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#deployerc1167proxyandinitialize) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Function signature: `deployERC1167ProxyAndInitialize(address,bytes32,bytes)` - Function selector: `0x5340165f` ::: ```solidity function deployERC1167ProxyAndInitialize( address implementationContract, bytes32 providedSalt, bytes initializeCalldata ) external payable returns (address); ``` _Deploys a proxy smart contract and initializes it._ Deploys an ERC1167 minimal proxy contract using the CREATE2 opcode. The address where the contract will be deployed can be known in advance via the [`computeERC1167Address`](#computeerc1167address) function. This function deploys contracts with initialization (external call after deployment). The `providedSalt` parameter is not used directly as the salt by the CREATE2 opcode. Instead, it is hashed with keccak256: `keccak256(abi.encodePacked(true, initializeCalldata, providedSalt))`. See [`generateSalt`](#generatesalt) function for more details. Using the same `implementationContract`, `providedSalt` and `initializeCalldata` multiple times will revert, as the contract cannot be deployed twice at the same address. If the initialize function of the contract to deploy is payable, value can be sent along to fund the created contract while initializing. However, sending value to this function while the initialize function is not payable will result in a revert. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `implementationContract` | `address` | The contract address to use as the base implementation behind the proxy that will be deployed | | `providedSalt` | `bytes32` | The salt provided by the deployer, which will be used to generate the final salt that will be used by the `CREATE2` opcode for contract deployment | | `initializeCalldata` | `bytes` | The calldata to be executed on the created contract | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------- | | `0` | `address` | The address of the minimal proxy deployed |
### generateSalt :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#generatesalt) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Function signature: `generateSalt(bytes32,bool,bytes)` - Function selector: `0x1a17ccbf` ::: ```solidity function generateSalt( bytes32 providedSalt, bool initializable, bytes initializeCalldata ) external pure returns (bytes32); ``` Generates the salt used to deploy the contract by hashing the following parameters (concatenated together) with keccak256: 1. the `providedSalt` 2. the `initializable` boolean 3. the `initializeCalldata`, only if the contract is initializable (the `initializable` boolean is set to `true`) - The `providedSalt` parameter is not used directly as the salt by the CREATE2 opcode. Instead, it is used along with these parameters: 1. `initializable` boolean 2. `initializeCalldata` (when the contract is initializable and `initializable` is set to `true`). - This approach ensures that in order to reproduce an initializable contract at the same address on another chain, not only the `providedSalt` is required to be the same, but also the initialize parameters within the `initializeCalldata` must also be the same. This maintains consistent deployment behaviour. Users are required to initialize contracts with the same parameters across different chains to ensure contracts are deployed at the same address across different chains. 1. Example (for initializable contracts) - For an existing contract A on chain 1 owned by X, to replicate the same contract at the same address with the same owner X on chain 2, the salt used to generate the address should include the initializeCalldata that assigns X as the owner of contract A. - For instance, if another user, Y, tries to deploy the contract at the same address on chain 2 using the same providedSalt, but with a different initializeCalldata to make Y the owner instead of X, the generated address would be different, preventing Y from deploying the contract with different ownership at the same address. - However, for non-initializable contracts, if the constructor has arguments that specify the deployment behavior, they will be included in the creation bytecode. Any change in the constructor arguments will lead to a different contract's creation bytecode which will result in a different address on other chains. 2. Example (for non-initializable contracts) - If a contract is deployed with specific constructor arguments on chain 1, these arguments are embedded within the creation bytecode. For instance, if contract B is deployed with a specific `tokenName` and `tokenSymbol` on chain 1, and a user wants to deploy the same contract with the same `tokenName` and `tokenSymbol` on chain 2, they must use the same constructor arguments to produce the same creation bytecode. This ensures that the same deployment behaviour is maintained across different chains, as long as the same creation bytecode is used. - If another user Z, tries to deploy the same contract B at the same address on chain 2 using the same `providedSalt` but different constructor arguments (a different `tokenName` and/or `tokenSymbol`), the generated address will be different. This prevents user Z from deploying the contract with different constructor arguments at the same address on chain 2. - The providedSalt was hashed to produce the salt used by CREATE2 opcode to prevent users from deploying initializable contracts using non-initializable functions such as [`deployCreate2`](#deploycreate2) without having the initialization call. - In other words, if the providedSalt was not hashed and was used as it is as the salt by the CREATE2 opcode, malicious users can check the generated salt used for the already deployed initializable contract on chain 1, and deploy the contract from [`deployCreate2`](#deploycreate2) function on chain 2, with passing the generated salt of the deployed contract as providedSalt that will produce the same address but without the initialization, where the malicious user can initialize after. #### Parameters | Name | Type | Description | | -------------------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `providedSalt` | `bytes32` | The salt provided by the deployer, which will be used to generate the final salt that will be used by the `CREATE2` opcode for contract deployment | | `initializable` | `bool` | The Boolean that specifies if the contract must be initialized or not | | `initializeCalldata` | `bytes` | The calldata to be executed on the created contract if `initializable` is set to `true` | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------------ | | `0` | `bytes32` | The generated salt which will be used for CREATE2 deployment |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_verifyCallResult ```solidity function _verifyCallResult(bool success, bytes returndata) internal pure; ``` Verifies that the contract created was initialized correctly. Bubble the revert reason if present, revert with `ContractInitializationFailed` otherwise.
## Events ### ContractCreated :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#contractcreated) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Event signature: `ContractCreated(address,bytes32,bytes32,bool,bytes)` - Event topic hash: `0x8872a323d65599f01bf90dc61c94b4e0cc8e2347d6af4122fccc3e112ee34a84` ::: ```solidity event ContractCreated( address indexed createdContract, bytes32 indexed providedSalt, bytes32 generatedSalt, bool indexed initialized, bytes initializeCalldata ); ``` _Contract created. Contract address: `createdContract`._ Emitted whenever a contract is created. #### Parameters | Name | Type | Description | | ------------------------------- | :-------: | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `createdContract` **`indexed`** | `address` | The address of the contract created. | | `providedSalt` **`indexed`** | `bytes32` | The salt provided by the deployer, which will be used to generate the final salt that will be used by the `CREATE2` opcode for contract deployment. | | `generatedSalt` | `bytes32` | The salt used by the `CREATE2` opcode for contract deployment. | | `initialized` **`indexed`** | `bool` | The Boolean that specifies if the contract must be initialized or not. | | `initializeCalldata` | `bytes` | The bytes provided as initializeCalldata (Empty string when `initialized` is set to false). |
## Errors ### ContractInitializationFailed :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#contractinitializationfailed) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Error signature: `ContractInitializationFailed()` - Error hash: `0xc1ee8543` ::: ```solidity error ContractInitializationFailed(); ``` _Couldn't initialize the contract._ Reverts when there is no revert reason bubbled up by the created contract when initializing
### InvalidValueSum :::note References - Specification details: [**LSP-16-UniversalFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md#invalidvaluesum) - Solidity implementation: [`LSP16UniversalFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts/contracts/LSP16UniversalFactory.sol) - Error signature: `InvalidValueSum()` - Error hash: `0x2fd9ca91` ::: ```solidity error InvalidValueSum(); ``` Reverts when `msg.value` sent to [`deployCreate2AndInitialize(..)`](#deploycreate2andinitialize) function is not equal to the sum of the `initializeCalldataMsgValue` and `constructorMsgValue`
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP17Extendable :::info Standard Specifications [`LSP-17-ContractExtension`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md) ::: :::info Solidity implementation [`LSP17Extendable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol) ::: > Module to add more functionalities to a contract using extensions. Implementation of the `fallback(...)` logic according to LSP17 - Contract Extension standard. This module can be inherited to extend the functionality of the parent contract when calling a function that doesn't exist on the parent contract via forwarding the call to an extension mapped to the function selector being called, set originally by the parent contract ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### supportsInterface :::note References - Specification details: [**LSP-17-ContractExtension**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#supportsinterface) - Solidity implementation: [`LSP17Extendable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension mapped to a specific function selector If no extension was found, return the address(0) To be overridden. Up to the implementer contract to return an extension based on a function selector
### \_fallbackLSP17Extendable :::tip Hint This function does not forward to the extension contract the `msg.value` received by the contract that inherits `LSP17Extendable`. If you would like to forward the `msg.value` to the extension contract, you can override the code of this internal function as follow: ```solidity (bool success, bytes memory result) = extension.call{value: msg.value}( abi.encodePacked(callData, msg.sender, msg.value) ); ``` ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the `address(0)` will be returned. Forwards the value if the extension is payable. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the `CALL` opcode, passing the `msg.data` appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the `msg.value`.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP17Extension :::info Standard Specifications [`LSP-17-ContractExtension`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md) ::: :::info Solidity implementation [`LSP17Extension.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol) ::: > Module to create a contract that can act as an extension. Implementation of the extension logic according to LSP17ContractExtension. This module can be inherited to provide context of the msg variable related to the extendable contract ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### VERSION :::note References - Specification details: [**LSP-17-ContractExtension**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#version) - Solidity implementation: [`LSP17Extension.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol) - Function signature: `VERSION()` - Function selector: `0xffa1ad74` ::: ```solidity function VERSION() external view returns (string); ``` _Contract version._ #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `string` | - |
### supportsInterface :::note References - Specification details: [**LSP-17-ContractExtension**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#supportsinterface) - Solidity implementation: [`LSP17Extension.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_extendableMsgData ```solidity function _extendableMsgData() internal view returns (bytes); ``` Returns the original `msg.data` passed to the extendable contract without the appended `msg.sender` and `msg.value`.
### \_extendableMsgSender ```solidity function _extendableMsgSender() internal view returns (address); ``` Returns the original `msg.sender` calling the extendable contract.
### \_extendableMsgValue ```solidity function _extendableMsgValue() internal view returns (uint256); ``` Returns the original `msg.value` sent to the extendable contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # Extension4337 :::info Standard Specifications [`LSP-17-Extensions`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md) ::: :::info Solidity implementation [`Extension4337.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp17-contracts/contracts/Extension4337.sol) ::: ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**LSP-17-Extensions**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#constructor) - Solidity implementation: [`Extension4337.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp17-contracts/contracts/Extension4337.sol) ::: ```solidity constructor(address entryPoint_); ``` #### Parameters | Name | Type | Description | | ------------- | :-------: | ----------- | | `entryPoint_` | `address` | - |
### VERSION :::note References - Specification details: [**LSP-17-Extensions**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#version) - Solidity implementation: [`Extension4337.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp17-contracts/contracts/Extension4337.sol) - Function signature: `VERSION()` - Function selector: `0xffa1ad74` ::: ```solidity function VERSION() external view returns (string); ``` _Contract version._ #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `string` | - |
### entryPoint :::note References - Specification details: [**LSP-17-Extensions**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#entrypoint) - Solidity implementation: [`Extension4337.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp17-contracts/contracts/Extension4337.sol) - Function signature: `entryPoint()` - Function selector: `0xb0d691fe` ::: ```solidity function entryPoint() external view returns (address); ``` Get the address of the Entry Point contract that will execute the user operation. #### Returns | Name | Type | Description | | ---- | :-------: | -------------------------------------- | | `0` | `address` | The address of the EntryPoint contract |
### supportsInterface :::note References - Specification details: [**LSP-17-Extensions**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#supportsinterface) - Solidity implementation: [`Extension4337.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp17-contracts/contracts/Extension4337.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### validateUserOp :::note References - Specification details: [**LSP-17-Extensions**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#validateuserop) - Solidity implementation: [`Extension4337.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp17-contracts/contracts/Extension4337.sol) - Function signature: `validateUserOp(UserOperation,bytes32,uint256)` - Function selector: `0xe86fc51e` ::: :::info In addition to the logic of the `IAccount` interface from 4337, the permissions of the address that signed the user operation are checked to ensure that it has the permission `_4337_PERMISSION`. ::: ```solidity function validateUserOp( UserOperation userOp, bytes32 userOpHash, uint256 ) external nonpayable returns (uint256); ``` Validate user's signature and nonce. The entryPoint will make the call to the recipient only if this validation call returns successfully. Signature failure should be reported by returning `SIG_VALIDATION_FAILED` (`1`). This allows making a "simulation call" without a valid signature. Other failures (_e.g. nonce mismatch, or invalid signature format_) should still revert to signal failure. The third parameter (not mentioned but `missingAccountFunds` from the `IAccount` interface) describes the missing funds on the account's deposit in the entrypoint. This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call. The excess is left as a deposit in the entrypoint, for future calls. Can be withdrawn anytime using "entryPoint.withdrawTo()" In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.
**Requirements:** - caller MUST be the **entrypoint contract**. - the signature and nonce must be valid.
#### Parameters | Name | Type | Description | | ------------ | :-------------: | ----------- | | `userOp` | `UserOperation` | - | | `userOpHash` | `bytes32` | - | | `_2` | `uint256` | - | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `0` | `uint256` | validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode - `<20-byte>` sigAuthorizer - 0 for valid signature, 1 to mark signature failure, otherwise, an address of an "authorizer" contract. - `<6-byte>` validUntil - last timestamp this operation is valid. 0 for "indefinite" - `<6-byte>` validAfter - first timestamp this operation is valid If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure. Note that the validation code cannot use block.timestamp (or block.number) directly. |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_extendableMsgData ```solidity function _extendableMsgData() internal view returns (bytes); ``` Returns the original `msg.data` passed to the extendable contract without the appended `msg.sender` and `msg.value`.
### \_extendableMsgSender ```solidity function _extendableMsgSender() internal view returns (address); ``` Returns the original `msg.sender` calling the extendable contract.
### \_extendableMsgValue ```solidity function _extendableMsgValue() internal view returns (uint256); ``` Returns the original `msg.value` sent to the extendable contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # OnERC721ReceivedExtension :::info Standard Specifications [`LSP-17-Extensions`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md) ::: :::info Solidity implementation [`OnERC721ReceivedExtension.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp17-contracts/contracts/OnERC721ReceivedExtension.sol) ::: LSP17 Extension that can be attached to a LSP17Extendable contract to allow it to receive ERC721 tokens via `safeTransferFrom`. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### VERSION :::note References - Specification details: [**LSP-17-Extensions**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#version) - Solidity implementation: [`OnERC721ReceivedExtension.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp17-contracts/contracts/OnERC721ReceivedExtension.sol) - Function signature: `VERSION()` - Function selector: `0xffa1ad74` ::: ```solidity function VERSION() external view returns (string); ``` _Contract version._ #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `string` | - |
### onERC721Received :::note References - Specification details: [**LSP-17-Extensions**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#onerc721received) - Solidity implementation: [`OnERC721ReceivedExtension.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp17-contracts/contracts/OnERC721ReceivedExtension.sol) - Function signature: `onERC721Received(address,address,uint256,bytes)` - Function selector: `0x150b7a02` ::: ```solidity function onERC721Received( address, address, uint256, bytes ) external nonpayable returns (bytes4); ``` See [`IERC721Receiver-onERC721Received`](#ierc721receiver-onerc721received). Always returns `IERC721Receiver.onERC721Received.selector`. #### Parameters | Name | Type | Description | | ---- | :-------: | ----------- | | `_0` | `address` | - | | `_1` | `address` | - | | `_2` | `uint256` | - | | `_3` | `bytes` | - | #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `bytes4` | - |
### supportsInterface :::note References - Specification details: [**LSP-17-Extensions**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#supportsinterface) - Solidity implementation: [`OnERC721ReceivedExtension.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp17-contracts/contracts/OnERC721ReceivedExtension.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_extendableMsgData ```solidity function _extendableMsgData() internal view returns (bytes); ``` Returns the original `msg.data` passed to the extendable contract without the appended `msg.sender` and `msg.value`.
### \_extendableMsgSender ```solidity function _extendableMsgSender() internal view returns (address); ``` Returns the original `msg.sender` calling the extendable contract.
### \_extendableMsgValue ```solidity function _extendableMsgValue() internal view returns (uint256); ``` Returns the original `msg.value` sent to the extendable contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP1UniversalReceiverDelegateUP :::info Standard Specifications [`LSP-1-UniversalReceiver`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md) ::: :::info Solidity implementation [`LSP1UniversalReceiverDelegateUP.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) ::: > Implementation of a UniversalReceiverDelegate for the [LSP-0-ERC725Account] The [`LSP1UniversalReceiverDelegateUP`](#lsp1universalreceiverdelegateup) follows the [LSP-1-UniversalReceiver] standard and is designed for [LSP-0-ERC725Account] contracts. The [`LSP1UniversalReceiverDelegateUP`](#lsp1universalreceiverdelegateup) is a contract called by the [`universalReceiver(...)`](#universalreceiver) function of the [LSP-0-ERC725Account] contract that: - Writes the data keys representing assets received from type [LSP-7-DigitalAsset] and [LSP-8-IdentifiableDigitalAsset] into the account storage, and removes them when the balance is zero according to the [LSP-5-ReceivedAssets] Standard. - Writes the data keys representing the owned vaults from type [LSP-9-Vault] into your account storage, and removes them when transferring ownership to other accounts according to the [LSP-10-ReceivedVaults] Standard. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### VERSION :::note References - Specification details: [**LSP-1-UniversalReceiver**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#version) - Solidity implementation: [`LSP1UniversalReceiverDelegateUP.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) - Function signature: `VERSION()` - Function selector: `0xffa1ad74` ::: ```solidity function VERSION() external view returns (string); ``` _Contract version._ #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `string` | - |
### supportsInterface :::note References - Specification details: [**LSP-1-UniversalReceiver**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#supportsinterface) - Solidity implementation: [`LSP1UniversalReceiverDelegateUP.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### universalReceiverDelegate :::note References - Specification details: [**LSP-1-UniversalReceiver**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#universalreceiverdelegate) - Solidity implementation: [`LSP1UniversalReceiverDelegateUP.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) - Function signature: `universalReceiverDelegate(address,uint256,bytes32,bytes)` - Function selector: `0xa245bbda` ::: :::info - If some issues occurred with generating the `dataKeys` or `dataValues` the `returnedMessage` will be an error message, otherwise it will be empty. - If an error occurred when trying to use `setDataBatch(dataKeys,dataValues)`, it will return the raw error data back to the caller. ::: :::caution Warning When the data stored in the ERC725Y storage of the LSP0 contract is corrupted (\_e.g: ([LSP-5-ReceivedAssets]'s Array length not 16 bytes long, the token received is already registered in `LSP5ReceivetAssets[]`, the token being sent is not sent as full balance, etc...), the function call will still pass and return (**not revert!**) and not modify any data key on the storage of the [LSP-0-ERC725Account]. ::: ```solidity function universalReceiverDelegate( address notifier, uint256, bytes32 typeId, bytes ) external nonpayable returns (bytes); ``` _Reacted on received notification with `typeId`._ 1. Writes the data keys of the received [LSP-7-DigitalAsset], [LSP-8-IdentifiableDigitalAsset] and [LSP-9-Vault] contract addresses into the account storage according to the [LSP-5-ReceivedAssets] and [LSP-10-ReceivedVaults] Standard. 2. The data keys representing an asset/vault are cleared when the asset/vault is no longer owned by the account.
**Requirements:** - This contract should be allowed to use the [`setDataBatch(...)`](#setdatabatch) function in order to update the LSP5 and LSP10 Data Keys. - Cannot accept native tokens
#### Parameters | Name | Type | Description | | ---------- | :-------: | ---------------------------------------------- | | `notifier` | `address` | - | | `_1` | `uint256` | - | | `typeId` | `bytes32` | Unique identifier for a specific notification. | | `_3` | `bytes` | - | #### Returns | Name | Type | Description | | ---- | :-----: | ---------------------------------------- | | `0` | `bytes` | The result of the reaction for `typeId`. |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_tokenSender ```solidity function _tokenSender(address notifier) internal nonpayable returns (bytes); ``` Handler for LSP7 and LSP8 token sender type id. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------- | | `notifier` | `address` | The LSP7 or LSP8 token address. |
### \_tokenRecipient ```solidity function _tokenRecipient( address notifier, bytes4 interfaceId ) internal nonpayable returns (bytes); ``` Handler for LSP7 and LSP8 token recipient type id. #### Parameters | Name | Type | Description | | ------------- | :-------: | ------------------------------- | | `notifier` | `address` | The LSP7 or LSP8 token address. | | `interfaceId` | `bytes4` | The LSP7 or LSP8 interface id. |
### \_vaultSender ```solidity function _vaultSender(address notifier) internal nonpayable returns (bytes); ``` Handler for LSP9 vault sender type id. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------------------- | | `notifier` | `address` | The LSP9 vault address. |
### \_vaultRecipient ```solidity function _vaultRecipient(address notifier) internal nonpayable returns (bytes); ``` Handler for LSP9 vault recipient type id. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------------------- | | `notifier` | `address` | The LSP9 vault address. |
### \_setDataBatchWithoutReverting :::info If an the low-level transaction revert, the returned data will be forwarded. Th contract that uses this function can use the `Address` library to revert with the revert reason. ::: ```solidity function _setDataBatchWithoutReverting( bytes32[] dataKeys, bytes[] dataValues ) internal nonpayable returns (bytes); ``` Calls `bytes4(keccak256(setDataBatch(bytes32[],bytes[])))` without checking for `bool success`, but it returns all the data back. #### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------- | | `dataKeys` | `bytes32[]` | Data Keys to be set. | | `dataValues` | `bytes[]` | Data Values to be set. |
## Errors ### CannotRegisterEOAsAsAssets :::note References - Specification details: [**LSP-1-UniversalReceiver**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#cannotregistereoasasassets) - Solidity implementation: [`LSP1UniversalReceiverDelegateUP.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) - Error signature: `CannotRegisterEOAsAsAssets(address)` - Error hash: `0xa5295345` ::: ```solidity error CannotRegisterEOAsAsAssets(address caller); ``` _EOA: `caller` cannot be registered as an asset._ Reverts when EOA calls the [`universalReceiver(..)`](#universalreceiver) function with an asset/vault typeId. #### Parameters | Name | Type | Description | | -------- | :-------: | ---------------------- | | `caller` | `address` | The address of the EOA |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP1UniversalReceiverDelegateVault :::info Standard Specifications [`LSP-1-UniversalReceiver`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md) ::: :::info Solidity implementation [`LSP1UniversalReceiverDelegateVault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) ::: > Implementation of a UniversalReceiverDelegate for the [LSP9Vault] The [`LSP1UniversalReceiverDelegateVault`](#lsp1universalreceiverdelegatevault) follows the [LSP-1-UniversalReceiver] standard and is designed for [LSP9Vault] contracts. The [`LSP1UniversalReceiverDelegateVault`](#lsp1universalreceiverdelegatevault) is a contract called by the [`universalReceiver(...)`](#universalreceiver) function of the [LSP-9-Vault] contract that: - Writes the data keys representing assets received from type [LSP-7-DigitalAsset] and [LSP-8-IdentifiableDigitalAsset] into the account storage, and removes them when the balance is zero according to the [LSP-5-ReceivedAssets] Standard. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### VERSION :::note References - Specification details: [**LSP-1-UniversalReceiver**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#version) - Solidity implementation: [`LSP1UniversalReceiverDelegateVault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) - Function signature: `VERSION()` - Function selector: `0xffa1ad74` ::: ```solidity function VERSION() external view returns (string); ``` _Contract version._ #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `string` | - |
### supportsInterface :::note References - Specification details: [**LSP-1-UniversalReceiver**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#supportsinterface) - Solidity implementation: [`LSP1UniversalReceiverDelegateVault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### universalReceiverDelegate :::note References - Specification details: [**LSP-1-UniversalReceiver**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#universalreceiverdelegate) - Solidity implementation: [`LSP1UniversalReceiverDelegateVault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) - Function signature: `universalReceiverDelegate(address,uint256,bytes32,bytes)` - Function selector: `0xa245bbda` ::: :::info - If some issues occurred with generating the `dataKeys` or `dataValues` the `returnedMessage` will be an error message, otherwise it will be empty. - If an error occurred when trying to use `setDataBatch(dataKeys,dataValues)`, it will return the raw error data back to the caller. ::: ```solidity function universalReceiverDelegate( address notifier, uint256, bytes32 typeId, bytes ) external nonpayable returns (bytes); ``` _Reacted on received notification with `typeId`._ Handles two cases: Writes the received [LSP-7-DigitalAsset] or [LSP-8-IdentifiableDigitalAsset] assets into the vault storage according to the [LSP-5-ReceivedAssets] standard.
**Requirements:** - Cannot accept native tokens.
#### Parameters | Name | Type | Description | | ---------- | :-------: | ---------------------------------------------- | | `notifier` | `address` | - | | `_1` | `uint256` | - | | `typeId` | `bytes32` | Unique identifier for a specific notification. | | `_3` | `bytes` | - | #### Returns | Name | Type | Description | | ---- | :-----: | ---------------------------------------- | | `0` | `bytes` | The result of the reaction for `typeId`. |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_tokenSender ```solidity function _tokenSender(address notifier) internal nonpayable returns (bytes); ``` Handler for LSP7 and LSP8 token sender type id. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------- | | `notifier` | `address` | The LSP7 or LSP8 token address. |
### \_tokenRecipient ```solidity function _tokenRecipient( address notifier, bytes4 interfaceId ) internal nonpayable returns (bytes); ``` Handler for LSP7 and LSP8 token recipient type id. #### Parameters | Name | Type | Description | | ------------- | :-------: | ------------------------------- | | `notifier` | `address` | The LSP7 or LSP8 token address. | | `interfaceId` | `bytes4` | The LSP7 or LSP8 interface id. |
### \_setDataBatchWithoutReverting :::info If an the low-level transaction revert, the returned data will be forwarded. Th contract that uses this function can use the `Address` library to revert with the revert reason. ::: ```solidity function _setDataBatchWithoutReverting( bytes32[] dataKeys, bytes[] dataValues ) internal nonpayable returns (bytes); ``` Calls `bytes4(keccak256(setDataBatch(bytes32[],bytes[])))` without checking for `bool success`, but it returns all the data back. #### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------- | | `dataKeys` | `bytes32[]` | Data Keys to be set. | | `dataValues` | `bytes[]` | Data Values to be set. |
## Errors ### CannotRegisterEOAsAsAssets :::note References - Specification details: [**LSP-1-UniversalReceiver**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#cannotregistereoasasassets) - Solidity implementation: [`LSP1UniversalReceiverDelegateVault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) - Error signature: `CannotRegisterEOAsAsAssets(address)` - Error hash: `0xa5295345` ::: ```solidity error CannotRegisterEOAsAsAssets(address caller); ``` _EOA: `caller` cannot be registered as an asset._ Reverts when EOA calls the [`universalReceiver(..)`](#universalreceiver) function with an asset/vault typeId. #### Parameters | Name | Type | Description | | -------- | :-------: | ---------------------- | | `caller` | `address` | The address of the EOA |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP20CallVerification :::info Standard Specifications [`LSP-20-CallVerification`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-20-CallVerification.md) ::: :::info Solidity implementation [`LSP20CallVerification.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol) ::: > Implementation of a contract calling the verification functions according to LSP20 - Call Verification standard. Module to be inherited used to verify the execution of functions according to a verifier address. Verification can happen before or after execution based on a returnedStatus. ## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_verifyCall ```solidity function _verifyCall( address logicVerifier ) internal nonpayable returns (bool verifyAfter); ``` Calls [`lsp20VerifyCall`](#lsp20verifycall) function on the logicVerifier.
### \_verifyCallResult ```solidity function _verifyCallResult( address logicVerifier, bytes callResult ) internal nonpayable; ``` Calls [`lsp20VerifyCallResult`](#lsp20verifycallresult) function on the logicVerifier.
### \_revertWithLSP20DefaultError ```solidity function _revertWithLSP20DefaultError( bool postCall, bytes returnedData ) internal pure; ```
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # IPostDeploymentModule :::info Standard Specifications [`LSP-23-LinkedContractsDeployment`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md) ::: :::info Solidity implementation [`IPostDeploymentModule.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/IPostDeploymentModule.sol) ::: ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### executePostDeployment :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#executepostdeployment) - Solidity implementation: [`IPostDeploymentModule.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/IPostDeploymentModule.sol) - Function signature: `executePostDeployment(address,address,bytes)` - Function selector: `0x28c4d14e` ::: ```solidity function executePostDeployment( address primaryContract, address secondaryContract, bytes calldataToPostDeploymentModule ) external nonpayable; ``` _This function can be used to perform any additional setup or configuration after the primary and secondary contracts have been deployed._ Executes post-deployment logic for the primary and secondary contracts. #### Parameters | Name | Type | Description | | -------------------------------- | :-------: | -------------------------------------------------------- | | `primaryContract` | `address` | The address of the deployed primary contract. | | `secondaryContract` | `address` | The address of the deployed secondary contract. | | `calldataToPostDeploymentModule` | `bytes` | Calldata to be passed for the post-deployment execution. |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP23LinkedContractsFactory :::info Standard Specifications [`LSP-23-LinkedContractsDeployment`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md) ::: :::info Solidity implementation [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) ::: ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### computeAddresses :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#computeaddresses) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Function signature: `computeAddresses(ILSP23LinkedContractsFactory.PrimaryContractDeployment,ILSP23LinkedContractsFactory.SecondaryContractDeployment,address,bytes)` - Function selector: `0xdecfb0b9` ::: ```solidity function computeAddresses( ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata ) external view returns (address primaryContractAddress, address secondaryContractAddress); ``` #### Parameters | Name | Type | Description | | ------------------------------ | :--------------------------------------------------------: | ----------- | | `primaryContractDeployment` | `ILSP23LinkedContractsFactory.PrimaryContractDeployment` | - | | `secondaryContractDeployment` | `ILSP23LinkedContractsFactory.SecondaryContractDeployment` | - | | `postDeploymentModule` | `address` | - | | `postDeploymentModuleCalldata` | `bytes` | - | #### Returns | Name | Type | Description | | -------------------------- | :-------: | ----------- | | `primaryContractAddress` | `address` | - | | `secondaryContractAddress` | `address` | - |
### computeERC1167Addresses :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#computeerc1167addresses) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Function signature: `computeERC1167Addresses(ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit,ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit,address,bytes)` - Function selector: `0x8da85898` ::: ```solidity function computeERC1167Addresses( ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata ) external view returns (address primaryContractAddress, address secondaryContractAddress); ``` #### Parameters | Name | Type | Description | | --------------------------------- | :------------------------------------------------------------: | ----------- | | `primaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit` | - | | `secondaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit` | - | | `postDeploymentModule` | `address` | - | | `postDeploymentModuleCalldata` | `bytes` | - | #### Returns | Name | Type | Description | | -------------------------- | :-------: | ----------- | | `primaryContractAddress` | `address` | - | | `secondaryContractAddress` | `address` | - |
### deployContracts :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#deploycontracts) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Function signature: `deployContracts(ILSP23LinkedContractsFactory.PrimaryContractDeployment,ILSP23LinkedContractsFactory.SecondaryContractDeployment,address,bytes)` - Function selector: `0xf830c0ab` ::: ```solidity function deployContracts( ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata ) external payable returns (address primaryContractAddress, address secondaryContractAddress); ``` #### Parameters | Name | Type | Description | | ------------------------------ | :--------------------------------------------------------: | ----------- | | `primaryContractDeployment` | `ILSP23LinkedContractsFactory.PrimaryContractDeployment` | - | | `secondaryContractDeployment` | `ILSP23LinkedContractsFactory.SecondaryContractDeployment` | - | | `postDeploymentModule` | `address` | - | | `postDeploymentModuleCalldata` | `bytes` | - | #### Returns | Name | Type | Description | | -------------------------- | :-------: | ----------- | | `primaryContractAddress` | `address` | - | | `secondaryContractAddress` | `address` | - |
### deployERC1167Proxies :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#deployerc1167proxies) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Function signature: `deployERC1167Proxies(ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit,ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit,address,bytes)` - Function selector: `0x17c042c4` ::: ```solidity function deployERC1167Proxies( ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata ) external payable returns (address primaryContractAddress, address secondaryContractAddress); ``` #### Parameters | Name | Type | Description | | --------------------------------- | :------------------------------------------------------------: | ----------- | | `primaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit` | - | | `secondaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit` | - | | `postDeploymentModule` | `address` | - | | `postDeploymentModuleCalldata` | `bytes` | - | #### Returns | Name | Type | Description | | -------------------------- | :-------: | ----------- | | `primaryContractAddress` | `address` | - | | `secondaryContractAddress` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_deployPrimaryContract ```solidity function _deployPrimaryContract(struct ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, struct ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata) internal nonpayable returns (address primaryContractAddress); ```
### \_deploySecondaryContract ```solidity function _deploySecondaryContract(struct ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address primaryContractAddress) internal nonpayable returns (address secondaryContractAddress); ```
### \_deployAndInitializePrimaryContractProxy ```solidity function _deployAndInitializePrimaryContractProxy(struct ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, struct ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata) internal nonpayable returns (address primaryContractAddress); ```
### \_deployAndInitializeSecondaryContractProxy ```solidity function _deployAndInitializeSecondaryContractProxy(struct ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address primaryContractAddress) internal nonpayable returns (address secondaryContractAddress); ```
### \_generatePrimaryContractSalt ```solidity function _generatePrimaryContractSalt(struct ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, struct ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata) internal pure returns (bytes32 primaryContractGeneratedSalt); ```
### \_generatePrimaryContractProxySalt ```solidity function _generatePrimaryContractProxySalt(struct ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, struct ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata) internal pure returns (bytes32 primaryContractProxyGeneratedSalt); ```
## Events ### DeployedContracts :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#deployedcontracts) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Event signature: `DeployedContracts(address,address,ILSP23LinkedContractsFactory.PrimaryContractDeployment,ILSP23LinkedContractsFactory.SecondaryContractDeployment,address,bytes)` - Event topic hash: `0x1ea27dabd8fd1508e844ab51c2fd3d9081f2684346857f9187da6d4a1aa7d3e6` ::: ```solidity event DeployedContracts(address indexed primaryContract, address indexed secondaryContract, ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata); ``` Emitted when a primary and secondary contract are deployed. #### Parameters | Name | Type | Description | | --------------------------------- | :--------------------------------------------------------: | ------------------------------------------------------ | | `primaryContract` **`indexed`** | `address` | Address of the deployed primary contract. | | `secondaryContract` **`indexed`** | `address` | Address of the deployed secondary contract. | | `primaryContractDeployment` | `ILSP23LinkedContractsFactory.PrimaryContractDeployment` | Parameters used for the primary contract deployment. | | `secondaryContractDeployment` | `ILSP23LinkedContractsFactory.SecondaryContractDeployment` | Parameters used for the secondary contract deployment. | | `postDeploymentModule` | `address` | Address of the post-deployment module. | | `postDeploymentModuleCalldata` | `bytes` | Calldata passed to the post-deployment module. |
### DeployedERC1167Proxies :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#deployederc1167proxies) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Event signature: `DeployedERC1167Proxies(address,address,ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit,ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit,address,bytes)` - Event topic hash: `0xb03dbe7a02c063899f863d542410b5b038c8f537045be3a26e7144e0074e1c7b` ::: ```solidity event DeployedERC1167Proxies(address indexed primaryContract, address indexed secondaryContract, ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata); ``` Emitted when proxies of a primary and secondary contract are deployed. #### Parameters | Name | Type | Description | | --------------------------------- | :------------------------------------------------------------: | ------------------------------------------------------------ | | `primaryContract` **`indexed`** | `address` | Address of the deployed primary contract proxy. | | `secondaryContract` **`indexed`** | `address` | Address of the deployed secondary contract proxy. | | `primaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit` | Parameters used for the primary contract proxy deployment. | | `secondaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit` | Parameters used for the secondary contract proxy deployment. | | `postDeploymentModule` | `address` | Address of the post-deployment module. | | `postDeploymentModuleCalldata` | `bytes` | Calldata passed to the post-deployment module. |
## Errors ### InvalidValueSum :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#invalidvaluesum) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Error signature: `InvalidValueSum()` - Error hash: `0x2fd9ca91` ::: ```solidity error InvalidValueSum(); ``` _Invalid value sent._ Reverts when the `msg.value` sent is not equal to the sum of value used for the deployment of the contract & its owner contract.
### PrimaryContractProxyInitFailureError :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#primarycontractproxyinitfailureerror) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Error signature: `PrimaryContractProxyInitFailureError(bytes)` - Error hash: `0x4364b6ee` ::: ```solidity error PrimaryContractProxyInitFailureError(bytes errorData); ``` _Failed to deploy & initialise the Primary Contract Proxy. Error: `errorData`._ Reverts when the deployment & initialisation of the contract has failed. #### Parameters | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `errorData` | `bytes` | Potentially information about why the deployment & initialisation have failed. |
### SecondaryContractProxyInitFailureError :::note References - Specification details: [**LSP-23-LinkedContractsDeployment**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#secondarycontractproxyinitfailureerror) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Error signature: `SecondaryContractProxyInitFailureError(bytes)` - Error hash: `0x9654a854` ::: ```solidity error SecondaryContractProxyInitFailureError(bytes errorData); ``` _Failed to deploy & initialise the Secondary Contract Proxy. Error: `errorData`._ Reverts when the deployment & initialisation of the secondary contract has failed. #### Parameters | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `errorData` | `bytes` | Potentially information about why the deployment & initialisation have failed. |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # IPostDeploymentModule :::info Standard Specifications [`LSP-23-LinkedContractsFactory`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md) ::: :::info Solidity implementation [`IPostDeploymentModule.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) ::: ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### executePostDeployment :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#executepostdeployment) - Solidity implementation: [`IPostDeploymentModule.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Function signature: `executePostDeployment(address,address,bytes)` - Function selector: `0x28c4d14e` ::: ```solidity function executePostDeployment( address primaryContract, address secondaryContract, bytes calldataToPostDeploymentModule ) external nonpayable; ``` _This function can be used to perform any additional setup or configuration after the primary and secondary contracts have been deployed._ Executes post-deployment logic for the primary and secondary contracts. #### Parameters | Name | Type | Description | | -------------------------------- | :-------: | -------------------------------------------------------- | | `primaryContract` | `address` | The address of the deployed primary contract. | | `secondaryContract` | `address` | The address of the deployed secondary contract. | | `calldataToPostDeploymentModule` | `bytes` | Calldata to be passed for the post-deployment execution. |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP23LinkedContractsFactory :::info Standard Specifications [`LSP-23-LinkedContractsFactory`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md) ::: :::info Solidity implementation [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) ::: ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### computeAddresses :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#computeaddresses) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Function signature: `computeAddresses(ILSP23LinkedContractsFactory.PrimaryContractDeployment,ILSP23LinkedContractsFactory.SecondaryContractDeployment,address,bytes)` - Function selector: `0xdecfb0b9` ::: ```solidity function computeAddresses( ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata ) external view returns (address primaryContractAddress, address secondaryContractAddress); ``` Computes the addresses of a primary contract and a secondary linked contract #### Parameters | Name | Type | Description | | ------------------------------ | :--------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `primaryContractDeployment` | `ILSP23LinkedContractsFactory.PrimaryContractDeployment` | Contains the needed parameter to deploy the primary contract. (`salt`, `fundingAmount`, `creationBytecode`) | | `secondaryContractDeployment` | `ILSP23LinkedContractsFactory.SecondaryContractDeployment` | Contains the needed parameter to deploy the secondary contract. (`fundingAmount`, `creationBytecode`, `addPrimaryContractAddress`, `extraConstructorParams`) | | `postDeploymentModule` | `address` | The optional module to be executed after deployment | | `postDeploymentModuleCalldata` | `bytes` | The data to be passed to the post deployment module | #### Returns | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------- | | `primaryContractAddress` | `address` | The address of the deployed primary contract. | | `secondaryContractAddress` | `address` | The address of the deployed secondary contract. |
### computeERC1167Addresses :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#computeerc1167addresses) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Function signature: `computeERC1167Addresses(ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit,ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit,address,bytes)` - Function selector: `0x8da85898` ::: ```solidity function computeERC1167Addresses( ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata ) external view returns (address primaryContractAddress, address secondaryContractAddress); ``` Computes the addresses of a primary and a secondary linked contracts ERC1167 proxies to be created #### Parameters | Name | Type | Description | | --------------------------------- | :------------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `primaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit` | Contains the needed parameters to deploy a primary proxy contract. (`salt`, `fundingAmount`, `implementationContract`, `initializationCalldata`) | | `secondaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit` | Contains the needed parameters to deploy the secondary proxy contract. (`fundingAmount`, `implementationContract`, `initializationCalldata`, `addPrimaryContractAddress`, `extraInitializationParams`) | | `postDeploymentModule` | `address` | The optional module to be executed after deployment. | | `postDeploymentModuleCalldata` | `bytes` | The data to be passed to the post deployment module. | #### Returns | Name | Type | Description | | -------------------------- | :-------: | ---------------------------------------------------- | | `primaryContractAddress` | `address` | The address of the deployed primary contract proxy | | `secondaryContractAddress` | `address` | The address of the deployed secondary contract proxy |
### deployContracts :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#deploycontracts) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Function signature: `deployContracts(ILSP23LinkedContractsFactory.PrimaryContractDeployment,ILSP23LinkedContractsFactory.SecondaryContractDeployment,address,bytes)` - Function selector: `0xf830c0ab` ::: ```solidity function deployContracts( ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata ) external payable returns (address primaryContractAddress, address secondaryContractAddress); ``` _Contracts deployed. Contract Address: `primaryContractAddress`. Primary Contract Address: `primaryContractAddress`_ Deploys a primary and a secondary linked contract. #### Parameters | Name | Type | Description | | ------------------------------ | :--------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `primaryContractDeployment` | `ILSP23LinkedContractsFactory.PrimaryContractDeployment` | Contains the needed parameter to deploy a contract. (`salt`, `fundingAmount`, `creationBytecode`) | | `secondaryContractDeployment` | `ILSP23LinkedContractsFactory.SecondaryContractDeployment` | Contains the needed parameter to deploy the secondary contract. (`fundingAmount`, `creationBytecode`, `addPrimaryContractAddress`, `extraConstructorParams`) | | `postDeploymentModule` | `address` | The optional module to be executed after deployment | | `postDeploymentModuleCalldata` | `bytes` | The data to be passed to the post deployment module | #### Returns | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------- | | `primaryContractAddress` | `address` | The address of the primary contract. | | `secondaryContractAddress` | `address` | The address of the secondary contract. |
### deployERC1167Proxies :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#deployerc1167proxies) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Function signature: `deployERC1167Proxies(ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit,ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit,address,bytes)` - Function selector: `0x17c042c4` ::: ```solidity function deployERC1167Proxies( ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata ) external payable returns (address primaryContractAddress, address secondaryContractAddress); ``` _Contract proxies deployed. Primary Proxy Address: `primaryContractAddress`. Secondary Contract Proxy Address: `secondaryContractAddress`_ Deploys ERC1167 proxies of a primary contract and a secondary linked contract #### Parameters | Name | Type | Description | | --------------------------------- | :------------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `primaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit` | Contains the needed parameters to deploy a proxy contract. (`salt`, `fundingAmount`, `implementationContract`, `initializationCalldata`) | | `secondaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit` | Contains the needed parameters to deploy the secondary proxy contract. (`fundingAmount`, `implementationContract`, `initializationCalldata`, `addPrimaryContractAddress`, `extraInitializationParams`) | | `postDeploymentModule` | `address` | The optional module to be executed after deployment. | | `postDeploymentModuleCalldata` | `bytes` | The data to be passed to the post deployment module. | #### Returns | Name | Type | Description | | -------------------------- | :-------: | ---------------------------------------------------- | | `primaryContractAddress` | `address` | The address of the deployed primary contract proxy | | `secondaryContractAddress` | `address` | The address of the deployed secondary contract proxy |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_deployPrimaryContract ```solidity function _deployPrimaryContract(struct ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, struct ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata) internal nonpayable returns (address primaryContractAddress); ```
### \_deploySecondaryContract ```solidity function _deploySecondaryContract(struct ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address primaryContractAddress) internal nonpayable returns (address secondaryContractAddress); ```
### \_deployAndInitializePrimaryContractProxy ```solidity function _deployAndInitializePrimaryContractProxy(struct ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, struct ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata) internal nonpayable returns (address primaryContractAddress); ```
### \_deployAndInitializeSecondaryContractProxy ```solidity function _deployAndInitializeSecondaryContractProxy(struct ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address primaryContractAddress) internal nonpayable returns (address secondaryContractAddress); ```
### \_generatePrimaryContractSalt ```solidity function _generatePrimaryContractSalt(struct ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, struct ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata) internal pure returns (bytes32 primaryContractGeneratedSalt); ```
### \_generatePrimaryContractProxySalt ```solidity function _generatePrimaryContractProxySalt(struct ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, struct ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata) internal pure returns (bytes32 primaryContractProxyGeneratedSalt); ```
## Events ### DeployedContracts :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#deployedcontracts) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Event signature: `DeployedContracts(address,address,ILSP23LinkedContractsFactory.PrimaryContractDeployment,ILSP23LinkedContractsFactory.SecondaryContractDeployment,address,bytes)` - Event topic hash: `0x1ea27dabd8fd1508e844ab51c2fd3d9081f2684346857f9187da6d4a1aa7d3e6` ::: ```solidity event DeployedContracts( address indexed primaryContract, address indexed secondaryContract, ILSP23LinkedContractsFactory.PrimaryContractDeployment primaryContractDeployment, ILSP23LinkedContractsFactory.SecondaryContractDeployment secondaryContractDeployment, address postDeploymentModule, bytes postDeploymentModuleCalldata ); ``` Emitted when a primary and secondary contract are deployed. #### Parameters | Name | Type | Description | | --------------------------------- | :--------------------------------------------------------: | ------------------------------------------------------ | | `primaryContract` **`indexed`** | `address` | Address of the deployed primary contract. | | `secondaryContract` **`indexed`** | `address` | Address of the deployed secondary contract. | | `primaryContractDeployment` | `ILSP23LinkedContractsFactory.PrimaryContractDeployment` | Parameters used for the primary contract deployment. | | `secondaryContractDeployment` | `ILSP23LinkedContractsFactory.SecondaryContractDeployment` | Parameters used for the secondary contract deployment. | | `postDeploymentModule` | `address` | Address of the post-deployment module. | | `postDeploymentModuleCalldata` | `bytes` | Calldata passed to the post-deployment module. |
### DeployedERC1167Proxies :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#deployederc1167proxies) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Event signature: `DeployedERC1167Proxies(address,address,ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit,ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit,address,bytes)` - Event topic hash: `0xb03dbe7a02c063899f863d542410b5b038c8f537045be3a26e7144e0074e1c7b` ::: ```solidity event DeployedERC1167Proxies( address indexed primaryContract, address indexed secondaryContract, ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit primaryContractDeploymentInit, ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit secondaryContractDeploymentInit, address postDeploymentModule, bytes postDeploymentModuleCalldata ); ``` Emitted when proxies of a primary and secondary contract are deployed. #### Parameters | Name | Type | Description | | --------------------------------- | :------------------------------------------------------------: | ------------------------------------------------------------ | | `primaryContract` **`indexed`** | `address` | Address of the deployed primary contract proxy. | | `secondaryContract` **`indexed`** | `address` | Address of the deployed secondary contract proxy. | | `primaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.PrimaryContractDeploymentInit` | Parameters used for the primary contract proxy deployment. | | `secondaryContractDeploymentInit` | `ILSP23LinkedContractsFactory.SecondaryContractDeploymentInit` | Parameters used for the secondary contract proxy deployment. | | `postDeploymentModule` | `address` | Address of the post-deployment module. | | `postDeploymentModuleCalldata` | `bytes` | Calldata passed to the post-deployment module. |
## Errors ### InvalidValueSum :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#invalidvaluesum) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Error signature: `InvalidValueSum()` - Error hash: `0x2fd9ca91` ::: ```solidity error InvalidValueSum(); ``` _Invalid value sent._ Reverts when the `msg.value` sent is not equal to the sum of value used for the deployment of the contract & its owner contract.
### PrimaryContractProxyInitFailureError :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#primarycontractproxyinitfailureerror) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Error signature: `PrimaryContractProxyInitFailureError(bytes)` - Error hash: `0x4364b6ee` ::: ```solidity error PrimaryContractProxyInitFailureError(bytes errorData); ``` _Failed to deploy & initialize the Primary Contract Proxy. Error: `errorData`._ Reverts when the deployment & initialization of the contract has failed. #### Parameters | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `errorData` | `bytes` | Potentially information about why the deployment & initialization have failed. |
### SecondaryContractProxyInitFailureError :::note References - Specification details: [**LSP-23-LinkedContractsFactory**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#secondarycontractproxyinitfailureerror) - Solidity implementation: [`LSP23LinkedContractsFactory.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts/contracts/LSP23LinkedContractsFactory.sol) - Error signature: `SecondaryContractProxyInitFailureError(bytes)` - Error hash: `0x9654a854` ::: ```solidity error SecondaryContractProxyInitFailureError(bytes errorData); ``` _Failed to deploy & initialize the Secondary Contract Proxy. Error: `errorData`._ Reverts when the deployment & initialization of the secondary contract has failed. #### Parameters | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `errorData` | `bytes` | Potentially information about why the deployment & initialization have failed. |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP25MultiChannelNonce :::info Standard Specifications [`LSP-25-ExecuteRelayCall`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-25-ExecuteRelayCall.md) ::: :::info Solidity implementation [`LSP25MultiChannelNonce.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp25-contracts/contracts/ILSP25ExecuteRelayCall.sol) ::: > Implementation of the multi channel nonce and the signature verification defined in the LSP25 standard. This contract can be used as a backbone for other smart contracts to implement meta-transactions via the LSP25 Execute Relay Call interface. It contains a storage of nonces for signer addresses across various channel IDs, enabling these signers to submit signed transactions that order-independent. (transactions that do not need to be submitted one after the other in a specific order). Finally, it contains internal functions to verify signatures for specific calldata according the signature format specified in the LSP25 standard. ## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_getNonce ```solidity function _getNonce( address from, uint128 channelId ) internal view returns (uint256 idx); ``` Read the nonce for a `from` address on a specific `channelId`. This will return an `idx`, which is the concatenation of two `uint128` as follow: 1. the `channelId` where the nonce was queried for. 2. the actual nonce of the given `channelId`. For example, if on `channelId` number `5`, the latest nonce is `1`, the `idx` returned by this function will be: ``` // in decimals = 1701411834604692317316873037158841057281 idx = 0x0000000000000000000000000000000500000000000000000000000000000001 ``` This idx can be described as follow: ``` channelId => 5 nonce in this channel => 1 v------------------------------v-------------------------------v 0x0000000000000000000000000000000500000000000000000000000000000001 ``` #### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `from` | `address` | The address to read the nonce for. | | `channelId` | `uint128` | The channel in which to extract the nonce. | #### Returns | Name | Type | Description | | ----- | :-------: | ---------------------------------------------------------------------------------------------------------------------- | | `idx` | `uint256` | The idx composed of two `uint128`: the channelId + nonce in channel concatenated together in a single `uint256` value. |
### \_recoverSignerFromLSP25Signature ```solidity function _recoverSignerFromLSP25Signature( bytes signature, uint256 nonce, uint256 validityTimestamps, uint256 msgValue, bytes callData ) internal view returns (address); ``` Recover the address of the signer that generated a `signature` using the parameters provided `nonce`, `validityTimestamps`, `msgValue` and `callData`. The address of the signer will be recovered using the LSP25 signature format. #### Parameters | Name | Type | Description | | -------------------- | :-------: | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `signature` | `bytes` | A 65 bytes long signature generated according to the signature format specified in the LSP25 standard. | | `nonce` | `uint256` | The nonce that the signer used to generate the `signature`. | | `validityTimestamps` | `uint256` | The validity timestamp that the signer used to generate the signature (See [`_verifyValidityTimestamps`](#_verifyvaliditytimestamps) to learn more). | | `msgValue` | `uint256` | The amount of native tokens intended to be sent for the relay transaction. | | `callData` | `bytes` | The calldata to execute as a relay transaction that the signer signed for. | #### Returns | Name | Type | Description | | ---- | :-------: | -------------------------------------------------------- | | `0` | `address` | The address that signed, recovered from the `signature`. |
### \_verifyValidityTimestamps ```solidity function _verifyValidityTimestamps(uint256 validityTimestamps) internal view; ``` Verify that the current timestamp is within the date and time range provided by `validityTimestamps`. #### Parameters | Name | Type | Description | | -------------------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `validityTimestamps` | `uint256` | Two `uint128` concatenated together, where the left-most `uint128` represent the timestamp from which the transaction can be executed, |
### \_isValidNonce ```solidity function _isValidNonce(address from, uint256 idx) internal view returns (bool); ``` Verify that the nonce `_idx` for `_from` (obtained via [`getNonce`](#getnonce)) is valid in its channel ID. The "idx" is a 256bits (unsigned) integer, where: - the 128 leftmost bits = channelId - and the 128 rightmost bits = nonce within the channel #### Parameters | Name | Type | Description | | ------ | :-------: | ---------------------------------------------------------------------------- | | `from` | `address` | The signer's address. | | `idx` | `uint256` | The concatenation of the `channelId` + `nonce` within a specific channel ID. | #### Returns | Name | Type | Description | | ---- | :----: | ------------------------------------------------------------------------ | | `0` | `bool` | true if the nonce is the latest nonce for the `signer`, false otherwise. |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP4DigitalAssetMetadata :::info Standard Specifications [`LSP-4-DigitalAsset-Metadata`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md) ::: :::info Solidity implementation [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) ::: > Implementation of a LSP4DigitalAssetMetadata contract that stores the **Token-Metadata** (`LSP4TokenName` and `LSP4TokenSymbol`) in its ERC725Y data store. Standard Implementation of the LSP4 standard. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### getData :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#getdata) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#getdatabatch) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### owner :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#owner) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#renounceownership) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### setData :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#setdata) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#setdatabatch) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#supportsinterface) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### transferOwnership :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#transferownership) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data keys `LSP4TokenName` and `LSP4TokenSymbol` cannot be changed via this function once the digital asset contract has been deployed.
## Events ### DataChanged :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#datachanged) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OwnershipTransferred :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#ownershiptransferred) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#ownablecallernottheowner) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-4-DigitalAsset-Metadata**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP6KeyManager :::info Standard Specifications [`LSP-6-KeyManager`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md) ::: :::info Solidity implementation [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) ::: > Implementation of a contract acting as a controller of an ERC725 Account, using permissions stored in the ERC725Y storage. All the permissions can be set on the ERC725 Account using `setData(bytes32,bytes)` or `setData(bytes32[],bytes[])`. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#constructor) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) ::: ```solidity constructor(address target_); ``` _Deploying a LSP6KeyManager linked to the contract at address `target_`._ Deploy a Key Manager and set the `target_` address in the contract storage, making this Key Manager linked to this `target_` contract. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------------------------------------------ | | `target_` | `address` | The address of the contract to control and forward calldata payloads to. |
### VERSION :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#version) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `VERSION()` - Function selector: `0xffa1ad74` ::: ```solidity function VERSION() external view returns (string); ``` _Contract version._ #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `string` | - |
### execute :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#execute) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `execute(bytes)` - Function selector: `0x09c5eabe` ::: ```solidity function execute(bytes payload) external payable returns (bytes); ``` _Executing the following payload on the linked contract: `payload`_ Execute A `payload` on the linked [`target`](#target) contract after having verified the permissions associated with the function being run. The `payload` MUST be a valid abi-encoded function call of one of the functions present in the linked [`target`](#target), otherwise the call will fail. The linked [`target`](#target) will return some data on successful execution, or revert on failure.
**Emitted events:** - [`PermissionsVerified`](#permissionsverified) event when the permissions related to `payload` have been verified successfully.
#### Parameters | Name | Type | Description | | --------- | :-----: | --------------------------------------------------------------------------- | | `payload` | `bytes` | The abi-encoded function call to execute on the linked [`target`](#target). | #### Returns | Name | Type | Description | | ---- | :-----: | --------------------------------------------------------------------------------------- | | `0` | `bytes` | The abi-decoded data returned by the function called on the linked [`target`](#target). |
### executeBatch :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#executebatch) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `executeBatch(uint256[],bytes[])` - Function selector: `0xbf0176ff` ::: ```solidity function executeBatch( uint256[] values, bytes[] payloads ) external payable returns (bytes[]); ``` \*Executing the following batch of payloads and sensind on the linked contract. - payloads: `payloads` - values transferred for each payload: `values`\* Same as [`execute`](#execute) but execute a batch of payloads (abi-encoded function calls) in a single transaction.
**Emitted events:** - [`PermissionsVerified`](#permissionsverified) event for each permissions related to each `payload` that have been verified successfully.
#### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------------------------------------------------------------- | | `values` | `uint256[]` | An array of amount of native tokens to be transferred for each `payload`. | | `payloads` | `bytes[]` | An array of abi-encoded function calls to execute successively on the linked [`target`](#target). | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------------------------------------------------ | | `0` | `bytes[]` | An array of abi-decoded data returned by the functions called on the linked [`target`](#target). |
### executeRelayCall :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#executerelaycall) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `executeRelayCall(bytes,uint256,uint256,bytes)` - Function selector: `0x4c8a4e74` ::: :::tip Hint If you are looking to learn how to sign and execute relay transactions via the Key Manager, see our Javascript step by step guide [_"Execute Relay Transactions"_](../../../learn/universal-profile/key-manager/execute-relay-transactions.md). See the LSP6 Standard page for more details on how to [generate a valid signature for Execute Relay Call](/standards/access-control/lsp6-key-manager.md#how-to-sign-relay-transactions). ::: ```solidity function executeRelayCall( bytes signature, uint256 nonce, uint256 validityTimestamps, bytes payload ) external payable returns (bytes); ``` _Executing the following payload given the nonce `nonce` and signature `signature`. Payload: `payload`_ Allows any address (executor) to execute a payload (= abi-encoded function call), given they have a valid signature from a signer address and a valid `nonce` for this signer. The signature MUST be generated according to the signature format defined by the LSP25 standard. The signer that generated the `signature` MUST be a controller with some permissions on the linked [`target`](#target). The `payload` will be executed on the [`target`](#target) contract once the LSP25 signature and the permissions of the signer have been verified.
**Emitted events:** - [`PermissionsVerified`](#permissionsverified) event when the permissions related to `payload` have been verified successfully.
#### Parameters | Name | Type | Description | | -------------------- | :-------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `signature` | `bytes` | A 65 bytes long signature for a meta transaction according to LSP25. | | `nonce` | `uint256` | The nonce of the address that signed the calldata (in a specific `_channel`), obtained via [`getNonce`](#getnonce). Used to prevent replay attack. | | `validityTimestamps` | `uint256` | Two `uint128` timestamps concatenated together that describes when the relay transaction is valid "from" (left `uint128`) and "until" as a deadline (right `uint128`). | | `payload` | `bytes` | The abi-encoded function call to execute. | #### Returns | Name | Type | Description | | ---- | :-----: | ------------------------------------------------- | | `0` | `bytes` | The data being returned by the function executed. |
### executeRelayCallBatch :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#executerelaycallbatch) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `executeRelayCallBatch(bytes[],uint256[],uint256[],uint256[],bytes[])` - Function selector: `0xa20856a5` ::: ```solidity function executeRelayCallBatch( bytes[] signatures, uint256[] nonces, uint256[] validityTimestamps, uint256[] values, bytes[] payloads ) external payable returns (bytes[]); ``` _Executing a batch of relay calls (= meta-transactions)._ Same as [`executeRelayCall`](#executerelaycall) but execute a batch of signed calldata payloads (abi-encoded function calls) in a single transaction. The `signatures` can be from multiple controllers, not necessarely the same controller, as long as each of these controllers that signed have the right permissions related to the calldata `payload` they signed.
**Requirements:** - the length of `signatures`, `nonces`, `validityTimestamps`, `values` and `payloads` MUST be the same. - the value sent to this function (`msg.value`) MUST be equal to the sum of all `values` in the batch. There should not be any excess value sent to this function.
#### Parameters | Name | Type | Description | | -------------------- | :---------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `signatures` | `bytes[]` | An array of 65 bytes long signatures for meta transactions according to LSP25. | | `nonces` | `uint256[]` | An array of nonces of the addresses that signed the calldata payloads (in specific channels). Obtained via [`getNonce`](#getnonce). Used to prevent replay attack. | | `validityTimestamps` | `uint256[]` | An array of two `uint128` concatenated timestamps that describe when the relay transaction is valid "from" (left `uint128`) and "until" (right `uint128`). | | `values` | `uint256[]` | An array of amount of native tokens to be transferred for each calldata `payload`. | | `payloads` | `bytes[]` | An array of abi-encoded function calls to be executed successively. | #### Returns | Name | Type | Description | | ---- | :-------: | ---------------------------------------------------------------- | | `0` | `bytes[]` | An array of abi-decoded data returned by the functions executed. |
### getNonce :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#getnonce) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `getNonce(address,uint128)` - Function selector: `0xb44581d9` ::: :::tip Hint A signer can choose its channel number arbitrarily. The recommended practice is to: - use `channelId == 0` for transactions for which the ordering of execution matters.abi _Example: you have two transactions A and B, and transaction A must be executed first and complete successfully before transaction B should be executed)._ - use any other `channelId` number for transactions that you want to be order independent (out-of-order execution, execution _"in parallel"_). \_Example: you have two transactions A and B. You want transaction B to be executed a) without having to wait for transaction A to complete, or b) regardless if transaction A completed successfully or not. ::: ```solidity function getNonce( address from, uint128 channelId ) external view returns (uint256); ``` _Reading the latest nonce of address `from` in the channel ID `channelId`._ Get the nonce for a specific `from` address that can be used for signing relay transactions via [`executeRelayCall`](#executerelaycall). #### Parameters | Name | Type | Description | | ----------- | :-------: | -------------------------------------------------------------------------- | | `from` | `address` | The address of the signer of the transaction. | | `channelId` | `uint128` | The channel id that the signer wants to use for executing the transaction. | #### Returns | Name | Type | Description | | ---- | :-------: | -------------------------------------------- | | `0` | `uint256` | The current nonce on a specific `channelId`. |
### isValidSignature :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#isvalidsignature) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `isValidSignature(bytes32,bytes)` - Function selector: `0x1626ba7e` ::: :::caution Warning This function does not enforce by default the inclusion of the address of this contract in the signature digest. It is recommended that protocols or applications using this contract include the targeted address (= this contract) in the data to sign. To ensure that a signature is valid for a specific LSP6KeyManager and prevent signatures from the same EOA to be replayed across different LSP6KeyManager. ::: ```solidity function isValidSignature( bytes32 dataHash, bytes signature ) external view returns (bytes4 returnedStatus); ``` Checks if a signature was signed by a controller that has the permission `SIGN`. If the signer is a controller with the permission `SIGN`, it will return the ERC1271 success value. #### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------- | | `dataHash` | `bytes32` | - | | `signature` | `bytes` | Signature byte array associated with \_data | #### Returns | Name | Type | Description | | ---------------- | :------: | ---------------------------------------------------- | | `returnedStatus` | `bytes4` | `0x1626ba7e` on success, or `0xffffffff` on failure. |
### lsp20VerifyCall :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#lsp20verifycall) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `lsp20VerifyCall(address,address,address,uint256,bytes)` - Function selector: `0xde928f14` ::: :::tip Hint This function can call by any other address than the [`target`](#`target`). This allows to verify permissions in a _"read-only"_ manner. Anyone can call this function to verify if the `caller` has the right permissions to perform the abi-encoded function call `data` on the [`target`](#`target`) contract (while sending `msgValue` alongside the call). If the permissions have been verified successfully and `caller` is authorized, one of the following two LSP20 success value will be returned: - `0x1a238000`: LSP20 success value **without** post verification (last byte is `0x00`). - `0x1a238001`: LSP20 success value **with** post-verification (last byte is `0x01`). ::: ```solidity function lsp20VerifyCall( address, address targetContract, address caller, uint256 msgValue, bytes callData ) external nonpayable returns (bytes4); ``` #### Parameters | Name | Type | Description | | ---------------- | :-------: | ------------------------------------------------------------- | | `_0` | `address` | - | | `targetContract` | `address` | - | | `caller` | `address` | The address who called the function on the `target` contract. | | `msgValue` | `uint256` | - | | `callData` | `bytes` | The calldata sent by the caller to the msg.sender | #### Returns | Name | Type | Description | | ---- | :------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `0` | `bytes4` | MUST return the first 3 bytes of `lsp20VerifyCall(address,uint256,bytes)` function selector if the call to the function is allowed, concatenated with a byte that determines if the lsp20VerifyCallResult function should be called after the original function call. The byte that invoke the lsp20VerifyCallResult function is strictly `0x01`. |
### lsp20VerifyCallResult :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#lsp20verifycallresult) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `lsp20VerifyCallResult(bytes32,bytes)` - Function selector: `0xd3fc45d3` ::: ```solidity function lsp20VerifyCallResult( bytes32, bytes ) external nonpayable returns (bytes4); ``` #### Parameters | Name | Type | Description | | ---- | :-------: | ----------- | | `_0` | `bytes32` | - | | `_1` | `bytes` | - | #### Returns | Name | Type | Description | | ---- | :------: | ---------------------------------------------------------------------------------------------- | | `0` | `bytes4` | MUST return the lsp20VerifyCallResult function selector if the call to the function is allowed |
### supportsInterface :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#supportsinterface) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` See [`IERC165-supportsInterface`](#ierc165-supportsinterface). #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### target :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#target) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Function signature: `target()` - Function selector: `0xd4b83992` ::: ```solidity function target() external view returns (address); ``` Get The address of the contract linked to this Key Manager. #### Returns | Name | Type | Description | | ---- | :-------: | ---------------------------------- | | `0` | `address` | The address of the linked contract |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_verifyCanSetData ```solidity function _verifyCanSetData( address controlledContract, address controllerAddress, bytes32 controllerPermissions, bytes32 inputDataKey, bytes inputDataValue ) internal view; ``` verify if the `controllerAddress` has the permissions required to set a data key on the ERC725Y storage of the `controlledContract`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------------------------- | | `controlledContract` | `address` | the address of the ERC725Y contract where the data key is set. | | `controllerAddress` | `address` | the address of the controller who wants to set the data key. | | `controllerPermissions` | `bytes32` | the permissions of the controller address. | | `inputDataKey` | `bytes32` | the data key to set on the `controlledContract`. | | `inputDataValue` | `bytes` | the data value to set for the `inputDataKey`. |
### \_verifyCanSetData ```solidity function _verifyCanSetData( address controlledContract, address controller, bytes32 permissions, bytes32[] inputDataKeys, bytes[] inputDataValues ) internal view; ``` verify if the `controllerAddress` has the permissions required to set an array of data keys on the ERC725Y storage of the `controlledContract`. #### Parameters | Name | Type | Description | | -------------------- | :---------: | -------------------------------------------------------------- | | `controlledContract` | `address` | the address of the ERC725Y contract where the data key is set. | | `controller` | `address` | the address of the controller who wants to set the data key. | | `permissions` | `bytes32` | the permissions of the controller address. | | `inputDataKeys` | `bytes32[]` | an array of data keys to set on the `controlledContract`. | | `inputDataValues` | `bytes[]` | an array of data values to set for the `inputDataKeys`. |
### \_getPermissionRequiredToSetDataKey ```solidity function _getPermissionRequiredToSetDataKey( address controlledContract, bytes32 controllerPermissions, bytes32 inputDataKey, bytes inputDataValue ) internal view returns (bytes32); ``` retrieve the permission required based on the data key to be set on the `controlledContract`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------- | | `controlledContract` | `address` | the address of the ERC725Y contract where the data key is verified. | | `controllerPermissions` | `bytes32` | - | | `inputDataKey` | `bytes32` | the data key to set on the `controlledContract`. Can be related to LSP6 Permissions, LSP1 Delegate or LSP17 Extensions. | | `inputDataValue` | `bytes` | the data value to set for the `inputDataKey`. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------------------------------ | | `0` | `bytes32` | the permission required to set the `inputDataKey` on the `controlledContract`. |
### \_getPermissionToSetPermissionsArray ```solidity function _getPermissionToSetPermissionsArray( address controlledContract, bytes32 inputDataKey, bytes inputDataValue, bool hasBothAddControllerAndEditPermissions ) internal view returns (bytes32); ``` retrieve the permission required to update the `AddressPermissions[]` array data key defined in LSP6. #### Parameters | Name | Type | Description | | ---------------------------------------- | :-------: | ----------------------------------------------------------------------------------------- | | `controlledContract` | `address` | the address of the ERC725Y contract where the data key is verified. | | `inputDataKey` | `bytes32` | either `AddressPermissions[]` (array length) or `AddressPermissions[index]` (array index) | | `inputDataValue` | `bytes` | the updated value for the `inputDataKey`. MUST be: | | `hasBothAddControllerAndEditPermissions` | `bool` | - | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------- | | `0` | `bytes32` | either ADD or CHANGE PERMISSIONS. |
### \_getPermissionToSetControllerPermissions ```solidity function _getPermissionToSetControllerPermissions( address controlledContract, bytes32 inputPermissionDataKey ) internal view returns (bytes32); ``` retrieve the permission required to set permissions for a controller address. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ------------------------------------------------------------------- | | `controlledContract` | `address` | the address of the ERC725Y contract where the data key is verified. | | `inputPermissionDataKey` | `bytes32` | `AddressPermissions:Permissions:`. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------- | | `0` | `bytes32` | either ADD or CHANGE PERMISSIONS. |
### \_getPermissionToSetAllowedCalls ```solidity function _getPermissionToSetAllowedCalls( address controlledContract, bytes32 dataKey, bytes dataValue, bool hasBothAddControllerAndEditPermissions ) internal view returns (bytes32); ``` Retrieve the permission required to set some AllowedCalls for a controller. #### Parameters | Name | Type | Description | | ---------------------------------------- | :-------: | ------------------------------------------------------------------------------------------- | | `controlledContract` | `address` | The address of the ERC725Y contract from which to fetch the value of `dataKey`. | | `dataKey` | `bytes32` | A data key ion the format `AddressPermissions:AllowedCalls:`. | | `dataValue` | `bytes` | The updated value for the `dataKey`. MUST be a bytes32[CompactBytesArray] of Allowed Calls. | | `hasBothAddControllerAndEditPermissions` | `bool` | - | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------- | | `0` | `bytes32` | Either ADD or EDIT PERMISSIONS. |
### \_getPermissionToSetAllowedERC725YDataKeys ```solidity function _getPermissionToSetAllowedERC725YDataKeys( address controlledContract, bytes32 dataKey, bytes dataValue, bool hasBothAddControllerAndEditPermissions ) internal view returns (bytes32); ``` Retrieve the permission required to set some Allowed ERC725Y Data Keys for a controller. #### Parameters | Name | Type | Description | | ---------------------------------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `controlledContract` | `address` | the address of the ERC725Y contract from which to fetch the value of `dataKey`. | | `dataKey` | `bytes32` | A data key in the format `AddressPermissions:AllowedERC725YDataKeys:`. | | `dataValue` | `bytes` | The updated value for the `dataKey`. MUST be a bytes[CompactBytesArray] of Allowed ERC725Y Data Keys. | | `hasBothAddControllerAndEditPermissions` | `bool` | - | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------- | | `0` | `bytes32` | Either ADD or EDIT PERMISSIONS. |
### \_getPermissionToSetLSP1Delegate ```solidity function _getPermissionToSetLSP1Delegate( address controlledContract, bytes32 lsp1DelegateDataKey ) internal view returns (bytes32); ``` retrieve the permission required to either add or change the address of a LSP1 Universal Receiver Delegate stored under a specific LSP1 data key. #### Parameters | Name | Type | Description | | --------------------- | :-------: | -------------------------------------------------------------------- | | `controlledContract` | `address` | the address of the ERC725Y contract where the data key is verified. | | `lsp1DelegateDataKey` | `bytes32` | either the data key for the default `LSP1UniversalReceiverDelegate`, | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------------- | | `0` | `bytes32` | either ADD or CHANGE UNIVERSALRECEIVERDELEGATE. |
### \_getPermissionToSetLSP17Extension ```solidity function _getPermissionToSetLSP17Extension( address controlledContract, bytes32 lsp17ExtensionDataKey ) internal view returns (bytes32); ``` Verify if `controller` has the required permissions to either add or change the address of an LSP0 Extension stored under a specific LSP17Extension data key #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ------------------------------------------------------------------- | | `controlledContract` | `address` | the address of the ERC725Y contract where the data key is verified. | | `lsp17ExtensionDataKey` | `bytes32` | the dataKey to set with `_LSP17_EXTENSION_PREFIX` as prefix. |
### \_verifyAllowedERC725YSingleKey ```solidity function _verifyAllowedERC725YSingleKey( address controllerAddress, bytes32 inputDataKey, bytes allowedERC725YDataKeysCompacted ) internal pure; ``` Verify if the `inputKey` is present in the list of `allowedERC725KeysCompacted` for the `controllerAddress`. #### Parameters | Name | Type | Description | | --------------------------------- | :-------: | ----------------------------------------------------------------------------------------- | | `controllerAddress` | `address` | the address of the controller. | | `inputDataKey` | `bytes32` | the data key to verify against the allowed ERC725Y Data Keys for the `controllerAddress`. | | `allowedERC725YDataKeysCompacted` | `bytes` | a CompactBytesArray of allowed ERC725Y Data Keys for the `controllerAddress`. |
### \_verifyAllowedERC725YDataKeys ```solidity function _verifyAllowedERC725YDataKeys( address controllerAddress, bytes32[] inputDataKeys, bytes allowedERC725YDataKeysCompacted, bool[] validatedInputKeysList, uint256 allowedDataKeysFound ) internal pure; ``` Verify if all the `inputDataKeys` are present in the list of `allowedERC725KeysCompacted` of the `controllerAddress`. #### Parameters | Name | Type | Description | | --------------------------------- | :---------: | ---------------------------------------------------------------------------------------------------------------------------- | | `controllerAddress` | `address` | the address of the controller. | | `inputDataKeys` | `bytes32[]` | the data keys to verify against the allowed ERC725Y Data Keys of the `controllerAddress`. | | `allowedERC725YDataKeysCompacted` | `bytes` | a CompactBytesArray of allowed ERC725Y Data Keys of the `controllerAddress`. | | `validatedInputKeysList` | `bool[]` | an array of booleans to store the result of the verification of each data keys checked. | | `allowedDataKeysFound` | `uint256` | the number of data keys that were previously validated for other permissions like `ADDCONTROLLER`, `EDITPERMISSIONS`, etc... |
### \_requirePermissions ```solidity function _requirePermissions( address controller, bytes32 addressPermissions, bytes32 permissionRequired ) internal pure; ``` Check if the `controller` has the `permissionRequired` among its permission listed in `controllerPermissions` If not, this function will revert with the error `NotAuthorised` and the name of the permission missing by the controller. #### Parameters | Name | Type | Description | | -------------------- | :-------: | --------------------------------- | | `controller` | `address` | the caller address | | `addressPermissions` | `bytes32` | the caller's permissions BitArray | | `permissionRequired` | `bytes32` | the required permission |
### \_verifyCanExecute ```solidity function _verifyCanExecute( address controlledContract, address controller, bytes32 permissions, uint256 operationType, address to, uint256 value, bytes data ) internal view; ``` verify if `controllerAddress` has the required permissions to interact with other addresses using the controlledContract. #### Parameters | Name | Type | Description | | -------------------- | :-------: | -------------------------------------------------------------------------------------------------------- | | `controlledContract` | `address` | the address of the ERC725 contract where the payload is executed and where the permissions are verified. | | `controller` | `address` | the address who want to run the execute function on the ERC725Account. | | `permissions` | `bytes32` | the permissions of the controller address. | | `operationType` | `uint256` | - | | `to` | `address` | - | | `value` | `uint256` | - | | `data` | `bytes` | - |
### \_verifyCanDeployContract ```solidity function _verifyCanDeployContract( address controller, bytes32 permissions, bool isFundingContract ) internal view; ```
### \_verifyCanStaticCall ```solidity function _verifyCanStaticCall( address controlledContract, address controller, bytes32 permissions, address to, uint256 value, bytes data ) internal view; ```
### \_verifyCanCall ```solidity function _verifyCanCall( address controlledContract, address controller, bytes32 permissions, address to, uint256 value, bytes data ) internal view; ```
### \_verifyAllowedCall ```solidity function _verifyAllowedCall( address controlledContract, address controllerAddress, uint256 operationType, address to, uint256 value, bytes data ) internal view; ```
### \_extractCallType ```solidity function _extractCallType( uint256 operationType, uint256 value, bytes data ) internal pure returns (bytes4 requiredCallTypes); ``` extract the bytes4 representation of a single bit for the type of call according to the `operationType` #### Parameters | Name | Type | Description | | --------------- | :-------: | -------------------------------------------- | | `operationType` | `uint256` | 0 = CALL, 3 = STATICCALL or 3 = DELEGATECALL | | `value` | `uint256` | - | | `data` | `bytes` | - | #### Returns | Name | Type | Description | | ------------------- | :------: | --------------------------------------------------------- | | `requiredCallTypes` | `bytes4` | a bytes4 value containing a single 1 bit for the callType |
### \_isAllowedAddress ```solidity function _isAllowedAddress( bytes allowedCall, address to ) internal pure returns (bool); ```
### \_isAllowedStandard ```solidity function _isAllowedStandard( bytes allowedCall, address to ) internal view returns (bool); ```
### \_isAllowedFunction ```solidity function _isAllowedFunction( bytes allowedCall, bytes data ) internal pure returns (bool); ```
### \_isAllowedCallType ```solidity function _isAllowedCallType( bytes allowedCall, bytes4 requiredCallTypes ) internal pure returns (bool); ```
### \_verifyExecuteRelayCallPermission ```solidity function _verifyExecuteRelayCallPermission( address controllerAddress, bytes32 controllerPermissions ) internal pure; ```
### \_verifyOwnershipPermissions ```solidity function _verifyOwnershipPermissions( address controllerAddress, bytes32 controllerPermissions ) internal pure; ```
### \_getNonce ```solidity function _getNonce( address from, uint128 channelId ) internal view returns (uint256 idx); ``` Read the nonce for a `from` address on a specific `channelId`. This will return an `idx`, which is the concatenation of two `uint128` as follow: 1. the `channelId` where the nonce was queried for. 2. the actual nonce of the given `channelId`. For example, if on `channelId` number `5`, the latest nonce is `1`, the `idx` returned by this function will be: ``` // in decimals = 1701411834604692317316873037158841057281 idx = 0x0000000000000000000000000000000500000000000000000000000000000001 ``` This idx can be described as follow: ``` channelId => 5 nonce in this channel => 1 v------------------------------v-------------------------------v 0x0000000000000000000000000000000500000000000000000000000000000001 ``` #### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `from` | `address` | The address to read the nonce for. | | `channelId` | `uint128` | The channel in which to extract the nonce. | #### Returns | Name | Type | Description | | ----- | :-------: | ---------------------------------------------------------------------------------------------------------------------- | | `idx` | `uint256` | The idx composed of two `uint128`: the channelId + nonce in channel concatenated together in a single `uint256` value. |
### \_recoverSignerFromLSP25Signature ```solidity function _recoverSignerFromLSP25Signature( bytes signature, uint256 nonce, uint256 validityTimestamps, uint256 msgValue, bytes callData ) internal view returns (address); ``` Recover the address of the signer that generated a `signature` using the parameters provided `nonce`, `validityTimestamps`, `msgValue` and `callData`. The address of the signer will be recovered using the LSP25 signature format. #### Parameters | Name | Type | Description | | -------------------- | :-------: | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `signature` | `bytes` | A 65 bytes long signature generated according to the signature format specified in the LSP25 standard. | | `nonce` | `uint256` | The nonce that the signer used to generate the `signature`. | | `validityTimestamps` | `uint256` | The validity timestamp that the signer used to generate the signature (See [`_verifyValidityTimestamps`](#_verifyvaliditytimestamps) to learn more). | | `msgValue` | `uint256` | The amount of native tokens intended to be sent for the relay transaction. | | `callData` | `bytes` | The calldata to execute as a relay transaction that the signer signed for. | #### Returns | Name | Type | Description | | ---- | :-------: | -------------------------------------------------------- | | `0` | `address` | The address that signed, recovered from the `signature`. |
### \_verifyValidityTimestamps ```solidity function _verifyValidityTimestamps(uint256 validityTimestamps) internal view; ``` Verify that the current timestamp is within the date and time range provided by `validityTimestamps`. #### Parameters | Name | Type | Description | | -------------------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `validityTimestamps` | `uint256` | Two `uint128` concatenated together, where the left-most `uint128` represent the timestamp from which the transaction can be executed, |
### \_isValidNonce ```solidity function _isValidNonce(address from, uint256 idx) internal view returns (bool); ``` Verify that the nonce `_idx` for `_from` (obtained via [`getNonce`](#getnonce)) is valid in its channel ID. The "idx" is a 256bits (unsigned) integer, where: - the 128 leftmost bits = channelId - and the 128 rightmost bits = nonce within the channel #### Parameters | Name | Type | Description | | ------ | :-------: | ---------------------------------------------------------------------------- | | `from` | `address` | The signer's address. | | `idx` | `uint256` | The concatenation of the `channelId` + `nonce` within a specific channel ID. | #### Returns | Name | Type | Description | | ---- | :----: | ------------------------------------------------------------------------ | | `0` | `bool` | true if the nonce is the latest nonce for the `signer`, false otherwise. |
### \_execute ```solidity function _execute( uint256 msgValue, bytes payload ) internal nonpayable returns (bytes); ```
### \_executeRelayCall :::caution Warning Be aware that this function can also throw an error if the `callData` was signed incorrectly (not conforming to the signature format defined in the LSP25 standard). This is because the contract cannot distinguish if the data is signed correctly or not. Instead, it will recover an incorrect signer address from the signature and throw an [`InvalidRelayNonce`](#invalidrelaynonce) error with the incorrect signer address as the first parameter. ::: ```solidity function _executeRelayCall( bytes signature, uint256 nonce, uint256 validityTimestamps, uint256 msgValue, bytes payload ) internal nonpayable returns (bytes); ``` Validate that the `nonce` given for the `signature` signed and the `payload` to execute is valid and conform to the signature format according to the LSP25 standard. #### Parameters | Name | Type | Description | | -------------------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `signature` | `bytes` | A valid signature for a signer, generated according to the signature format specified in the LSP25 standard. | | `nonce` | `uint256` | The nonce that the signer used to generate the `signature`. | | `validityTimestamps` | `uint256` | Two `uint128` concatenated together, where the left-most `uint128` represent the timestamp from which the transaction can be executed, | | `msgValue` | `uint256` | - | | `payload` | `bytes` | The abi-encoded function call to execute. |
### \_executePayload ```solidity function _executePayload( address targetContract, uint256 msgValue, bytes payload ) internal nonpayable returns (bytes); ``` _Execute the `payload` passed to `execute(...)` or `executeRelayCall(...)`_ #### Parameters | Name | Type | Description | | ---------------- | :-------: | ----------------------------------------------------------------------------- | | `targetContract` | `address` | - | | `msgValue` | `uint256` | - | | `payload` | `bytes` | The abi-encoded function call to execute on the [`target`](#target) contract. | #### Returns | Name | Type | Description | | ---- | :-----: | ------------------------------------------------------------------------------------ | | `0` | `bytes` | bytes The data returned by the call made to the linked [`target`](#target) contract. |
### \_verifyPermissions ```solidity function _verifyPermissions( address targetContract, address from, bool isRelayedCall, bytes payload ) internal view; ``` Verify if the `from` address is allowed to execute the `payload` on the [`target`](#target) contract linked to this Key Manager. #### Parameters | Name | Type | Description | | ---------------- | :-------: | ---------------------------------------------------------------------------------------------------- | | `targetContract` | `address` | The contract that is owned by the Key Manager | | `from` | `address` | Either the caller of [`execute`](#execute) or the signer of [`executeRelayCall`](#executerelaycall). | | `isRelayedCall` | `bool` | - | | `payload` | `bytes` | The abi-encoded function call to execute on the [`target`](#target) contract. |
### \_nonReentrantBefore ```solidity function _nonReentrantBefore( address targetContract, bool isSetData, address from ) internal nonpayable returns (bool reentrancyStatus); ``` Check if we are in the context of a reentrant call, by checking if the reentrancy status is `true`. - If the status is `true`, the caller (or signer for relay call) MUST have the `REENTRANCY` permission. Otherwise, the call is reverted. - If the status is `false`, it is set to `true` only if we are not dealing with a call to the functions `setData` or `setDataBatch`. Used at the beginning of the [`lsp20VerifyCall`](#`lsp20verifycall`), [`_execute`](#`_execute`) and [`_executeRelayCall`](#`_executerelaycall`) functions, before the methods execution starts.
### \_nonReentrantAfter ```solidity function _nonReentrantAfter(address targetContract) internal nonpayable; ``` Resets the reentrancy status to `false` Used at the end of the [`lsp20VerifyCall`](#`lsp20verifycall`), [`_execute`](#`_execute`) and [`_executeRelayCall`](#`_executerelaycall`) functions after the functions' execution is terminated.
## Events ### PermissionsVerified :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#permissionsverified) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Event signature: `PermissionsVerified(address,uint256,bytes4)` - Event topic hash: `0xc0a62328f6bf5e3172bb1fcb2019f54b2c523b6a48e3513a2298fbf0150b781e` ::: ```solidity event PermissionsVerified( address indexed signer, uint256 indexed value, bytes4 indexed selector ); ``` _Verified the permissions of `signer` for calling function `selector` on the linked account and sending `value` of native token._ Emitted when the LSP6KeyManager contract verified the permissions of the `signer` successfully. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `signer` **`indexed`** | `address` | The address of the controller that executed the calldata payload (either directly via [`execute`](#execute) or via meta transaction using [`executeRelayCall`](#executerelaycall)). | | `value` **`indexed`** | `uint256` | The amount of native token to be transferred in the calldata payload. | | `selector` **`indexed`** | `bytes4` | The bytes4 function of the function that was executed on the linked [`target`](#target) |
## Errors ### BatchExecuteParamsLengthMismatch :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#batchexecuteparamslengthmismatch) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `BatchExecuteParamsLengthMismatch()` - Error hash: `0x55a187db` ::: ```solidity error BatchExecuteParamsLengthMismatch(); ``` _The array parameters provided to the function `executeBatch(...)` do not have the same number of elements. (Different array param's length)._ Reverts when the array parameters `uint256[] value` and `bytes[] payload` have different sizes. There should be the same number of elements for each array parameters.
### BatchExecuteRelayCallParamsLengthMismatch :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#batchexecuterelaycallparamslengthmismatch) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `BatchExecuteRelayCallParamsLengthMismatch()` - Error hash: `0xb4d50d21` ::: ```solidity error BatchExecuteRelayCallParamsLengthMismatch(); ``` _The array parameters provided to the function `executeRelayCallBatch(...)` do not have the same number of elements. (Different array param's length)._ Reverts when providing array parameters of different sizes to `executeRelayCallBatch(bytes[],uint256[],bytes[])`
### CallingKeyManagerNotAllowed :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#callingkeymanagernotallowed) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `CallingKeyManagerNotAllowed()` - Error hash: `0xa431b236` ::: ```solidity error CallingKeyManagerNotAllowed(); ``` _Calling the Key Manager address for this transaction is disallowed._ Reverts when calling the KeyManager through `execute(uint256,address,uint256,bytes)`.
### DelegateCallDisallowedViaKeyManager :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#delegatecalldisallowedviakeymanager) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `DelegateCallDisallowedViaKeyManager()` - Error hash: `0x80d6ebae` ::: ```solidity error DelegateCallDisallowedViaKeyManager(); ``` _Performing DELEGATE CALLS via the Key Manager is currently disallowed._ Reverts when trying to do a `delegatecall` via the ERC725X.execute(uint256,address,uint256,bytes) (operation type 4) function of the linked [`target`](#target). `DELEGATECALL` is disallowed by default on the LSP6KeyManager.
### ERC725X_ExecuteParametersEmptyArray :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#erc725x_executeparametersemptyarray) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `ERC725X_ExecuteParametersEmptyArray()` - Error hash: `0xe9ad2b5f` ::: ```solidity error ERC725X_ExecuteParametersEmptyArray(); ``` Reverts when one of the array parameter provided to the [`executeBatch`](#executebatch) function is an empty array.
### ERC725X_ExecuteParametersLengthMismatch :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#erc725x_executeparameterslengthmismatch) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `ERC725X_ExecuteParametersLengthMismatch()` - Error hash: `0x3ff55f4d` ::: ```solidity error ERC725X_ExecuteParametersLengthMismatch(); ``` Reverts when there is not the same number of elements in the `operationTypes`, `targets` addresses, `values`, and `datas` array parameters provided when calling the [`executeBatch`](#executebatch) function.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### InvalidDataValuesForDataKeys :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#invaliddatavaluesfordatakeys) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `InvalidDataValuesForDataKeys(bytes32,bytes)` - Error hash: `0x1fa41397` ::: ```solidity error InvalidDataValuesForDataKeys(bytes32 dataKey, bytes dataValue); ``` _Data value: `dataValue` length is different from the required length for the data key which is set._ Reverts when the data value length is not one of the required lengths for the specific data key. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------------------------------------------------------- | | `dataKey` | `bytes32` | The data key that has a required length for the data value. | | `dataValue` | `bytes` | The data value that has an invalid length. |
### InvalidERC725Function :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#invaliderc725function) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `InvalidERC725Function(bytes4)` - Error hash: `0x2ba8851c` ::: ```solidity error InvalidERC725Function(bytes4 invalidFunction); ``` _The Key Manager could not verify the calldata of the transaction because it could not recognise the function being called. Invalid function selector: `invalidFunction`._ Reverts when trying to call a function on the linked [`target`](#target), that is not any of the following: - `setData(bytes32,bytes)` (ERC725Y) - `setDataBatch(bytes32[],bytes[])` (ERC725Y) - `execute(uint256,address,uint256,bytes)` (ERC725X) - `transferOwnership(address)` (LSP14) - `acceptOwnership()` (LSP14) - `renounceOwnership()` (LSP14) #### Parameters | Name | Type | Description | | ----------------- | :------: | --------------------------------------------------------------------------------------------------------------------------- | | `invalidFunction` | `bytes4` | The `bytes4` selector of the function that was attempted to be called on the linked [`target`](#target) but not recognised. |
### InvalidEncodedAllowedCalls :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#invalidencodedallowedcalls) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `InvalidEncodedAllowedCalls(bytes)` - Error hash: `0x187e77ab` ::: ```solidity error InvalidEncodedAllowedCalls(bytes allowedCallsValue); ``` _Could not decode the Allowed Calls. Value = `allowedCallsValue`._ Reverts when `allowedCallsValue` is not properly encoded as a `(bytes4,address,bytes4,bytes4)[CompactBytesArray]` (CompactBytesArray made of tuples that are 32 bytes long each). See LSP2 value type `CompactBytesArray` for more infos. #### Parameters | Name | Type | Description | | ------------------- | :-----: | ----------------------------------------------------------------------------------------------------------------- | | `allowedCallsValue` | `bytes` | The list of allowedCalls that are not encoded correctly as a `(bytes4,address,bytes4,bytes4)[CompactBytesArray]`. |
### InvalidEncodedAllowedERC725YDataKeys :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#invalidencodedallowederc725ydatakeys) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `InvalidEncodedAllowedERC725YDataKeys(bytes,string)` - Error hash: `0xae6cbd37` ::: ```solidity error InvalidEncodedAllowedERC725YDataKeys(bytes value, string context); ``` _Error when reading the Allowed ERC725Y Data Keys. Reason: `context`, Allowed ERC725Y Data Keys value read: `value`._ Reverts when `value` is not encoded properly as a `bytes32[CompactBytesArray]`. The `context` string provides context on when this error occurred (\_e.g: when fetching the `AllowedERC725YDataKeys` to verify the permissions of a controller, or when validating the `AllowedERC725YDataKeys` when setting them for a controller). #### Parameters | Name | Type | Description | | --------- | :------: | ---------------------------------------------------------- | | `value` | `bytes` | The value that is not a valid `bytes32[CompactBytesArray]` | | `context` | `string` | A brief description of where the error occurred. |
### InvalidLSP6Target :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#invalidlsp6target) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `InvalidLSP6Target()` - Error hash: `0xfc854579` ::: ```solidity error InvalidLSP6Target(); ``` _Invalid address supplied to link this Key Manager to (`address(0)`)._ Reverts when the address provided to set as the [`target`](#target) linked to this KeyManager is invalid (_e.g. `address(0)`_).
### InvalidPayload :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#invalidpayload) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `InvalidPayload(bytes)` - Error hash: `0x3621bbcc` ::: ```solidity error InvalidPayload(bytes payload); ``` _Invalid calldata payload sent._ Reverts when the payload is invalid. #### Parameters | Name | Type | Description | | --------- | :-----: | ----------- | | `payload` | `bytes` | - |
### InvalidRelayNonce :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#invalidrelaynonce) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `InvalidRelayNonce(address,uint256,bytes)` - Error hash: `0xc9bd9eb9` ::: ```solidity error InvalidRelayNonce(address signer, uint256 invalidNonce, bytes signature); ``` _The relay call failed because an invalid nonce was provided for the address `signer` that signed the execute relay call. Invalid nonce: `invalidNonce`, signature of signer: `signature`._ Reverts when the `signer` address retrieved from the `signature` has an invalid nonce: `invalidNonce`. #### Parameters | Name | Type | Description | | -------------- | :-------: | ---------------------------------------------------- | | `signer` | `address` | The address of the signer. | | `invalidNonce` | `uint256` | The nonce retrieved for the `signer` address. | | `signature` | `bytes` | The signature used to retrieve the `signer` address. |
### InvalidWhitelistedCall :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#invalidwhitelistedcall) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `InvalidWhitelistedCall(address)` - Error hash: `0x6fd203c5` ::: ```solidity error InvalidWhitelistedCall(address from); ``` _Invalid allowed calls (`0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff`) set for address `from`. Could not perform external call._ Reverts when a `from` address has _"any whitelisted call"_ as allowed call set. This revert happens during the verification of the permissions of the address for its allowed calls. A `from` address is not allowed to have 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff in its list of `AddressPermissions:AllowedCalls:
`, as this allows any STANDARD:ADDRESS:FUNCTION. This is equivalent to granting the SUPER permission and should never be valid. #### Parameters | Name | Type | Description | | ------ | :-------: | ---------------------------------------------------------------------- | | `from` | `address` | The controller address that has _"any allowed calls"_ whitelisted set. |
### KeyManagerCannotBeSetAsExtensionForLSP20Functions :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#keymanagercannotbesetasextensionforlsp20functions) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `KeyManagerCannotBeSetAsExtensionForLSP20Functions()` - Error hash: `0x4a9fa8cf` ::: ```solidity error KeyManagerCannotBeSetAsExtensionForLSP20Functions(); ``` _Key Manager cannot be used as an LSP17 extension for LSP20 functions._ Reverts when the address of the Key Manager is being set as extensions for lsp20 functions
### LSP6BatchExcessiveValueSent :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#lsp6batchexcessivevaluesent) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `LSP6BatchExcessiveValueSent(uint256,uint256)` - Error hash: `0xa51868b6` ::: ```solidity error LSP6BatchExcessiveValueSent(uint256 totalValues, uint256 msgValue); ``` _Too much funds sent to forward each amount in the batch. No amount of native tokens should stay in the Key Manager._ This error occurs when there was too much funds sent to the batch functions `execute(uint256[],bytes[])` or `executeRelayCall(bytes[],uint256[],uint256[],bytes[])` to cover the sum of all the values forwarded on Reverts to avoid the KeyManager to holds some remaining funds sent to the following batch functions: - execute(uint256[],bytes[]) - executeRelayCall(bytes[],uint256[],uint256[],bytes[]) This error occurs when `msg.value` is more than the sum of all the values being forwarded on each payloads (`values[]` parameter from the batch functions above). #### Parameters | Name | Type | Description | | ------------- | :-------: | ----------- | | `totalValues` | `uint256` | - | | `msgValue` | `uint256` | - |
### LSP6BatchInsufficientValueSent :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#lsp6batchinsufficientvaluesent) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `LSP6BatchInsufficientValueSent(uint256,uint256)` - Error hash: `0x30a324ac` ::: ```solidity error LSP6BatchInsufficientValueSent(uint256 totalValues, uint256 msgValue); ``` _Not enough funds sent to forward each amount in the batch._ This error occurs when there was not enough funds sent to the batch functions `execute(uint256[],bytes[])` or `executeRelayCall(bytes[],uint256[],uint256[],bytes[])` to cover the sum of all the values forwarded on each payloads (`values[]` parameter from the batch functions above). This mean that `msg.value` is less than the sum of all the values being forwarded on each payloads (`values[]` parameters). #### Parameters | Name | Type | Description | | ------------- | :-------: | ------------------------------------------------------------------------------------------------------------------------------------------------ | | `totalValues` | `uint256` | The sum of all the values forwarded on each payloads (`values[]` parameter from the batch functions above). | | `msgValue` | `uint256` | The amount of native tokens sent to the batch functions `execute(uint256[],bytes[])` or `executeRelayCall(bytes[],uint256[],uint256[],bytes[])`. |
### NoCallsAllowed :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#nocallsallowed) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `NoCallsAllowed(address)` - Error hash: `0x6cb60587` ::: ```solidity error NoCallsAllowed(address from); ``` _The address `from` is not authorised to use the linked account contract to make external calls, because it has no Allowed Calls set._ Reverts when the `from` address has no `AllowedCalls` set and cannot interact with any address using the linked [`target`](#target). #### Parameters | Name | Type | Description | | ------ | :-------: | ------------------------------------- | | `from` | `address` | The address that has no AllowedCalls. |
### NoERC725YDataKeysAllowed :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#noerc725ydatakeysallowed) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `NoERC725YDataKeysAllowed(address)` - Error hash: `0xed7fa509` ::: ```solidity error NoERC725YDataKeysAllowed(address from); ``` _The address `from` is not authorised to set data, because it has no ERC725Y Data Key allowed._ Reverts when the `from` address has no AllowedERC725YDataKeys set and cannot set any ERC725Y data key on the ERC725Y storage of the linked [`target`](#target). #### Parameters | Name | Type | Description | | ------ | :-------: | ----------------------------------------------------- | | `from` | `address` | The address that has no `AllowedERC725YDataKeys` set. |
### NoPermissionsSet :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#nopermissionsset) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `NoPermissionsSet(address)` - Error hash: `0xf292052a` ::: ```solidity error NoPermissionsSet(address from); ``` _The address `from` does not have any permission set on the contract linked to the Key Manager._ Reverts when address `from` does not have any permissions set on the account linked to this Key Manager #### Parameters | Name | Type | Description | | ------ | :-------: | ------------------------------------------ | | `from` | `address` | the address that does not have permissions |
### NotAllowedCall :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#notallowedcall) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `NotAllowedCall(address,address,bytes4)` - Error hash: `0x45147bce` ::: ```solidity error NotAllowedCall(address from, address to, bytes4 selector); ``` _The address `from` is not authorised to call the function `selector` on the `to` address._ Reverts when `from` is not authorised to call the `execute(uint256,address,uint256,bytes)` function because of a not allowed callType, address, standard or function. #### Parameters | Name | Type | Description | | ---------- | :-------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The controller that tried to call the `execute(uint256,address,uint256,bytes)` function. | | `to` | `address` | The address of an EOA or contract that `from` tried to call using the linked [`target`](#target) | | `selector` | `bytes4` | If `to` is a contract, the bytes4 selector of the function that `from` is trying to call. If no function is called (_e.g: a native token transfer_), selector = `0x00000000` |
### NotAllowedERC725YDataKey :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#notallowederc725ydatakey) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `NotAllowedERC725YDataKey(address,bytes32)` - Error hash: `0x557ae079` ::: ```solidity error NotAllowedERC725YDataKey(address from, bytes32 disallowedKey); ``` _The address `from` is not authorised to set the data key `disallowedKey` on the contract linked to the Key Manager._ Reverts when address `from` is not authorised to set the key `disallowedKey` on the linked [`target`](#target). #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------------------------------------------------------------------------------------------------------------- | | `from` | `address` | address The controller that tried to `setData` on the linked [`target`](#target). | | `disallowedKey` | `bytes32` | A bytes32 data key that `from` is not authorised to set on the ERC725Y storage of the linked [`target`](#target). |
### NotAuthorised :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#notauthorised) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `NotAuthorised(address,string)` - Error hash: `0x3bdad6e6` ::: ```solidity error NotAuthorised(address from, string permission); ``` _The address `from` is not authorised to `permission` on the contract linked to the Key Manager._ Reverts when address `from` is not authorised and does not have `permission` on the linked [`target`](#target) #### Parameters | Name | Type | Description | | ------------ | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | address The address that was not authorised. | | `permission` | `string` | permission The permission required (\_e.g: `SETDATA`, `CALL`, `TRANSFERVALUE`) |
### NotRecognisedPermissionKey :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#notrecognisedpermissionkey) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `NotRecognisedPermissionKey(bytes32)` - Error hash: `0x0f7d735b` ::: ```solidity error NotRecognisedPermissionKey(bytes32 dataKey); ``` _The data key `dataKey` starts with `AddressPermissions` prefix but is none of the permission data keys defined in LSP6._ Reverts when `dataKey` is a `bytes32` value that does not adhere to any of the permission data keys defined by the LSP6 standard #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------------------------------------------------ | | `dataKey` | `bytes32` | The dataKey that does not match any of the standard LSP6 permission data keys. |
### RelayCallBeforeStartTime :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#relaycallbeforestarttime) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `RelayCallBeforeStartTime()` - Error hash: `0x00de4b8a` ::: ```solidity error RelayCallBeforeStartTime(); ``` _Relay call not valid yet._ Reverts when the relay call is cannot yet bet executed. This mean that the starting timestamp provided to [`executeRelayCall`](#executerelaycall) function is bigger than the current timestamp.
### RelayCallExpired :::note References - Specification details: [**LSP-6-KeyManager**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#relaycallexpired) - Solidity implementation: [`LSP6KeyManager.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) - Error signature: `RelayCallExpired()` - Error hash: `0x5c53a98c` ::: ```solidity error RelayCallExpired(); ``` _Relay call expired (deadline passed)._ Reverts when the period to execute the relay call has expired.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP7DigitalAsset :::info Standard Specifications [`LSP-7-DigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md) ::: :::info Solidity implementation [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: > Implementation of a LSP7 Digital Asset, a contract that represents a fungible token. Minting and transferring are supplied with a `uint256` amount. This implementation is agnostic to the way tokens are created. A supply mechanism has to be added in a derived contract using [`_mint`](#_mint) For a generic mechanism, see [`LSP7Mintable`](#lsp7mintable). ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### fallback :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#fallback) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), revert.
### receive :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#receive) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: ```solidity receive() external payable; ``` _LSP7 contract cannot receive native tokens._ Reverts whenever someone tries to send native tokens to a LSP7 contract.
### authorizeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#authorizeoperator) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `authorizeOperator(address,uint256,bytes)` - Function selector: `0xb49506fd` ::: :::danger To avoid front-running and Allowance Double-Spend Exploit when increasing or decreasing the authorized amount of an operator, it is advised to use the [`increaseAllowance`](#increaseallowance) and [`decreaseAllowance`](#decreaseallowance) functions. For more information, see: https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/ ::: ```solidity function authorizeOperator( address operator, uint256 amount, bytes operatorNotificationData ) external nonpayable; ``` Sets an `amount` of tokens that an `operator` has access from the caller's balance (allowance). See [`authorizedAmountFor`](#authorizedamountfor). Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------ | | `operator` | `address` | The address to authorize as an operator. | | `amount` | `uint256` | The allowance amount of tokens operator has access to. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### authorizedAmountFor :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#authorizedamountfor) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `authorizedAmountFor(address,address)` - Function selector: `0x65aeaa95` ::: ```solidity function authorizedAmountFor( address operator, address tokenOwner ) external view returns (uint256); ``` Get the amount of tokens `operator` address has access to from `tokenOwner`. Operators can send and burn tokens on behalf of their owners. #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------- | | `operator` | `address` | The operator's address to query the authorized amount for. | | `tokenOwner` | `address` | The token owner that `operator` has allowance on. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------------------------------------------- | | `0` | `uint256` | The amount of tokens the `operator`'s address has access on the `tokenOwner`'s balance. |
### balanceOf :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#balanceof) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `balanceOf(address)` - Function selector: `0x70a08231` ::: ```solidity function balanceOf(address tokenOwner) external view returns (uint256); ``` Get the number of tokens owned by `tokenOwner`. If the token is divisible (the [`decimals`](#decimals) function returns `18`), the amount returned should be divided by 1e18 to get a better picture of the actual balance of the `tokenOwner`. _Example:_ `balanceOf(someAddress) -> 42_000_000_000_000_000_000 / 1e18 = 42 tokens` #### Parameters | Name | Type | Description | | ------------ | :-------: | --------------------------------------------------------- | | `tokenOwner` | `address` | The address of the token holder to query the balance for. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------- | | `0` | `uint256` | The amount of tokens owned by `tokenOwner`. |
### batchCalls :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#batchcalls) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### decimals :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#decimals) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `decimals()` - Function selector: `0x313ce567` ::: ```solidity function decimals() external view returns (uint8); ``` Returns the number of decimals used to get its user representation. If the asset contract has been set to be non-divisible via the `isNonDivisible_` parameter in the `constructor`, the decimals returned will be `0`. Otherwise `18` is the common value. #### Returns | Name | Type | Description | | ---- | :-----: | ----------------------------------------------------------------------- | | `0` | `uint8` | the number of decimals. If `0` is returned, the asset is non-divisible. |
### decreaseAllowance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#decreaseallowance) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `decreaseAllowance(address,address,uint256,bytes)` - Function selector: `0x78381670` ::: ```solidity function decreaseAllowance( address operator, address tokenOwner, uint256 subtractedAmount, bytes operatorNotificationData ) external nonpayable; ``` _Decrease the allowance of `operator` by -`subtractedAmount`_ Atomically decreases the allowance granted to `operator` by the caller. This is an alternative approach to [`authorizeOperator`](#authorizeoperator) that can be used as a mitigation for the double spending allowance problem. Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------ | | `operator` | `address` | The operator to decrease allowance for `msg.sender` | | `tokenOwner` | `address` | The address of the token owner. | | `subtractedAmount` | `uint256` | The amount to decrease by in the operator's allowance. | | `operatorNotificationData` | `bytes` | - |
### getData :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getdata) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getdatabatch) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### getOperatorsOf :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getoperatorsof) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getOperatorsOf(address)` - Function selector: `0xd72fc29a` ::: ```solidity function getOperatorsOf(address tokenOwner) external view returns (address[]); ``` Returns all `operator` addresses that are allowed to transfer or burn on behalf of `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `tokenOwner` | `address` | The token owner to get the operators for. | #### Returns | Name | Type | Description | | ---- | :---------: | ----------------------------------------------------------------------------------- | | `0` | `address[]` | An array of operators allowed to transfer or burn tokens on behalf of `tokenOwner`. |
### increaseAllowance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#increaseallowance) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `increaseAllowance(address,uint256,bytes)` - Function selector: `0x2bc1da82` ::: ```solidity function increaseAllowance( address operator, uint256 addedAmount, bytes operatorNotificationData ) external nonpayable; ``` _Increase the allowance of `operator` by +`addedAmount`_ Atomically increases the allowance granted to `operator` by the caller. This is an alternative approach to [`authorizeOperator`](#authorizeoperator) that can be used as a mitigation for the double spending allowance problem. Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------- | | `operator` | `address` | The operator to increase the allowance for `msg.sender` | | `addedAmount` | `uint256` | The additional amount to add on top of the current operator's allowance | | `operatorNotificationData` | `bytes` | - |
### owner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#owner) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#renounceownership) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### revokeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `revokeOperator(address,address,bool,bytes)` - Function selector: `0x30d0dc37` ::: ```solidity function revokeOperator( address operator, address tokenOwner, bool notify, bytes operatorNotificationData ) external nonpayable; ``` Enables `tokenOwner` to remove `operator` for its tokens, disallowing it to send any amount of tokens on its behalf. This function also allows the `operator` to remove itself if it is the caller of this function #### Parameters | Name | Type | Description | | -------------------------- | :-------: | --------------------------------------------------------- | | `operator` | `address` | The address to revoke as an operator. | | `tokenOwner` | `address` | The address of the token owner. | | `notify` | `bool` | Boolean indicating whether to notify the operator or not. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### setData :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#setdata) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#setdatabatch) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#supportsinterface) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas. #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### totalSupply :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#totalsupply) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `totalSupply()` - Function selector: `0x18160ddd` ::: ```solidity function totalSupply() external view returns (uint256); ``` Returns the number of existing tokens that have been minted in this contract. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------ | | `0` | `uint256` | The number of existing tokens. |
### transfer :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transfer) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transfer(address,address,uint256,bool,bytes)` - Function selector: `0x760d9bba` ::: ```solidity function transfer( address from, address to, uint256 amount, bool force, bytes data ) external nonpayable; ``` Transfers an `amount` of tokens from the `from` address to the `to` address and notify both sender and recipients via the LSP1 [`universalReceiver(...)`](#`universalreceiver) function. If the tokens are transferred by an operator on behalf of a token holder, the allowance for the operator will be decreased by `amount` once the token transfer has been completed (See [`authorizedAmountFor`](#authorizedamountfor)). #### Parameters | Name | Type | Description | | -------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The sender address. | | `to` | `address` | The recipient address. | | `amount` | `uint256` | The amount of tokens to transfer. | | `force` | `bool` | When set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. |
### transferBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transferbatch) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transferBatch(address[],address[],uint256[],bool[],bytes[])` - Function selector: `0x2d7667c9` ::: ```solidity function transferBatch( address[] from, address[] to, uint256[] amount, bool[] force, bytes[] data ) external nonpayable; ``` Same as [`transfer(...)`](#`transfer) but transfer multiple tokens based on the arrays of `from`, `to`, `amount`. #### Parameters | Name | Type | Description | | -------- | :---------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address[]` | An array of sending addresses. | | `to` | `address[]` | An array of receiving addresses. | | `amount` | `uint256[]` | An array of amount of tokens to transfer for each `from -> to` transfer. | | `force` | `bool[]` | For each transfer, when set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes[]` | An array of additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. |
### transferOwnership :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transferownership) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data keys `LSP4TokenName` and `LSP4TokenSymbol` cannot be changed via this function once the digital asset contract has been deployed.
### \_updateOperator ```solidity function _updateOperator( address tokenOwner, address operator, uint256 allowance, bool notified, bytes operatorNotificationData ) internal nonpayable; ``` Changes token `amount` the `operator` has access to from `tokenOwner` tokens. If the amount is zero the operator is removed from the list of operators, otherwise he is added to the list of operators. If the amount is zero then the operator is being revoked, otherwise the operator amount is being modified. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------- | | `tokenOwner` | `address` | The address that will give `operator` an allowance for on its balance. | | `operator` | `address` | @param operatorNotificationData The data to send to the universalReceiver function of the operator in case of notifying | | `allowance` | `uint256` | The maximum amount of token that `operator` can spend from the `tokenOwner`'s balance. | | `notified` | `bool` | Boolean indicating whether the operator has been notified about the change of allowance | | `operatorNotificationData` | `bytes` | The data to send to the universalReceiver function of the operator in case of notifying |
### \_mint :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the recipient via LSP1**. ::: ```solidity function _mint( address to, uint256 amount, bool force, bytes data ) internal nonpayable; ``` Mints `amount` of tokens and transfers it to `to`.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as `from`.
#### Parameters | Name | Type | Description | | -------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to mint tokens for. | | `amount` | `uint256` | The amount of tokens to mint. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `data` | `bytes` | Additional data the caller wants included in the emitted [`Transfer`](#transfer) event, and sent in the LSP1 hook to the `to` address. |
### \_burn :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the sender via LSP1**. ::: :::tip Hint In dApps, you can know which address is burning tokens by listening for the `Transfer` event and filter with the zero address as `to`. ::: ```solidity function _burn(address from, uint256 amount, bytes data) internal nonpayable; ``` Burns (= destroys) `amount` of tokens, decrease the `from` balance. This is done by sending them to the zero address. Both the sender and recipient will be notified of the token transfer through the LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as the `to` address
#### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address to burn tokens from its balance. | | `amount` | `uint256` | The amount of tokens to burn. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. |
### \_spendAllowance ```solidity function _spendAllowance( address operator, address tokenOwner, uint256 amountToSpend ) internal nonpayable; ``` Spend `amountToSpend` from the `operator`'s authorized on behalf of the `tokenOwner`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ------------------------------------------------------------------- | | `operator` | `address` | The address of the operator to decrease the allowance of. | | `tokenOwner` | `address` | The address that granted an allowance on its balance to `operator`. | | `amountToSpend` | `uint256` | The amount of tokens to subtract in allowance of `operator`. |
### \_transfer :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the sender/recipient via LSP1**. ::: ```solidity function _transfer( address from, address to, uint256 amount, bool force, bytes data ) internal nonpayable; ``` Transfer tokens from `from` to `to` by decreasing the balance of `from` by `-amount` and increasing the balance of `to` by `+amount`. Both the sender and recipient will be notified of the token transfer through the LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event.
#### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address to decrease the balance. | | `to` | `address` | The address to increase the balance. | | `amount` | `uint256` | The amount of tokens to transfer from `from` to `to`. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. |
### \_beforeTokenTransfer ```solidity function _beforeTokenTransfer( address from, address to, uint256 amount, bytes data ) internal nonpayable; ``` Hook that is called before any token transfer, including minting and burning. Allows to run custom logic before updating balances and notifying sender/recipient by overriding this function. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------ | | `from` | `address` | The sender address | | `to` | `address` | The recipient address | | `amount` | `uint256` | The amount of token to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_afterTokenTransfer ```solidity function _afterTokenTransfer( address from, address to, uint256 amount, bytes data ) internal nonpayable; ``` Hook that is called after any token transfer, including minting and burning. Allows to run custom logic after updating balances, but **before notifying sender/recipient** by overriding this function. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------ | | `from` | `address` | The sender address | | `to` | `address` | The recipient address | | `amount` | `uint256` | The amount of token to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_notifyTokenOperator ```solidity function _notifyTokenOperator( address operator, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the operator `operator` about the `amount` tokens being authorized with. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENOPERATOR` as typeId, if `operator` is a contract that supports the LSP1 interface. If `operator` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `operator` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `operator` address in the `universalReceiver` call. |
### \_notifyTokenSender ```solidity function _notifyTokenSender(address from, bytes lsp1Data) internal nonpayable; ``` Attempt to notify the token sender `from` about the `amount` of tokens being transferred. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. If `from` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. |
### \_notifyTokenReceiver ```solidity function _notifyTokenReceiver( address to, bool force, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the token receiver `to` about the `amount` tokens being received. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. If `to` is is an EOA or a contract that does not support the LSP1 interface, the behaviour will depend on the `force` boolean flag. - if `force` is set to `true`, nothing will happen and no notification will be sent. - if `force` is set to `false, the transaction will revert. #### Parameters | Name | Type | Description | | ---------- | :-------: | --------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `lsp1Data` | `bytes` | The data to be sent to the `to` address in the `universalReceiver(...)` call. |
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0). - we do not check that payable bool as in lsp7 standard we will always forward the value to the extension
### \_fallbackLSP17Extendable :::info The LSP7 Token contract should not hold any native tokens. Any native tokens received by the contract will be forwarded to the extension address mapped to the selector from `msg.sig`. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call with the received value to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the address(0) will be returned. Forwards the value if the extension is payable. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the CALL opcode, passing the [`msg.data`](#msg.data) appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the [`msg.value`](#msg.value)
## Events ### DataChanged :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#datachanged) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OperatorAuthorizationChanged :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorauthorizationchanged) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OperatorAuthorizationChanged(address,address,uint256,bytes)` - Event topic hash: `0xf772a43bfdf4729b196e3fb54a818b91a2ca6c49d10b2e16278752f9f515c25d` ::: ```solidity event OperatorAuthorizationChanged( address indexed operator, address indexed tokenOwner, uint256 indexed amount, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` enables `operator` for `amount` tokens. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address authorized as an operator | | `tokenOwner` **`indexed`** | `address` | The token owner | | `amount` **`indexed`** | `uint256` | The amount of tokens `operator` address has access to from `tokenOwner` | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OperatorRevoked :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorrevoked) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OperatorRevoked(address,address,bool,bytes)` - Event topic hash: `0x0ebf5762d8855cbe012d2ca42fb33a81175e17c8a8751f8859931ba453bd4167` ::: ```solidity event OperatorRevoked( address indexed operator, address indexed tokenOwner, bool indexed notified, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` disables `operator` for `amount` tokens and set its [`authorizedAmountFor(...)`](#`authorizedamountfor) to `0`. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address revoked from operating | | `tokenOwner` **`indexed`** | `address` | The token owner | | `notified` **`indexed`** | `bool` | Bool indicating whether the operator has been notified or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OwnershipTransferred :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownershiptransferred) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### Transfer :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transfer) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `Transfer(address,address,address,uint256,bool,bytes)` - Event topic hash: `0x3997e418d2cef0b3b0e907b1e39605c3f7d32dbd061e82ea5b4a770d46a160a6` ::: ```solidity event Transfer( address indexed operator, address indexed from, address indexed to, uint256 amount, bool force, bytes data ); ``` Emitted when the `from` transferred successfully `amount` of tokens to `to`. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ---------------------------------------------------------------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address of the operator that executed the transfer. | | `from` **`indexed`** | `address` | The address which tokens were sent from (balance decreased by `-amount`). | | `to` **`indexed`** | `address` | The address that received the tokens (balance increased by `+amount`). | | `amount` | `uint256` | The amount of tokens transferred. | | `force` | `bool` | if the transferred enforced the `to` recipient address to be a contract that implements the LSP1 standard or not. | | `data` | `bytes` | Any additional data included by the caller during the transfer, and sent in the LSP1 hooks to the `from` and `to` addresses. |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### InvalidExtensionAddress :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#invalidextensionaddress) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `InvalidExtensionAddress(bytes)` - Error hash: `0x42bfe79f` ::: ```solidity error InvalidExtensionAddress(bytes storedData); ``` reverts when the bytes retrieved from the LSP17 data key is not a valid address (not 20 bytes) #### Parameters | Name | Type | Description | | ------------ | :-----: | ----------- | | `storedData` | `bytes` | - |
### InvalidFunctionSelector :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#invalidfunctionselector) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `InvalidFunctionSelector(bytes)` - Error hash: `0xe5099ee3` ::: ```solidity error InvalidFunctionSelector(bytes data); ``` reverts when the contract is called with a function selector not valid (less than 4 bytes of data) #### Parameters | Name | Type | Description | | ------ | :-----: | ----------- | | `data` | `bytes` | - |
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### LSP7AmountExceedsAuthorizedAmount :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsauthorizedamount) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7AmountExceedsAuthorizedAmount(address,uint256,address,uint256)` - Error hash: `0xf3a6b691` ::: ```solidity error LSP7AmountExceedsAuthorizedAmount( address tokenOwner, uint256 authorizedAmount, address operator, uint256 amount ); ``` reverts when `operator` of `tokenOwner` send an `amount` of tokens larger than the `authorizedAmount`. #### Parameters | Name | Type | Description | | ------------------ | :-------: | ----------- | | `tokenOwner` | `address` | - | | `authorizedAmount` | `uint256` | - | | `operator` | `address` | - | | `amount` | `uint256` | - |
### LSP7AmountExceedsBalance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsbalance) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7AmountExceedsBalance(uint256,address,uint256)` - Error hash: `0x08d47949` ::: ```solidity error LSP7AmountExceedsBalance( uint256 balance, address tokenOwner, uint256 amount ); ``` reverts when sending an `amount` of tokens larger than the current `balance` of the `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `balance` | `uint256` | - | | `tokenOwner` | `address` | - | | `amount` | `uint256` | - |
### LSP7BatchCallFailed :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7batchcallfailed) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7BatchCallFailed(uint256)` - Error hash: `0xb774c284` ::: ```solidity error LSP7BatchCallFailed(uint256 callIndex); ``` _Batch call failed._ Reverts when a batch call failed. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------- | | `callIndex` | `uint256` | - |
### LSP7CannotSendWithAddressZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotsendwithaddresszero) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CannotSendWithAddressZero()` - Error hash: `0xd2d5ec30` ::: ```solidity error LSP7CannotSendWithAddressZero(); ``` reverts when trying to: - mint tokens to the zero address. - burn tokens from the zero address. - transfer tokens from or to the zero address.
### LSP7CannotUseAddressZeroAsOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotuseaddresszeroasoperator) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CannotUseAddressZeroAsOperator()` - Error hash: `0x6355e766` ::: ```solidity error LSP7CannotUseAddressZeroAsOperator(); ``` reverts when trying to set the zero address as an operator.
### LSP7DecreaseAllowanceNotAuthorized :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreaseallowancenotauthorized) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7DecreaseAllowanceNotAuthorized(address,address,address)` - Error hash: `0x98ce2945` ::: ```solidity error LSP7DecreaseAllowanceNotAuthorized( address caller, address tokenOwner, address operator ); ``` Reverts when the call to decrease allowance is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `operator` | `address` | - |
### LSP7DecreasedAllowanceBelowZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreasedallowancebelowzero) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7DecreasedAllowanceBelowZero()` - Error hash: `0x0ef76c35` ::: ```solidity error LSP7DecreasedAllowanceBelowZero(); ``` Reverts when trying to decrease an operator's allowance to more than its current allowance.
### LSP7InvalidTransferBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7invalidtransferbatch) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7InvalidTransferBatch()` - Error hash: `0x263eee8d` ::: ```solidity error LSP7InvalidTransferBatch(); ``` reverts when the array parameters used in [`transferBatch`](#transferbatch) have different lengths.
### LSP7NotifyTokenReceiverContractMissingLSP1Interface :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceivercontractmissinglsp1interface) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7NotifyTokenReceiverContractMissingLSP1Interface(address)` - Error hash: `0xa608fbb6` ::: ```solidity error LSP7NotifyTokenReceiverContractMissingLSP1Interface( address tokenReceiver ); ``` reverts if the `tokenReceiver` does not implement LSP1 when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP7NotifyTokenReceiverIsEOA :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceiveriseoa) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7NotifyTokenReceiverIsEOA(address)` - Error hash: `0x26c247f4` ::: ```solidity error LSP7NotifyTokenReceiverIsEOA(address tokenReceiver); ``` reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP7RevokeOperatorNotAuthorized :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7revokeoperatornotauthorized) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7RevokeOperatorNotAuthorized(address,address,address)` - Error hash: `0x1a525b32` ::: ```solidity error LSP7RevokeOperatorNotAuthorized( address caller, address tokenOwner, address operator ); ``` Reverts when the call to revoke operator is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `operator` | `address` | - |
### LSP7TokenContractCannotHoldValue :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7tokencontractcannotholdvalue) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7TokenContractCannotHoldValue()` - Error hash: `0x388f5adc` ::: ```solidity error LSP7TokenContractCannotHoldValue(); ``` _LSP7 contract cannot receive native tokens._ Error occurs when sending native tokens to the LSP7 contract without sending any data. E.g. Sending value without passing a bytes4 function selector to call a LSP17 Extension.
### LSP7TokenOwnerCannotBeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7tokenownercannotbeoperator) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7TokenOwnerCannotBeOperator()` - Error hash: `0xdab75047` ::: ```solidity error LSP7TokenOwnerCannotBeOperator(); ``` reverts when trying to authorize or revoke the token's owner as an operator.
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OperatorAllowanceCannotBeIncreasedFromZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorallowancecannotbeincreasedfromzero) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OperatorAllowanceCannotBeIncreasedFromZero(address)` - Error hash: `0xcba6e977` ::: ```solidity error OperatorAllowanceCannotBeIncreasedFromZero(address operator); ``` Reverts when token owner call [`increaseAllowance`](#increaseallowance) for an operator that does not have any allowance #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownablecallernottheowner) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP7Burnable :::info Standard Specifications [`LSP-7-DigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md) ::: :::info Solidity implementation [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: > LSP7 token extension that allows token holders to destroy both their own tokens and those that they have an allowance for as an operator. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### fallback :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#fallback) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), revert.
### receive :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#receive) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: ```solidity receive() external payable; ``` _LSP7 contract cannot receive native tokens._ Reverts whenever someone tries to send native tokens to a LSP7 contract.
### authorizeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#authorizeoperator) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `authorizeOperator(address,uint256,bytes)` - Function selector: `0xb49506fd` ::: :::danger To avoid front-running and Allowance Double-Spend Exploit when increasing or decreasing the authorized amount of an operator, it is advised to use the [`increaseAllowance`](#increaseallowance) and [`decreaseAllowance`](#decreaseallowance) functions. For more information, see: https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/ ::: ```solidity function authorizeOperator( address operator, uint256 amount, bytes operatorNotificationData ) external nonpayable; ``` Sets an `amount` of tokens that an `operator` has access from the caller's balance (allowance). See [`authorizedAmountFor`](#authorizedamountfor). Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------ | | `operator` | `address` | The address to authorize as an operator. | | `amount` | `uint256` | The allowance amount of tokens operator has access to. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### authorizedAmountFor :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#authorizedamountfor) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `authorizedAmountFor(address,address)` - Function selector: `0x65aeaa95` ::: ```solidity function authorizedAmountFor( address operator, address tokenOwner ) external view returns (uint256); ``` Get the amount of tokens `operator` address has access to from `tokenOwner`. Operators can send and burn tokens on behalf of their owners. #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------- | | `operator` | `address` | The operator's address to query the authorized amount for. | | `tokenOwner` | `address` | The token owner that `operator` has allowance on. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------------------------------------------- | | `0` | `uint256` | The amount of tokens the `operator`'s address has access on the `tokenOwner`'s balance. |
### balanceOf :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#balanceof) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `balanceOf(address)` - Function selector: `0x70a08231` ::: ```solidity function balanceOf(address tokenOwner) external view returns (uint256); ``` Get the number of tokens owned by `tokenOwner`. If the token is divisible (the [`decimals`](#decimals) function returns `18`), the amount returned should be divided by 1e18 to get a better picture of the actual balance of the `tokenOwner`. _Example:_ `balanceOf(someAddress) -> 42_000_000_000_000_000_000 / 1e18 = 42 tokens` #### Parameters | Name | Type | Description | | ------------ | :-------: | --------------------------------------------------------- | | `tokenOwner` | `address` | The address of the token holder to query the balance for. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------- | | `0` | `uint256` | The amount of tokens owned by `tokenOwner`. |
### batchCalls :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#batchcalls) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### burn :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#burn) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `burn(address,uint256,bytes)` - Function selector: `0x44d17187` ::: ```solidity function burn(address from, uint256 amount, bytes data) external nonpayable; ``` See internal [`_burn`](#_burn) function for details. #### Parameters | Name | Type | Description | | -------- | :-------: | ----------- | | `from` | `address` | - | | `amount` | `uint256` | - | | `data` | `bytes` | - |
### decimals :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#decimals) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `decimals()` - Function selector: `0x313ce567` ::: ```solidity function decimals() external view returns (uint8); ``` Returns the number of decimals used to get its user representation. If the asset contract has been set to be non-divisible via the `isNonDivisible_` parameter in the `constructor`, the decimals returned will be `0`. Otherwise `18` is the common value. #### Returns | Name | Type | Description | | ---- | :-----: | ----------------------------------------------------------------------- | | `0` | `uint8` | the number of decimals. If `0` is returned, the asset is non-divisible. |
### decreaseAllowance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#decreaseallowance) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `decreaseAllowance(address,address,uint256,bytes)` - Function selector: `0x78381670` ::: ```solidity function decreaseAllowance( address operator, address tokenOwner, uint256 subtractedAmount, bytes operatorNotificationData ) external nonpayable; ``` _Decrease the allowance of `operator` by -`subtractedAmount`_ Atomically decreases the allowance granted to `operator` by the caller. This is an alternative approach to [`authorizeOperator`](#authorizeoperator) that can be used as a mitigation for the double spending allowance problem. Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------ | | `operator` | `address` | The operator to decrease allowance for `msg.sender` | | `tokenOwner` | `address` | The address of the token owner. | | `subtractedAmount` | `uint256` | The amount to decrease by in the operator's allowance. | | `operatorNotificationData` | `bytes` | - |
### getData :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getdata) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getdatabatch) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### getOperatorsOf :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getoperatorsof) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getOperatorsOf(address)` - Function selector: `0xd72fc29a` ::: ```solidity function getOperatorsOf(address tokenOwner) external view returns (address[]); ``` Returns all `operator` addresses that are allowed to transfer or burn on behalf of `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `tokenOwner` | `address` | The token owner to get the operators for. | #### Returns | Name | Type | Description | | ---- | :---------: | ----------------------------------------------------------------------------------- | | `0` | `address[]` | An array of operators allowed to transfer or burn tokens on behalf of `tokenOwner`. |
### increaseAllowance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#increaseallowance) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `increaseAllowance(address,uint256,bytes)` - Function selector: `0x2bc1da82` ::: ```solidity function increaseAllowance( address operator, uint256 addedAmount, bytes operatorNotificationData ) external nonpayable; ``` _Increase the allowance of `operator` by +`addedAmount`_ Atomically increases the allowance granted to `operator` by the caller. This is an alternative approach to [`authorizeOperator`](#authorizeoperator) that can be used as a mitigation for the double spending allowance problem. Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------- | | `operator` | `address` | The operator to increase the allowance for `msg.sender` | | `addedAmount` | `uint256` | The additional amount to add on top of the current operator's allowance | | `operatorNotificationData` | `bytes` | - |
### owner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#owner) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#renounceownership) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### revokeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `revokeOperator(address,address,bool,bytes)` - Function selector: `0x30d0dc37` ::: ```solidity function revokeOperator( address operator, address tokenOwner, bool notify, bytes operatorNotificationData ) external nonpayable; ``` Enables `tokenOwner` to remove `operator` for its tokens, disallowing it to send any amount of tokens on its behalf. This function also allows the `operator` to remove itself if it is the caller of this function #### Parameters | Name | Type | Description | | -------------------------- | :-------: | --------------------------------------------------------- | | `operator` | `address` | The address to revoke as an operator. | | `tokenOwner` | `address` | The address of the token owner. | | `notify` | `bool` | Boolean indicating whether to notify the operator or not. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### setData :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#setdata) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#setdatabatch) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#supportsinterface) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas. #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### totalSupply :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#totalsupply) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `totalSupply()` - Function selector: `0x18160ddd` ::: ```solidity function totalSupply() external view returns (uint256); ``` Returns the number of existing tokens that have been minted in this contract. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------ | | `0` | `uint256` | The number of existing tokens. |
### transfer :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transfer) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transfer(address,address,uint256,bool,bytes)` - Function selector: `0x760d9bba` ::: ```solidity function transfer( address from, address to, uint256 amount, bool force, bytes data ) external nonpayable; ``` Transfers an `amount` of tokens from the `from` address to the `to` address and notify both sender and recipients via the LSP1 [`universalReceiver(...)`](#`universalreceiver) function. If the tokens are transferred by an operator on behalf of a token holder, the allowance for the operator will be decreased by `amount` once the token transfer has been completed (See [`authorizedAmountFor`](#authorizedamountfor)). #### Parameters | Name | Type | Description | | -------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The sender address. | | `to` | `address` | The recipient address. | | `amount` | `uint256` | The amount of tokens to transfer. | | `force` | `bool` | When set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. |
### transferBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transferbatch) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transferBatch(address[],address[],uint256[],bool[],bytes[])` - Function selector: `0x2d7667c9` ::: ```solidity function transferBatch( address[] from, address[] to, uint256[] amount, bool[] force, bytes[] data ) external nonpayable; ``` Same as [`transfer(...)`](#`transfer) but transfer multiple tokens based on the arrays of `from`, `to`, `amount`. #### Parameters | Name | Type | Description | | -------- | :---------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address[]` | An array of sending addresses. | | `to` | `address[]` | An array of receiving addresses. | | `amount` | `uint256[]` | An array of amount of tokens to transfer for each `from -> to` transfer. | | `force` | `bool[]` | For each transfer, when set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes[]` | An array of additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. |
### transferOwnership :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transferownership) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data keys `LSP4TokenName` and `LSP4TokenSymbol` cannot be changed via this function once the digital asset contract has been deployed.
### \_updateOperator ```solidity function _updateOperator( address tokenOwner, address operator, uint256 allowance, bool notified, bytes operatorNotificationData ) internal nonpayable; ``` Changes token `amount` the `operator` has access to from `tokenOwner` tokens. If the amount is zero the operator is removed from the list of operators, otherwise he is added to the list of operators. If the amount is zero then the operator is being revoked, otherwise the operator amount is being modified. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------- | | `tokenOwner` | `address` | The address that will give `operator` an allowance for on its balance. | | `operator` | `address` | @param operatorNotificationData The data to send to the universalReceiver function of the operator in case of notifying | | `allowance` | `uint256` | The maximum amount of token that `operator` can spend from the `tokenOwner`'s balance. | | `notified` | `bool` | Boolean indicating whether the operator has been notified about the change of allowance | | `operatorNotificationData` | `bytes` | The data to send to the universalReceiver function of the operator in case of notifying |
### \_mint :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the recipient via LSP1**. ::: ```solidity function _mint( address to, uint256 amount, bool force, bytes data ) internal nonpayable; ``` Mints `amount` of tokens and transfers it to `to`.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as `from`.
#### Parameters | Name | Type | Description | | -------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to mint tokens for. | | `amount` | `uint256` | The amount of tokens to mint. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `data` | `bytes` | Additional data the caller wants included in the emitted [`Transfer`](#transfer) event, and sent in the LSP1 hook to the `to` address. |
### \_burn :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the sender via LSP1**. ::: :::tip Hint In dApps, you can know which address is burning tokens by listening for the `Transfer` event and filter with the zero address as `to`. ::: ```solidity function _burn(address from, uint256 amount, bytes data) internal nonpayable; ``` Burns (= destroys) `amount` of tokens, decrease the `from` balance. This is done by sending them to the zero address. Both the sender and recipient will be notified of the token transfer through the LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as the `to` address
#### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address to burn tokens from its balance. | | `amount` | `uint256` | The amount of tokens to burn. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. |
### \_spendAllowance ```solidity function _spendAllowance( address operator, address tokenOwner, uint256 amountToSpend ) internal nonpayable; ``` Spend `amountToSpend` from the `operator`'s authorized on behalf of the `tokenOwner`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ------------------------------------------------------------------- | | `operator` | `address` | The address of the operator to decrease the allowance of. | | `tokenOwner` | `address` | The address that granted an allowance on its balance to `operator`. | | `amountToSpend` | `uint256` | The amount of tokens to subtract in allowance of `operator`. |
### \_transfer :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the sender/recipient via LSP1**. ::: ```solidity function _transfer( address from, address to, uint256 amount, bool force, bytes data ) internal nonpayable; ``` Transfer tokens from `from` to `to` by decreasing the balance of `from` by `-amount` and increasing the balance of `to` by `+amount`. Both the sender and recipient will be notified of the token transfer through the LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event.
#### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address to decrease the balance. | | `to` | `address` | The address to increase the balance. | | `amount` | `uint256` | The amount of tokens to transfer from `from` to `to`. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. |
### \_beforeTokenTransfer ```solidity function _beforeTokenTransfer( address from, address to, uint256 amount, bytes data ) internal nonpayable; ``` Hook that is called before any token transfer, including minting and burning. Allows to run custom logic before updating balances and notifying sender/recipient by overriding this function. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------ | | `from` | `address` | The sender address | | `to` | `address` | The recipient address | | `amount` | `uint256` | The amount of token to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_afterTokenTransfer ```solidity function _afterTokenTransfer( address from, address to, uint256 amount, bytes data ) internal nonpayable; ``` Hook that is called after any token transfer, including minting and burning. Allows to run custom logic after updating balances, but **before notifying sender/recipient** by overriding this function. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------ | | `from` | `address` | The sender address | | `to` | `address` | The recipient address | | `amount` | `uint256` | The amount of token to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_notifyTokenOperator ```solidity function _notifyTokenOperator( address operator, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the operator `operator` about the `amount` tokens being authorized with. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENOPERATOR` as typeId, if `operator` is a contract that supports the LSP1 interface. If `operator` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `operator` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `operator` address in the `universalReceiver` call. |
### \_notifyTokenSender ```solidity function _notifyTokenSender(address from, bytes lsp1Data) internal nonpayable; ``` Attempt to notify the token sender `from` about the `amount` of tokens being transferred. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. If `from` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. |
### \_notifyTokenReceiver ```solidity function _notifyTokenReceiver( address to, bool force, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the token receiver `to` about the `amount` tokens being received. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. If `to` is is an EOA or a contract that does not support the LSP1 interface, the behaviour will depend on the `force` boolean flag. - if `force` is set to `true`, nothing will happen and no notification will be sent. - if `force` is set to `false, the transaction will revert. #### Parameters | Name | Type | Description | | ---------- | :-------: | --------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `lsp1Data` | `bytes` | The data to be sent to the `to` address in the `universalReceiver(...)` call. |
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0). - we do not check that payable bool as in lsp7 standard we will always forward the value to the extension
### \_fallbackLSP17Extendable :::info The LSP7 Token contract should not hold any native tokens. Any native tokens received by the contract will be forwarded to the extension address mapped to the selector from `msg.sig`. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call with the received value to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the address(0) will be returned. Forwards the value if the extension is payable. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the CALL opcode, passing the [`msg.data`](#msg.data) appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the [`msg.value`](#msg.value)
## Events ### DataChanged :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#datachanged) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OperatorAuthorizationChanged :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorauthorizationchanged) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OperatorAuthorizationChanged(address,address,uint256,bytes)` - Event topic hash: `0xf772a43bfdf4729b196e3fb54a818b91a2ca6c49d10b2e16278752f9f515c25d` ::: ```solidity event OperatorAuthorizationChanged( address indexed operator, address indexed tokenOwner, uint256 indexed amount, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` enables `operator` for `amount` tokens. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address authorized as an operator | | `tokenOwner` **`indexed`** | `address` | The token owner | | `amount` **`indexed`** | `uint256` | The amount of tokens `operator` address has access to from `tokenOwner` | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OperatorRevoked :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorrevoked) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OperatorRevoked(address,address,bool,bytes)` - Event topic hash: `0x0ebf5762d8855cbe012d2ca42fb33a81175e17c8a8751f8859931ba453bd4167` ::: ```solidity event OperatorRevoked( address indexed operator, address indexed tokenOwner, bool indexed notified, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` disables `operator` for `amount` tokens and set its [`authorizedAmountFor(...)`](#`authorizedamountfor) to `0`. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address revoked from operating | | `tokenOwner` **`indexed`** | `address` | The token owner | | `notified` **`indexed`** | `bool` | Bool indicating whether the operator has been notified or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OwnershipTransferred :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownershiptransferred) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### Transfer :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transfer) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `Transfer(address,address,address,uint256,bool,bytes)` - Event topic hash: `0x3997e418d2cef0b3b0e907b1e39605c3f7d32dbd061e82ea5b4a770d46a160a6` ::: ```solidity event Transfer( address indexed operator, address indexed from, address indexed to, uint256 amount, bool force, bytes data ); ``` Emitted when the `from` transferred successfully `amount` of tokens to `to`. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ---------------------------------------------------------------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address of the operator that executed the transfer. | | `from` **`indexed`** | `address` | The address which tokens were sent from (balance decreased by `-amount`). | | `to` **`indexed`** | `address` | The address that received the tokens (balance increased by `+amount`). | | `amount` | `uint256` | The amount of tokens transferred. | | `force` | `bool` | if the transferred enforced the `to` recipient address to be a contract that implements the LSP1 standard or not. | | `data` | `bytes` | Any additional data included by the caller during the transfer, and sent in the LSP1 hooks to the `from` and `to` addresses. |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### InvalidExtensionAddress :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#invalidextensionaddress) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `InvalidExtensionAddress(bytes)` - Error hash: `0x42bfe79f` ::: ```solidity error InvalidExtensionAddress(bytes storedData); ``` reverts when the bytes retrieved from the LSP17 data key is not a valid address (not 20 bytes) #### Parameters | Name | Type | Description | | ------------ | :-----: | ----------- | | `storedData` | `bytes` | - |
### InvalidFunctionSelector :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#invalidfunctionselector) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `InvalidFunctionSelector(bytes)` - Error hash: `0xe5099ee3` ::: ```solidity error InvalidFunctionSelector(bytes data); ``` reverts when the contract is called with a function selector not valid (less than 4 bytes of data) #### Parameters | Name | Type | Description | | ------ | :-----: | ----------- | | `data` | `bytes` | - |
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### LSP7AmountExceedsAuthorizedAmount :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsauthorizedamount) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7AmountExceedsAuthorizedAmount(address,uint256,address,uint256)` - Error hash: `0xf3a6b691` ::: ```solidity error LSP7AmountExceedsAuthorizedAmount( address tokenOwner, uint256 authorizedAmount, address operator, uint256 amount ); ``` reverts when `operator` of `tokenOwner` send an `amount` of tokens larger than the `authorizedAmount`. #### Parameters | Name | Type | Description | | ------------------ | :-------: | ----------- | | `tokenOwner` | `address` | - | | `authorizedAmount` | `uint256` | - | | `operator` | `address` | - | | `amount` | `uint256` | - |
### LSP7AmountExceedsBalance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsbalance) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7AmountExceedsBalance(uint256,address,uint256)` - Error hash: `0x08d47949` ::: ```solidity error LSP7AmountExceedsBalance( uint256 balance, address tokenOwner, uint256 amount ); ``` reverts when sending an `amount` of tokens larger than the current `balance` of the `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `balance` | `uint256` | - | | `tokenOwner` | `address` | - | | `amount` | `uint256` | - |
### LSP7BatchCallFailed :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7batchcallfailed) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7BatchCallFailed(uint256)` - Error hash: `0xb774c284` ::: ```solidity error LSP7BatchCallFailed(uint256 callIndex); ``` _Batch call failed._ Reverts when a batch call failed. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------- | | `callIndex` | `uint256` | - |
### LSP7CannotSendWithAddressZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotsendwithaddresszero) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CannotSendWithAddressZero()` - Error hash: `0xd2d5ec30` ::: ```solidity error LSP7CannotSendWithAddressZero(); ``` reverts when trying to: - mint tokens to the zero address. - burn tokens from the zero address. - transfer tokens from or to the zero address.
### LSP7CannotUseAddressZeroAsOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotuseaddresszeroasoperator) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CannotUseAddressZeroAsOperator()` - Error hash: `0x6355e766` ::: ```solidity error LSP7CannotUseAddressZeroAsOperator(); ``` reverts when trying to set the zero address as an operator.
### LSP7DecreaseAllowanceNotAuthorized :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreaseallowancenotauthorized) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7DecreaseAllowanceNotAuthorized(address,address,address)` - Error hash: `0x98ce2945` ::: ```solidity error LSP7DecreaseAllowanceNotAuthorized( address caller, address tokenOwner, address operator ); ``` Reverts when the call to decrease allowance is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `operator` | `address` | - |
### LSP7DecreasedAllowanceBelowZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreasedallowancebelowzero) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7DecreasedAllowanceBelowZero()` - Error hash: `0x0ef76c35` ::: ```solidity error LSP7DecreasedAllowanceBelowZero(); ``` Reverts when trying to decrease an operator's allowance to more than its current allowance.
### LSP7InvalidTransferBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7invalidtransferbatch) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7InvalidTransferBatch()` - Error hash: `0x263eee8d` ::: ```solidity error LSP7InvalidTransferBatch(); ``` reverts when the array parameters used in [`transferBatch`](#transferbatch) have different lengths.
### LSP7NotifyTokenReceiverContractMissingLSP1Interface :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceivercontractmissinglsp1interface) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7NotifyTokenReceiverContractMissingLSP1Interface(address)` - Error hash: `0xa608fbb6` ::: ```solidity error LSP7NotifyTokenReceiverContractMissingLSP1Interface( address tokenReceiver ); ``` reverts if the `tokenReceiver` does not implement LSP1 when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP7NotifyTokenReceiverIsEOA :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceiveriseoa) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7NotifyTokenReceiverIsEOA(address)` - Error hash: `0x26c247f4` ::: ```solidity error LSP7NotifyTokenReceiverIsEOA(address tokenReceiver); ``` reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP7RevokeOperatorNotAuthorized :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7revokeoperatornotauthorized) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7RevokeOperatorNotAuthorized(address,address,address)` - Error hash: `0x1a525b32` ::: ```solidity error LSP7RevokeOperatorNotAuthorized( address caller, address tokenOwner, address operator ); ``` Reverts when the call to revoke operator is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `operator` | `address` | - |
### LSP7TokenContractCannotHoldValue :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7tokencontractcannotholdvalue) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7TokenContractCannotHoldValue()` - Error hash: `0x388f5adc` ::: ```solidity error LSP7TokenContractCannotHoldValue(); ``` _LSP7 contract cannot receive native tokens._ Error occurs when sending native tokens to the LSP7 contract without sending any data. E.g. Sending value without passing a bytes4 function selector to call a LSP17 Extension.
### LSP7TokenOwnerCannotBeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7tokenownercannotbeoperator) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7TokenOwnerCannotBeOperator()` - Error hash: `0xdab75047` ::: ```solidity error LSP7TokenOwnerCannotBeOperator(); ``` reverts when trying to authorize or revoke the token's owner as an operator.
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OperatorAllowanceCannotBeIncreasedFromZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorallowancecannotbeincreasedfromzero) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OperatorAllowanceCannotBeIncreasedFromZero(address)` - Error hash: `0xcba6e977` ::: ```solidity error OperatorAllowanceCannotBeIncreasedFromZero(address operator); ``` Reverts when token owner call [`increaseAllowance`](#increaseallowance) for an operator that does not have any allowance #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownablecallernottheowner) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Compatibility.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Compatibility.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`ILSP4Compatibility.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/ILSP4Compatibility.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`LSP7CompatibleERC20InitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CompatibleERC20InitAbstract.sol [`LSP7CompatibleERC20.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CompatibleERC20.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP7CappedSupply :::info Standard Specifications [`LSP-7-DigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md) ::: :::info Solidity implementation [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: LSP7 token extension to add a max token supply cap. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### fallback :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#fallback) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), revert.
### receive :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#receive) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: ```solidity receive() external payable; ``` _LSP7 contract cannot receive native tokens._ Reverts whenever someone tries to send native tokens to a LSP7 contract.
### authorizeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#authorizeoperator) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `authorizeOperator(address,uint256,bytes)` - Function selector: `0xb49506fd` ::: :::danger To avoid front-running and Allowance Double-Spend Exploit when increasing or decreasing the authorized amount of an operator, it is advised to use the [`increaseAllowance`](#increaseallowance) and [`decreaseAllowance`](#decreaseallowance) functions. For more information, see: https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/ ::: ```solidity function authorizeOperator( address operator, uint256 amount, bytes operatorNotificationData ) external nonpayable; ``` Sets an `amount` of tokens that an `operator` has access from the caller's balance (allowance). See [`authorizedAmountFor`](#authorizedamountfor). Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------ | | `operator` | `address` | The address to authorize as an operator. | | `amount` | `uint256` | The allowance amount of tokens operator has access to. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### authorizedAmountFor :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#authorizedamountfor) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `authorizedAmountFor(address,address)` - Function selector: `0x65aeaa95` ::: ```solidity function authorizedAmountFor( address operator, address tokenOwner ) external view returns (uint256); ``` Get the amount of tokens `operator` address has access to from `tokenOwner`. Operators can send and burn tokens on behalf of their owners. #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------- | | `operator` | `address` | The operator's address to query the authorized amount for. | | `tokenOwner` | `address` | The token owner that `operator` has allowance on. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------------------------------------------- | | `0` | `uint256` | The amount of tokens the `operator`'s address has access on the `tokenOwner`'s balance. |
### balanceOf :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#balanceof) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `balanceOf(address)` - Function selector: `0x70a08231` ::: ```solidity function balanceOf(address tokenOwner) external view returns (uint256); ``` Get the number of tokens owned by `tokenOwner`. If the token is divisible (the [`decimals`](#decimals) function returns `18`), the amount returned should be divided by 1e18 to get a better picture of the actual balance of the `tokenOwner`. _Example:_ `balanceOf(someAddress) -> 42_000_000_000_000_000_000 / 1e18 = 42 tokens` #### Parameters | Name | Type | Description | | ------------ | :-------: | --------------------------------------------------------- | | `tokenOwner` | `address` | The address of the token holder to query the balance for. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------- | | `0` | `uint256` | The amount of tokens owned by `tokenOwner`. |
### batchCalls :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#batchcalls) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### decimals :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#decimals) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `decimals()` - Function selector: `0x313ce567` ::: ```solidity function decimals() external view returns (uint8); ``` Returns the number of decimals used to get its user representation. If the asset contract has been set to be non-divisible via the `isNonDivisible_` parameter in the `constructor`, the decimals returned will be `0`. Otherwise `18` is the common value. #### Returns | Name | Type | Description | | ---- | :-----: | ----------------------------------------------------------------------- | | `0` | `uint8` | the number of decimals. If `0` is returned, the asset is non-divisible. |
### decreaseAllowance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#decreaseallowance) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `decreaseAllowance(address,address,uint256,bytes)` - Function selector: `0x78381670` ::: ```solidity function decreaseAllowance( address operator, address tokenOwner, uint256 subtractedAmount, bytes operatorNotificationData ) external nonpayable; ``` _Decrease the allowance of `operator` by -`subtractedAmount`_ Atomically decreases the allowance granted to `operator` by the caller. This is an alternative approach to [`authorizeOperator`](#authorizeoperator) that can be used as a mitigation for the double spending allowance problem. Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------ | | `operator` | `address` | The operator to decrease allowance for `msg.sender` | | `tokenOwner` | `address` | The address of the token owner. | | `subtractedAmount` | `uint256` | The amount to decrease by in the operator's allowance. | | `operatorNotificationData` | `bytes` | - |
### getData :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getdata) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getdatabatch) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### getOperatorsOf :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getoperatorsof) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getOperatorsOf(address)` - Function selector: `0xd72fc29a` ::: ```solidity function getOperatorsOf(address tokenOwner) external view returns (address[]); ``` Returns all `operator` addresses that are allowed to transfer or burn on behalf of `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `tokenOwner` | `address` | The token owner to get the operators for. | #### Returns | Name | Type | Description | | ---- | :---------: | ----------------------------------------------------------------------------------- | | `0` | `address[]` | An array of operators allowed to transfer or burn tokens on behalf of `tokenOwner`. |
### increaseAllowance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#increaseallowance) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `increaseAllowance(address,uint256,bytes)` - Function selector: `0x2bc1da82` ::: ```solidity function increaseAllowance( address operator, uint256 addedAmount, bytes operatorNotificationData ) external nonpayable; ``` _Increase the allowance of `operator` by +`addedAmount`_ Atomically increases the allowance granted to `operator` by the caller. This is an alternative approach to [`authorizeOperator`](#authorizeoperator) that can be used as a mitigation for the double spending allowance problem. Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------- | | `operator` | `address` | The operator to increase the allowance for `msg.sender` | | `addedAmount` | `uint256` | The additional amount to add on top of the current operator's allowance | | `operatorNotificationData` | `bytes` | - |
### owner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#owner) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#renounceownership) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### revokeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `revokeOperator(address,address,bool,bytes)` - Function selector: `0x30d0dc37` ::: ```solidity function revokeOperator( address operator, address tokenOwner, bool notify, bytes operatorNotificationData ) external nonpayable; ``` Enables `tokenOwner` to remove `operator` for its tokens, disallowing it to send any amount of tokens on its behalf. This function also allows the `operator` to remove itself if it is the caller of this function #### Parameters | Name | Type | Description | | -------------------------- | :-------: | --------------------------------------------------------- | | `operator` | `address` | The address to revoke as an operator. | | `tokenOwner` | `address` | The address of the token owner. | | `notify` | `bool` | Boolean indicating whether to notify the operator or not. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### setData :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#setdata) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#setdatabatch) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#supportsinterface) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas. #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### tokenSupplyCap :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#tokensupplycap) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `tokenSupplyCap()` - Function selector: `0x52058d8a` ::: ```solidity function tokenSupplyCap() external view returns (uint256); ``` _The maximum supply amount of tokens allowed to exist is `_TOKEN_SUPPLY_CAP`._ Get the maximum number of tokens that can exist to circulate. Once [`totalSupply`](#totalsupply) reaches reaches [`totalSuuplyCap`](#totalsuuplycap), it is not possible to mint more tokens. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------------ | | `0` | `uint256` | The maximum number of tokens that can exist in the contract. |
### totalSupply :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#totalsupply) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `totalSupply()` - Function selector: `0x18160ddd` ::: ```solidity function totalSupply() external view returns (uint256); ``` Returns the number of existing tokens that have been minted in this contract. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------ | | `0` | `uint256` | The number of existing tokens. |
### transfer :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transfer) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transfer(address,address,uint256,bool,bytes)` - Function selector: `0x760d9bba` ::: ```solidity function transfer( address from, address to, uint256 amount, bool force, bytes data ) external nonpayable; ``` Transfers an `amount` of tokens from the `from` address to the `to` address and notify both sender and recipients via the LSP1 [`universalReceiver(...)`](#`universalreceiver) function. If the tokens are transferred by an operator on behalf of a token holder, the allowance for the operator will be decreased by `amount` once the token transfer has been completed (See [`authorizedAmountFor`](#authorizedamountfor)). #### Parameters | Name | Type | Description | | -------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The sender address. | | `to` | `address` | The recipient address. | | `amount` | `uint256` | The amount of tokens to transfer. | | `force` | `bool` | When set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. |
### transferBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transferbatch) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transferBatch(address[],address[],uint256[],bool[],bytes[])` - Function selector: `0x2d7667c9` ::: ```solidity function transferBatch( address[] from, address[] to, uint256[] amount, bool[] force, bytes[] data ) external nonpayable; ``` Same as [`transfer(...)`](#`transfer) but transfer multiple tokens based on the arrays of `from`, `to`, `amount`. #### Parameters | Name | Type | Description | | -------- | :---------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address[]` | An array of sending addresses. | | `to` | `address[]` | An array of receiving addresses. | | `amount` | `uint256[]` | An array of amount of tokens to transfer for each `from -> to` transfer. | | `force` | `bool[]` | For each transfer, when set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes[]` | An array of additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. |
### transferOwnership :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transferownership) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data keys `LSP4TokenName` and `LSP4TokenSymbol` cannot be changed via this function once the digital asset contract has been deployed.
### \_updateOperator ```solidity function _updateOperator( address tokenOwner, address operator, uint256 allowance, bool notified, bytes operatorNotificationData ) internal nonpayable; ``` Changes token `amount` the `operator` has access to from `tokenOwner` tokens. If the amount is zero the operator is removed from the list of operators, otherwise he is added to the list of operators. If the amount is zero then the operator is being revoked, otherwise the operator amount is being modified. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------- | | `tokenOwner` | `address` | The address that will give `operator` an allowance for on its balance. | | `operator` | `address` | @param operatorNotificationData The data to send to the universalReceiver function of the operator in case of notifying | | `allowance` | `uint256` | The maximum amount of token that `operator` can spend from the `tokenOwner`'s balance. | | `notified` | `bool` | Boolean indicating whether the operator has been notified about the change of allowance | | `operatorNotificationData` | `bytes` | The data to send to the universalReceiver function of the operator in case of notifying |
### \_mint ```solidity function _mint( address to, uint256 amount, bool force, bytes data ) internal nonpayable; ``` Same as [`_mint`](#_mint) but allows to mint only if the [`totalSupply`](#totalsupply) does not exceed the [`tokenSupplyCap`](#tokensupplycap) after `amount` of tokens have been minted.
### \_burn :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the sender via LSP1**. ::: :::tip Hint In dApps, you can know which address is burning tokens by listening for the `Transfer` event and filter with the zero address as `to`. ::: ```solidity function _burn(address from, uint256 amount, bytes data) internal nonpayable; ``` Burns (= destroys) `amount` of tokens, decrease the `from` balance. This is done by sending them to the zero address. Both the sender and recipient will be notified of the token transfer through the LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as the `to` address
#### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address to burn tokens from its balance. | | `amount` | `uint256` | The amount of tokens to burn. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. |
### \_spendAllowance ```solidity function _spendAllowance( address operator, address tokenOwner, uint256 amountToSpend ) internal nonpayable; ``` Spend `amountToSpend` from the `operator`'s authorized on behalf of the `tokenOwner`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ------------------------------------------------------------------- | | `operator` | `address` | The address of the operator to decrease the allowance of. | | `tokenOwner` | `address` | The address that granted an allowance on its balance to `operator`. | | `amountToSpend` | `uint256` | The amount of tokens to subtract in allowance of `operator`. |
### \_transfer :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the sender/recipient via LSP1**. ::: ```solidity function _transfer( address from, address to, uint256 amount, bool force, bytes data ) internal nonpayable; ``` Transfer tokens from `from` to `to` by decreasing the balance of `from` by `-amount` and increasing the balance of `to` by `+amount`. Both the sender and recipient will be notified of the token transfer through the LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event.
#### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address to decrease the balance. | | `to` | `address` | The address to increase the balance. | | `amount` | `uint256` | The amount of tokens to transfer from `from` to `to`. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. |
### \_beforeTokenTransfer ```solidity function _beforeTokenTransfer( address from, address to, uint256 amount, bytes data ) internal nonpayable; ``` Hook that is called before any token transfer, including minting and burning. Allows to run custom logic before updating balances and notifying sender/recipient by overriding this function. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------ | | `from` | `address` | The sender address | | `to` | `address` | The recipient address | | `amount` | `uint256` | The amount of token to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_afterTokenTransfer ```solidity function _afterTokenTransfer( address from, address to, uint256 amount, bytes data ) internal nonpayable; ``` Hook that is called after any token transfer, including minting and burning. Allows to run custom logic after updating balances, but **before notifying sender/recipient** by overriding this function. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------ | | `from` | `address` | The sender address | | `to` | `address` | The recipient address | | `amount` | `uint256` | The amount of token to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_notifyTokenOperator ```solidity function _notifyTokenOperator( address operator, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the operator `operator` about the `amount` tokens being authorized with. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENOPERATOR` as typeId, if `operator` is a contract that supports the LSP1 interface. If `operator` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `operator` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `operator` address in the `universalReceiver` call. |
### \_notifyTokenSender ```solidity function _notifyTokenSender(address from, bytes lsp1Data) internal nonpayable; ``` Attempt to notify the token sender `from` about the `amount` of tokens being transferred. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. If `from` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. |
### \_notifyTokenReceiver ```solidity function _notifyTokenReceiver( address to, bool force, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the token receiver `to` about the `amount` tokens being received. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. If `to` is is an EOA or a contract that does not support the LSP1 interface, the behaviour will depend on the `force` boolean flag. - if `force` is set to `true`, nothing will happen and no notification will be sent. - if `force` is set to `false, the transaction will revert. #### Parameters | Name | Type | Description | | ---------- | :-------: | --------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `lsp1Data` | `bytes` | The data to be sent to the `to` address in the `universalReceiver(...)` call. |
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0). - we do not check that payable bool as in lsp7 standard we will always forward the value to the extension
### \_fallbackLSP17Extendable :::info The LSP7 Token contract should not hold any native tokens. Any native tokens received by the contract will be forwarded to the extension address mapped to the selector from `msg.sig`. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call with the received value to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the address(0) will be returned. Forwards the value if the extension is payable. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the CALL opcode, passing the [`msg.data`](#msg.data) appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the [`msg.value`](#msg.value)
## Events ### DataChanged :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#datachanged) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OperatorAuthorizationChanged :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorauthorizationchanged) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OperatorAuthorizationChanged(address,address,uint256,bytes)` - Event topic hash: `0xf772a43bfdf4729b196e3fb54a818b91a2ca6c49d10b2e16278752f9f515c25d` ::: ```solidity event OperatorAuthorizationChanged( address indexed operator, address indexed tokenOwner, uint256 indexed amount, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` enables `operator` for `amount` tokens. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address authorized as an operator | | `tokenOwner` **`indexed`** | `address` | The token owner | | `amount` **`indexed`** | `uint256` | The amount of tokens `operator` address has access to from `tokenOwner` | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OperatorRevoked :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorrevoked) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OperatorRevoked(address,address,bool,bytes)` - Event topic hash: `0x0ebf5762d8855cbe012d2ca42fb33a81175e17c8a8751f8859931ba453bd4167` ::: ```solidity event OperatorRevoked( address indexed operator, address indexed tokenOwner, bool indexed notified, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` disables `operator` for `amount` tokens and set its [`authorizedAmountFor(...)`](#`authorizedamountfor) to `0`. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address revoked from operating | | `tokenOwner` **`indexed`** | `address` | The token owner | | `notified` **`indexed`** | `bool` | Bool indicating whether the operator has been notified or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OwnershipTransferred :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownershiptransferred) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### Transfer :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transfer) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `Transfer(address,address,address,uint256,bool,bytes)` - Event topic hash: `0x3997e418d2cef0b3b0e907b1e39605c3f7d32dbd061e82ea5b4a770d46a160a6` ::: ```solidity event Transfer( address indexed operator, address indexed from, address indexed to, uint256 amount, bool force, bytes data ); ``` Emitted when the `from` transferred successfully `amount` of tokens to `to`. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ---------------------------------------------------------------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address of the operator that executed the transfer. | | `from` **`indexed`** | `address` | The address which tokens were sent from (balance decreased by `-amount`). | | `to` **`indexed`** | `address` | The address that received the tokens (balance increased by `+amount`). | | `amount` | `uint256` | The amount of tokens transferred. | | `force` | `bool` | if the transferred enforced the `to` recipient address to be a contract that implements the LSP1 standard or not. | | `data` | `bytes` | Any additional data included by the caller during the transfer, and sent in the LSP1 hooks to the `from` and `to` addresses. |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### InvalidExtensionAddress :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#invalidextensionaddress) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `InvalidExtensionAddress(bytes)` - Error hash: `0x42bfe79f` ::: ```solidity error InvalidExtensionAddress(bytes storedData); ``` reverts when the bytes retrieved from the LSP17 data key is not a valid address (not 20 bytes) #### Parameters | Name | Type | Description | | ------------ | :-----: | ----------- | | `storedData` | `bytes` | - |
### InvalidFunctionSelector :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#invalidfunctionselector) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `InvalidFunctionSelector(bytes)` - Error hash: `0xe5099ee3` ::: ```solidity error InvalidFunctionSelector(bytes data); ``` reverts when the contract is called with a function selector not valid (less than 4 bytes of data) #### Parameters | Name | Type | Description | | ------ | :-----: | ----------- | | `data` | `bytes` | - |
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### LSP7AmountExceedsAuthorizedAmount :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsauthorizedamount) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7AmountExceedsAuthorizedAmount(address,uint256,address,uint256)` - Error hash: `0xf3a6b691` ::: ```solidity error LSP7AmountExceedsAuthorizedAmount( address tokenOwner, uint256 authorizedAmount, address operator, uint256 amount ); ``` reverts when `operator` of `tokenOwner` send an `amount` of tokens larger than the `authorizedAmount`. #### Parameters | Name | Type | Description | | ------------------ | :-------: | ----------- | | `tokenOwner` | `address` | - | | `authorizedAmount` | `uint256` | - | | `operator` | `address` | - | | `amount` | `uint256` | - |
### LSP7AmountExceedsBalance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsbalance) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7AmountExceedsBalance(uint256,address,uint256)` - Error hash: `0x08d47949` ::: ```solidity error LSP7AmountExceedsBalance( uint256 balance, address tokenOwner, uint256 amount ); ``` reverts when sending an `amount` of tokens larger than the current `balance` of the `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `balance` | `uint256` | - | | `tokenOwner` | `address` | - | | `amount` | `uint256` | - |
### LSP7BatchCallFailed :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7batchcallfailed) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7BatchCallFailed(uint256)` - Error hash: `0xb774c284` ::: ```solidity error LSP7BatchCallFailed(uint256 callIndex); ``` _Batch call failed._ Reverts when a batch call failed. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------- | | `callIndex` | `uint256` | - |
### LSP7CannotSendWithAddressZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotsendwithaddresszero) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CannotSendWithAddressZero()` - Error hash: `0xd2d5ec30` ::: ```solidity error LSP7CannotSendWithAddressZero(); ``` reverts when trying to: - mint tokens to the zero address. - burn tokens from the zero address. - transfer tokens from or to the zero address.
### LSP7CannotUseAddressZeroAsOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotuseaddresszeroasoperator) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CannotUseAddressZeroAsOperator()` - Error hash: `0x6355e766` ::: ```solidity error LSP7CannotUseAddressZeroAsOperator(); ``` reverts when trying to set the zero address as an operator.
### LSP7CappedSupplyCannotMintOverCap :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cappedsupplycannotmintovercap) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CappedSupplyCannotMintOverCap()` - Error hash: `0xeacbf0d1` ::: ```solidity error LSP7CappedSupplyCannotMintOverCap(); ``` _Cannot mint anymore as total supply reached the maximum cap._ Reverts when trying to mint tokens but the [`totalSupply`](#totalsupply) has reached the maximum [`tokenSupplyCap`](#tokensupplycap).
### LSP7CappedSupplyRequired :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cappedsupplyrequired) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CappedSupplyRequired()` - Error hash: `0xacf1d8c5` ::: ```solidity error LSP7CappedSupplyRequired(); ``` _The `tokenSupplyCap` must be set and cannot be `0`._ Reverts when setting `0` for the [`tokenSupplyCap`](#tokensupplycap). The max token supply MUST be set to a number greater than 0.
### LSP7DecreaseAllowanceNotAuthorized :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreaseallowancenotauthorized) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7DecreaseAllowanceNotAuthorized(address,address,address)` - Error hash: `0x98ce2945` ::: ```solidity error LSP7DecreaseAllowanceNotAuthorized( address caller, address tokenOwner, address operator ); ``` Reverts when the call to decrease allowance is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `operator` | `address` | - |
### LSP7DecreasedAllowanceBelowZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreasedallowancebelowzero) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7DecreasedAllowanceBelowZero()` - Error hash: `0x0ef76c35` ::: ```solidity error LSP7DecreasedAllowanceBelowZero(); ``` Reverts when trying to decrease an operator's allowance to more than its current allowance.
### LSP7InvalidTransferBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7invalidtransferbatch) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7InvalidTransferBatch()` - Error hash: `0x263eee8d` ::: ```solidity error LSP7InvalidTransferBatch(); ``` reverts when the array parameters used in [`transferBatch`](#transferbatch) have different lengths.
### LSP7NotifyTokenReceiverContractMissingLSP1Interface :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceivercontractmissinglsp1interface) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7NotifyTokenReceiverContractMissingLSP1Interface(address)` - Error hash: `0xa608fbb6` ::: ```solidity error LSP7NotifyTokenReceiverContractMissingLSP1Interface( address tokenReceiver ); ``` reverts if the `tokenReceiver` does not implement LSP1 when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP7NotifyTokenReceiverIsEOA :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceiveriseoa) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7NotifyTokenReceiverIsEOA(address)` - Error hash: `0x26c247f4` ::: ```solidity error LSP7NotifyTokenReceiverIsEOA(address tokenReceiver); ``` reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP7RevokeOperatorNotAuthorized :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7revokeoperatornotauthorized) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7RevokeOperatorNotAuthorized(address,address,address)` - Error hash: `0x1a525b32` ::: ```solidity error LSP7RevokeOperatorNotAuthorized( address caller, address tokenOwner, address operator ); ``` Reverts when the call to revoke operator is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `operator` | `address` | - |
### LSP7TokenContractCannotHoldValue :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7tokencontractcannotholdvalue) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7TokenContractCannotHoldValue()` - Error hash: `0x388f5adc` ::: ```solidity error LSP7TokenContractCannotHoldValue(); ``` _LSP7 contract cannot receive native tokens._ Error occurs when sending native tokens to the LSP7 contract without sending any data. E.g. Sending value without passing a bytes4 function selector to call a LSP17 Extension.
### LSP7TokenOwnerCannotBeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7tokenownercannotbeoperator) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7TokenOwnerCannotBeOperator()` - Error hash: `0xdab75047` ::: ```solidity error LSP7TokenOwnerCannotBeOperator(); ``` reverts when trying to authorize or revoke the token's owner as an operator.
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OperatorAllowanceCannotBeIncreasedFromZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorallowancecannotbeincreasedfromzero) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OperatorAllowanceCannotBeIncreasedFromZero(address)` - Error hash: `0xcba6e977` ::: ```solidity error OperatorAllowanceCannotBeIncreasedFromZero(address operator); ``` Reverts when token owner call [`increaseAllowance`](#increaseallowance) for an operator that does not have any allowance #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownablecallernottheowner) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Compatibility.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Compatibility.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`ILSP4Compatibility.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/ILSP4Compatibility.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`LSP7CompatibleERC20InitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CompatibleERC20InitAbstract.sol [`LSP7CompatibleERC20.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CompatibleERC20.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP7Mintable :::info Standard Specifications [`LSP-7-DigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md) ::: :::info Solidity implementation [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: > LSP7DigitalAsset deployable preset contract with a public [`mint`](#mint) function callable only by the contract [`owner`](#owner). ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#constructor) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: ```solidity constructor( string name_, string symbol_, address newOwner_, uint256 lsp4TokenType_, bool isNonDivisible_ ); ``` _Deploying a `LSP7Mintable` token contract with: token name = `name_`, token symbol = `symbol_`, and address `newOwner_` as the token contract owner._ #### Parameters | Name | Type | Description | | ----------------- | :-------: | ---------------------------------------------------------------------------------------------------- | | `name_` | `string` | The name of the token. | | `symbol_` | `string` | The symbol of the token. | | `newOwner_` | `address` | The owner of the token contract. | | `lsp4TokenType_` | `uint256` | The type of token this digital asset contract represents (`0` = Token, `1` = NFT, `2` = Collection). | | `isNonDivisible_` | `bool` | Specify if the LSP7 token is a fungible or non-fungible token. |
### fallback :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#fallback) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), revert.
### receive :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#receive) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) ::: ```solidity receive() external payable; ``` _LSP7 contract cannot receive native tokens._ Reverts whenever someone tries to send native tokens to a LSP7 contract.
### authorizeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#authorizeoperator) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `authorizeOperator(address,uint256,bytes)` - Function selector: `0xb49506fd` ::: :::danger To avoid front-running and Allowance Double-Spend Exploit when increasing or decreasing the authorized amount of an operator, it is advised to use the [`increaseAllowance`](#increaseallowance) and [`decreaseAllowance`](#decreaseallowance) functions. For more information, see: https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/ ::: ```solidity function authorizeOperator( address operator, uint256 amount, bytes operatorNotificationData ) external nonpayable; ``` Sets an `amount` of tokens that an `operator` has access from the caller's balance (allowance). See [`authorizedAmountFor`](#authorizedamountfor). Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------ | | `operator` | `address` | The address to authorize as an operator. | | `amount` | `uint256` | The allowance amount of tokens operator has access to. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### authorizedAmountFor :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#authorizedamountfor) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `authorizedAmountFor(address,address)` - Function selector: `0x65aeaa95` ::: ```solidity function authorizedAmountFor( address operator, address tokenOwner ) external view returns (uint256); ``` Get the amount of tokens `operator` address has access to from `tokenOwner`. Operators can send and burn tokens on behalf of their owners. #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------- | | `operator` | `address` | The operator's address to query the authorized amount for. | | `tokenOwner` | `address` | The token owner that `operator` has allowance on. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------------------------------------------- | | `0` | `uint256` | The amount of tokens the `operator`'s address has access on the `tokenOwner`'s balance. |
### balanceOf :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#balanceof) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `balanceOf(address)` - Function selector: `0x70a08231` ::: ```solidity function balanceOf(address tokenOwner) external view returns (uint256); ``` Get the number of tokens owned by `tokenOwner`. If the token is divisible (the [`decimals`](#decimals) function returns `18`), the amount returned should be divided by 1e18 to get a better picture of the actual balance of the `tokenOwner`. _Example:_ `balanceOf(someAddress) -> 42_000_000_000_000_000_000 / 1e18 = 42 tokens` #### Parameters | Name | Type | Description | | ------------ | :-------: | --------------------------------------------------------- | | `tokenOwner` | `address` | The address of the token holder to query the balance for. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------- | | `0` | `uint256` | The amount of tokens owned by `tokenOwner`. |
### batchCalls :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#batchcalls) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### decimals :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#decimals) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `decimals()` - Function selector: `0x313ce567` ::: ```solidity function decimals() external view returns (uint8); ``` Returns the number of decimals used to get its user representation. If the asset contract has been set to be non-divisible via the `isNonDivisible_` parameter in the `constructor`, the decimals returned will be `0`. Otherwise `18` is the common value. #### Returns | Name | Type | Description | | ---- | :-----: | ----------------------------------------------------------------------- | | `0` | `uint8` | the number of decimals. If `0` is returned, the asset is non-divisible. |
### decreaseAllowance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#decreaseallowance) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `decreaseAllowance(address,address,uint256,bytes)` - Function selector: `0x78381670` ::: ```solidity function decreaseAllowance( address operator, address tokenOwner, uint256 subtractedAmount, bytes operatorNotificationData ) external nonpayable; ``` _Decrease the allowance of `operator` by -`subtractedAmount`_ Atomically decreases the allowance granted to `operator` by the caller. This is an alternative approach to [`authorizeOperator`](#authorizeoperator) that can be used as a mitigation for the double spending allowance problem. Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------ | | `operator` | `address` | The operator to decrease allowance for `msg.sender` | | `tokenOwner` | `address` | The address of the token owner. | | `subtractedAmount` | `uint256` | The amount to decrease by in the operator's allowance. | | `operatorNotificationData` | `bytes` | - |
### getData :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getdata) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getdatabatch) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### getOperatorsOf :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#getoperatorsof) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `getOperatorsOf(address)` - Function selector: `0xd72fc29a` ::: ```solidity function getOperatorsOf(address tokenOwner) external view returns (address[]); ``` Returns all `operator` addresses that are allowed to transfer or burn on behalf of `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `tokenOwner` | `address` | The token owner to get the operators for. | #### Returns | Name | Type | Description | | ---- | :---------: | ----------------------------------------------------------------------------------- | | `0` | `address[]` | An array of operators allowed to transfer or burn tokens on behalf of `tokenOwner`. |
### increaseAllowance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#increaseallowance) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `increaseAllowance(address,uint256,bytes)` - Function selector: `0x2bc1da82` ::: ```solidity function increaseAllowance( address operator, uint256 addedAmount, bytes operatorNotificationData ) external nonpayable; ``` _Increase the allowance of `operator` by +`addedAmount`_ Atomically increases the allowance granted to `operator` by the caller. This is an alternative approach to [`authorizeOperator`](#authorizeoperator) that can be used as a mitigation for the double spending allowance problem. Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------- | | `operator` | `address` | The operator to increase the allowance for `msg.sender` | | `addedAmount` | `uint256` | The additional amount to add on top of the current operator's allowance | | `operatorNotificationData` | `bytes` | - |
### mint :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#mint) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `mint(address,uint256,bool,bytes)` - Function selector: `0x7580d920` ::: ```solidity function mint( address to, uint256 amount, bool force, bytes data ) external nonpayable; ``` Public [`_mint`](#_mint) function only callable by the [`owner`](#owner). #### Parameters | Name | Type | Description | | -------- | :-------: | ----------- | | `to` | `address` | - | | `amount` | `uint256` | - | | `force` | `bool` | - | | `data` | `bytes` | - |
### owner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#owner) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#renounceownership) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### revokeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `revokeOperator(address,address,bool,bytes)` - Function selector: `0x30d0dc37` ::: ```solidity function revokeOperator( address operator, address tokenOwner, bool notify, bytes operatorNotificationData ) external nonpayable; ``` Enables `tokenOwner` to remove `operator` for its tokens, disallowing it to send any amount of tokens on its behalf. This function also allows the `operator` to remove itself if it is the caller of this function #### Parameters | Name | Type | Description | | -------------------------- | :-------: | --------------------------------------------------------- | | `operator` | `address` | The address to revoke as an operator. | | `tokenOwner` | `address` | The address of the token owner. | | `notify` | `bool` | Boolean indicating whether to notify the operator or not. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### setData :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#setdata) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#setdatabatch) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#supportsinterface) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas. #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### totalSupply :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#totalsupply) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `totalSupply()` - Function selector: `0x18160ddd` ::: ```solidity function totalSupply() external view returns (uint256); ``` Returns the number of existing tokens that have been minted in this contract. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------ | | `0` | `uint256` | The number of existing tokens. |
### transfer :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transfer) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transfer(address,address,uint256,bool,bytes)` - Function selector: `0x760d9bba` ::: ```solidity function transfer( address from, address to, uint256 amount, bool force, bytes data ) external nonpayable; ``` Transfers an `amount` of tokens from the `from` address to the `to` address and notify both sender and recipients via the LSP1 [`universalReceiver(...)`](#`universalreceiver) function. If the tokens are transferred by an operator on behalf of a token holder, the allowance for the operator will be decreased by `amount` once the token transfer has been completed (See [`authorizedAmountFor`](#authorizedamountfor)). #### Parameters | Name | Type | Description | | -------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The sender address. | | `to` | `address` | The recipient address. | | `amount` | `uint256` | The amount of tokens to transfer. | | `force` | `bool` | When set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. |
### transferBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transferbatch) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transferBatch(address[],address[],uint256[],bool[],bytes[])` - Function selector: `0x2d7667c9` ::: ```solidity function transferBatch( address[] from, address[] to, uint256[] amount, bool[] force, bytes[] data ) external nonpayable; ``` Same as [`transfer(...)`](#`transfer) but transfer multiple tokens based on the arrays of `from`, `to`, `amount`. #### Parameters | Name | Type | Description | | -------- | :---------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address[]` | An array of sending addresses. | | `to` | `address[]` | An array of receiving addresses. | | `amount` | `uint256[]` | An array of amount of tokens to transfer for each `from -> to` transfer. | | `force` | `bool[]` | For each transfer, when set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes[]` | An array of additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. |
### transferOwnership :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transferownership) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data keys `LSP4TokenName` and `LSP4TokenSymbol` cannot be changed via this function once the digital asset contract has been deployed.
### \_updateOperator ```solidity function _updateOperator( address tokenOwner, address operator, uint256 allowance, bool notified, bytes operatorNotificationData ) internal nonpayable; ``` Changes token `amount` the `operator` has access to from `tokenOwner` tokens. If the amount is zero the operator is removed from the list of operators, otherwise he is added to the list of operators. If the amount is zero then the operator is being revoked, otherwise the operator amount is being modified. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------- | | `tokenOwner` | `address` | The address that will give `operator` an allowance for on its balance. | | `operator` | `address` | @param operatorNotificationData The data to send to the universalReceiver function of the operator in case of notifying | | `allowance` | `uint256` | The maximum amount of token that `operator` can spend from the `tokenOwner`'s balance. | | `notified` | `bool` | Boolean indicating whether the operator has been notified about the change of allowance | | `operatorNotificationData` | `bytes` | The data to send to the universalReceiver function of the operator in case of notifying |
### \_mint :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the recipient via LSP1**. ::: ```solidity function _mint( address to, uint256 amount, bool force, bytes data ) internal nonpayable; ``` Mints `amount` of tokens and transfers it to `to`.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as `from`.
#### Parameters | Name | Type | Description | | -------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to mint tokens for. | | `amount` | `uint256` | The amount of tokens to mint. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `data` | `bytes` | Additional data the caller wants included in the emitted [`Transfer`](#transfer) event, and sent in the LSP1 hook to the `to` address. |
### \_burn :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the sender via LSP1**. ::: :::tip Hint In dApps, you can know which address is burning tokens by listening for the `Transfer` event and filter with the zero address as `to`. ::: ```solidity function _burn(address from, uint256 amount, bytes data) internal nonpayable; ``` Burns (= destroys) `amount` of tokens, decrease the `from` balance. This is done by sending them to the zero address. Both the sender and recipient will be notified of the token transfer through the LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as the `to` address
#### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address to burn tokens from its balance. | | `amount` | `uint256` | The amount of tokens to burn. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. |
### \_spendAllowance ```solidity function _spendAllowance( address operator, address tokenOwner, uint256 amountToSpend ) internal nonpayable; ``` Spend `amountToSpend` from the `operator`'s authorized on behalf of the `tokenOwner`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ------------------------------------------------------------------- | | `operator` | `address` | The address of the operator to decrease the allowance of. | | `tokenOwner` | `address` | The address that granted an allowance on its balance to `operator`. | | `amountToSpend` | `uint256` | The amount of tokens to subtract in allowance of `operator`. |
### \_transfer :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances, **but before notifying the sender/recipient via LSP1**. ::: ```solidity function _transfer( address from, address to, uint256 amount, bool force, bytes data ) internal nonpayable; ``` Transfer tokens from `from` to `to` by decreasing the balance of `from` by `-amount` and increasing the balance of `to` by `+amount`. Both the sender and recipient will be notified of the token transfer through the LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event.
#### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address to decrease the balance. | | `to` | `address` | The address to increase the balance. | | `amount` | `uint256` | The amount of tokens to transfer from `from` to `to`. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. |
### \_beforeTokenTransfer ```solidity function _beforeTokenTransfer( address from, address to, uint256 amount, bytes data ) internal nonpayable; ``` Hook that is called before any token transfer, including minting and burning. Allows to run custom logic before updating balances and notifying sender/recipient by overriding this function. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------ | | `from` | `address` | The sender address | | `to` | `address` | The recipient address | | `amount` | `uint256` | The amount of token to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_afterTokenTransfer ```solidity function _afterTokenTransfer( address from, address to, uint256 amount, bytes data ) internal nonpayable; ``` Hook that is called after any token transfer, including minting and burning. Allows to run custom logic after updating balances, but **before notifying sender/recipient** by overriding this function. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------ | | `from` | `address` | The sender address | | `to` | `address` | The recipient address | | `amount` | `uint256` | The amount of token to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_notifyTokenOperator ```solidity function _notifyTokenOperator( address operator, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the operator `operator` about the `amount` tokens being authorized with. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENOPERATOR` as typeId, if `operator` is a contract that supports the LSP1 interface. If `operator` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `operator` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `operator` address in the `universalReceiver` call. |
### \_notifyTokenSender ```solidity function _notifyTokenSender(address from, bytes lsp1Data) internal nonpayable; ``` Attempt to notify the token sender `from` about the `amount` of tokens being transferred. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. If `from` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. |
### \_notifyTokenReceiver ```solidity function _notifyTokenReceiver( address to, bool force, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the token receiver `to` about the `amount` tokens being received. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP7_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. If `to` is is an EOA or a contract that does not support the LSP1 interface, the behaviour will depend on the `force` boolean flag. - if `force` is set to `true`, nothing will happen and no notification will be sent. - if `force` is set to `false, the transaction will revert. #### Parameters | Name | Type | Description | | ---------- | :-------: | --------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `lsp1Data` | `bytes` | The data to be sent to the `to` address in the `universalReceiver(...)` call. |
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0). - we do not check that payable bool as in lsp7 standard we will always forward the value to the extension
### \_fallbackLSP17Extendable :::info The LSP7 Token contract should not hold any native tokens. Any native tokens received by the contract will be forwarded to the extension address mapped to the selector from `msg.sig`. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call with the received value to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the address(0) will be returned. Forwards the value if the extension is payable. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the CALL opcode, passing the [`msg.data`](#msg.data) appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the [`msg.value`](#msg.value)
## Events ### DataChanged :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#datachanged) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OperatorAuthorizationChanged :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorauthorizationchanged) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OperatorAuthorizationChanged(address,address,uint256,bytes)` - Event topic hash: `0xf772a43bfdf4729b196e3fb54a818b91a2ca6c49d10b2e16278752f9f515c25d` ::: ```solidity event OperatorAuthorizationChanged( address indexed operator, address indexed tokenOwner, uint256 indexed amount, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` enables `operator` for `amount` tokens. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address authorized as an operator | | `tokenOwner` **`indexed`** | `address` | The token owner | | `amount` **`indexed`** | `uint256` | The amount of tokens `operator` address has access to from `tokenOwner` | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OperatorRevoked :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorrevoked) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OperatorRevoked(address,address,bool,bytes)` - Event topic hash: `0x0ebf5762d8855cbe012d2ca42fb33a81175e17c8a8751f8859931ba453bd4167` ::: ```solidity event OperatorRevoked( address indexed operator, address indexed tokenOwner, bool indexed notified, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` disables `operator` for `amount` tokens and set its [`authorizedAmountFor(...)`](#`authorizedamountfor) to `0`. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address revoked from operating | | `tokenOwner` **`indexed`** | `address` | The token owner | | `notified` **`indexed`** | `bool` | Bool indicating whether the operator has been notified or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OwnershipTransferred :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownershiptransferred) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### Transfer :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#transfer) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Event signature: `Transfer(address,address,address,uint256,bool,bytes)` - Event topic hash: `0x3997e418d2cef0b3b0e907b1e39605c3f7d32dbd061e82ea5b4a770d46a160a6` ::: ```solidity event Transfer( address indexed operator, address indexed from, address indexed to, uint256 amount, bool force, bytes data ); ``` Emitted when the `from` transferred successfully `amount` of tokens to `to`. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ---------------------------------------------------------------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address of the operator that executed the transfer. | | `from` **`indexed`** | `address` | The address which tokens were sent from (balance decreased by `-amount`). | | `to` **`indexed`** | `address` | The address that received the tokens (balance increased by `+amount`). | | `amount` | `uint256` | The amount of tokens transferred. | | `force` | `bool` | if the transferred enforced the `to` recipient address to be a contract that implements the LSP1 standard or not. | | `data` | `bytes` | Any additional data included by the caller during the transfer, and sent in the LSP1 hooks to the `from` and `to` addresses. |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### InvalidExtensionAddress :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#invalidextensionaddress) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `InvalidExtensionAddress(bytes)` - Error hash: `0x42bfe79f` ::: ```solidity error InvalidExtensionAddress(bytes storedData); ``` reverts when the bytes retrieved from the LSP17 data key is not a valid address (not 20 bytes) #### Parameters | Name | Type | Description | | ------------ | :-----: | ----------- | | `storedData` | `bytes` | - |
### InvalidFunctionSelector :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#invalidfunctionselector) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `InvalidFunctionSelector(bytes)` - Error hash: `0xe5099ee3` ::: ```solidity error InvalidFunctionSelector(bytes data); ``` reverts when the contract is called with a function selector not valid (less than 4 bytes of data) #### Parameters | Name | Type | Description | | ------ | :-----: | ----------- | | `data` | `bytes` | - |
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### LSP7AmountExceedsAuthorizedAmount :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsauthorizedamount) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7AmountExceedsAuthorizedAmount(address,uint256,address,uint256)` - Error hash: `0xf3a6b691` ::: ```solidity error LSP7AmountExceedsAuthorizedAmount( address tokenOwner, uint256 authorizedAmount, address operator, uint256 amount ); ``` reverts when `operator` of `tokenOwner` send an `amount` of tokens larger than the `authorizedAmount`. #### Parameters | Name | Type | Description | | ------------------ | :-------: | ----------- | | `tokenOwner` | `address` | - | | `authorizedAmount` | `uint256` | - | | `operator` | `address` | - | | `amount` | `uint256` | - |
### LSP7AmountExceedsBalance :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsbalance) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7AmountExceedsBalance(uint256,address,uint256)` - Error hash: `0x08d47949` ::: ```solidity error LSP7AmountExceedsBalance( uint256 balance, address tokenOwner, uint256 amount ); ``` reverts when sending an `amount` of tokens larger than the current `balance` of the `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `balance` | `uint256` | - | | `tokenOwner` | `address` | - | | `amount` | `uint256` | - |
### LSP7BatchCallFailed :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7batchcallfailed) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7BatchCallFailed(uint256)` - Error hash: `0xb774c284` ::: ```solidity error LSP7BatchCallFailed(uint256 callIndex); ``` _Batch call failed._ Reverts when a batch call failed. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------- | | `callIndex` | `uint256` | - |
### LSP7CannotSendWithAddressZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotsendwithaddresszero) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CannotSendWithAddressZero()` - Error hash: `0xd2d5ec30` ::: ```solidity error LSP7CannotSendWithAddressZero(); ``` reverts when trying to: - mint tokens to the zero address. - burn tokens from the zero address. - transfer tokens from or to the zero address.
### LSP7CannotUseAddressZeroAsOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotuseaddresszeroasoperator) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7CannotUseAddressZeroAsOperator()` - Error hash: `0x6355e766` ::: ```solidity error LSP7CannotUseAddressZeroAsOperator(); ``` reverts when trying to set the zero address as an operator.
### LSP7DecreaseAllowanceNotAuthorized :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreaseallowancenotauthorized) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7DecreaseAllowanceNotAuthorized(address,address,address)` - Error hash: `0x98ce2945` ::: ```solidity error LSP7DecreaseAllowanceNotAuthorized( address caller, address tokenOwner, address operator ); ``` Reverts when the call to decrease allowance is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `operator` | `address` | - |
### LSP7DecreasedAllowanceBelowZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreasedallowancebelowzero) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7DecreasedAllowanceBelowZero()` - Error hash: `0x0ef76c35` ::: ```solidity error LSP7DecreasedAllowanceBelowZero(); ``` Reverts when trying to decrease an operator's allowance to more than its current allowance.
### LSP7InvalidTransferBatch :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7invalidtransferbatch) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7InvalidTransferBatch()` - Error hash: `0x263eee8d` ::: ```solidity error LSP7InvalidTransferBatch(); ``` reverts when the array parameters used in [`transferBatch`](#transferbatch) have different lengths.
### LSP7NotifyTokenReceiverContractMissingLSP1Interface :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceivercontractmissinglsp1interface) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7NotifyTokenReceiverContractMissingLSP1Interface(address)` - Error hash: `0xa608fbb6` ::: ```solidity error LSP7NotifyTokenReceiverContractMissingLSP1Interface( address tokenReceiver ); ``` reverts if the `tokenReceiver` does not implement LSP1 when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP7NotifyTokenReceiverIsEOA :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceiveriseoa) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7NotifyTokenReceiverIsEOA(address)` - Error hash: `0x26c247f4` ::: ```solidity error LSP7NotifyTokenReceiverIsEOA(address tokenReceiver); ``` reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP7RevokeOperatorNotAuthorized :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7revokeoperatornotauthorized) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7RevokeOperatorNotAuthorized(address,address,address)` - Error hash: `0x1a525b32` ::: ```solidity error LSP7RevokeOperatorNotAuthorized( address caller, address tokenOwner, address operator ); ``` Reverts when the call to revoke operator is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `operator` | `address` | - |
### LSP7TokenContractCannotHoldValue :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7tokencontractcannotholdvalue) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7TokenContractCannotHoldValue()` - Error hash: `0x388f5adc` ::: ```solidity error LSP7TokenContractCannotHoldValue(); ``` _LSP7 contract cannot receive native tokens._ Error occurs when sending native tokens to the LSP7 contract without sending any data. E.g. Sending value without passing a bytes4 function selector to call a LSP17 Extension.
### LSP7TokenOwnerCannotBeOperator :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#lsp7tokenownercannotbeoperator) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `LSP7TokenOwnerCannotBeOperator()` - Error hash: `0xdab75047` ::: ```solidity error LSP7TokenOwnerCannotBeOperator(); ``` reverts when trying to authorize or revoke the token's owner as an operator.
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OperatorAllowanceCannotBeIncreasedFromZero :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#operatorallowancecannotbeincreasedfromzero) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OperatorAllowanceCannotBeIncreasedFromZero(address)` - Error hash: `0xcba6e977` ::: ```solidity error OperatorAllowanceCannotBeIncreasedFromZero(address operator); ``` Reverts when token owner call [`increaseAllowance`](#increaseallowance) for an operator that does not have any allowance #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownablecallernottheowner) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Compatibility.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Compatibility.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`ILSP4Compatibility.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/ILSP4Compatibility.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`LSP7CompatibleERC20InitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CompatibleERC20InitAbstract.sol [`LSP7CompatibleERC20.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CompatibleERC20.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP8IdentifiableDigitalAsset :::info Standard Specifications [`LSP-8-IdentifiableDigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md) ::: :::info Solidity implementation [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: > Implementation of a LSP8 Identifiable Digital Asset, a contract that represents a non-fungible token. Standard implementation contract of the LSP8 standard. Minting and transferring are done by providing a unique `tokenId`. This implementation is agnostic to the way tokens are created. A supply mechanism has to be added in a derived contract using [`_mint`](#_mint) For a generic mechanism, see [`LSP7Mintable`](#lsp7mintable). ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### fallback :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#fallback) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), revert.
### receive :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#receive) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity receive() external payable; ``` _LSP8 contract cannot receive native tokens._ Reverts whenever someone tries to send native tokens to a LSP8 contract.
### authorizeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#authorizeoperator) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `authorizeOperator(address,bytes32,bytes)` - Function selector: `0x86a10ddd` ::: ```solidity function authorizeOperator( address operator, bytes32 tokenId, bytes operatorNotificationData ) external nonpayable; ``` Allow an `operator` address to transfer or burn a specific `tokenId` on behalf of its token owner. See [`isOperatorFor`](#isoperatorfor). Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------- | | `operator` | `address` | The address to authorize as an operator. | | `tokenId` | `bytes32` | The token ID operator has access to. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### balanceOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#balanceof) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `balanceOf(address)` - Function selector: `0x70a08231` ::: ```solidity function balanceOf(address tokenOwner) external view returns (uint256); ``` Get the number of token IDs owned by `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------- | | `tokenOwner` | `address` | The address to query \* | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------------------- | | `0` | `uint256` | The total number of token IDs that `tokenOwner` owns. |
### batchCalls :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#batchcalls) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### getData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdata) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatch) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### getDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatchfortokenids) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatchForTokenIds(bytes32[],bytes32[])` - Function selector: `0x1d26fce6` ::: ```solidity function getDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Retrieves data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ---------- | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------------------------------- | | `dataValues` | `bytes[]` | An array of data values for each pair of `tokenId` and `dataKey`. |
### getDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatafortokenid) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataForTokenId(bytes32,bytes32)` - Function selector: `0x16e023b3` ::: ```solidity function getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) external view returns (bytes dataValue); ``` _Retrieves data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------- | | `dataValue` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### getOperatorsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getoperatorsof) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getOperatorsOf(bytes32)` - Function selector: `0x49a6078d` ::: ```solidity function getOperatorsOf(bytes32 tokenId) external view returns (address[]); ``` Returns all `operator` addresses that are allowed to transfer or burn a specific `tokenId` on behalf of its owner. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `tokenId` | `bytes32` | The token ID to get the operators for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------------------------------------------------------------ | | `0` | `address[]` | An array of operators allowed to transfer or burn a specific `tokenId`. Requirements - `tokenId` must exist. |
### isOperatorFor :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#isoperatorfor) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `isOperatorFor(address,bytes32)` - Function selector: `0x2a3654a4` ::: ```solidity function isOperatorFor( address operator, bytes32 tokenId ) external view returns (bool); ``` Returns whether `operator` address is an operator for a given `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------- | | `operator` | `address` | The address to query operator status for. | | `tokenId` | `bytes32` | The token ID to check if `operator` is allowed to operate on. | #### Returns | Name | Type | Description | | ---- | :----: | --------------------------------------------------------------------- | | `0` | `bool` | `true` if `operator` is an operator for `tokenId`, `false` otherwise. |
### owner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#owner) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#renounceownership) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### revokeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `revokeOperator(address,bytes32,bool,bytes)` - Function selector: `0xdb8c9663` ::: ```solidity function revokeOperator( address operator, bytes32 tokenId, bool notify, bytes operatorNotificationData ) external nonpayable; ``` Remove access of `operator` for a given `tokenId`, disallowing it to transfer `tokenId` on behalf of its owner. See also [`isOperatorFor`](#isoperatorfor). #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------- | | `operator` | `address` | The address to revoke as an operator. | | `tokenId` | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notify` | `bool` | Boolean indicating whether to notify the operator or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### setData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdata) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatch) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### setDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatchfortokenids) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` - Function selector: `0xbe9f0e6f` ::: ```solidity function setDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys, bytes[] dataValues ) external nonpayable; ``` _Sets data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ------------ | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | | `dataValues` | `bytes[]` | An array of values to set for the given data keys. |
### setDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatafortokenid) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataForTokenId(bytes32,bytes32,bytes)` - Function selector: `0xd6c1407c` ::: ```solidity function setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) external nonpayable; ``` _Sets data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### supportsInterface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#supportsinterface) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas. #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### tokenIdsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenidsof) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenIdsOf(address)` - Function selector: `0xa3b261f2` ::: ```solidity function tokenIdsOf(address tokenOwner) external view returns (bytes32[]); ``` Returns the list of token IDs that the `tokenOwner` address owns. #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------- | | `tokenOwner` | `address` | The address that we want to get the list of token IDs for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------- | | `0` | `bytes32[]` | An array of `bytes32[] tokenIds` owned by `tokenOwner`. |
### tokenOwnerOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenownerof) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenOwnerOf(bytes32)` - Function selector: `0x217b2270` ::: ```solidity function tokenOwnerOf(bytes32 tokenId) external view returns (address); ``` Returns the address that owns a given `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------ | | `tokenId` | `bytes32` | The token ID to query the owner for. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------- | | `0` | `address` | The owner address of the given `tokenId`. |
### totalSupply :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#totalsupply) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `totalSupply()` - Function selector: `0x18160ddd` ::: ```solidity function totalSupply() external view returns (uint256); ``` Returns the number of existing tokens that have been minted in this contract. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------ | | `0` | `uint256` | The number of existing tokens. |
### transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transfer(address,address,bytes32,bool,bytes)` - Function selector: `0x511b6952` ::: ```solidity function transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) external nonpayable; ``` Transfer a given `tokenId` token from the `from` address to the `to` address. If operators are set for a specific `tokenId`, all the operators are revoked after the tokenId have been transferred. The `force` parameter MUST be set to `true` when transferring tokens to Externally Owned Accounts (EOAs) or contracts that do not implement the LSP1 standard. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address that owns the given `tokenId`. | | `to` | `address` | The address that will receive the `tokenId`. | | `tokenId` | `bytes32` | The token ID to transfer. | | `force` | `bool` | When set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. |
### transferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferbatch) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferBatch(address[],address[],bytes32[],bool[],bytes[])` - Function selector: `0x7e87632c` ::: ```solidity function transferBatch( address[] from, address[] to, bytes32[] tokenId, bool[] force, bytes[] data ) external nonpayable; ``` Transfers multiple tokens at once based on the arrays of `from`, `to` and `tokenId`. If any transfer fails, the whole call will revert. #### Parameters | Name | Type | Description | | --------- | :---------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address[]` | An array of sending addresses. | | `to` | `address[]` | An array of recipient addresses. | | `tokenId` | `bytes32[]` | An array of token IDs to transfer. | | `force` | `bool[]` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard and not revert. | | `data` | `bytes[]` | Any additional data the caller wants included in the emitted event, and sent in the hooks to the `from` and `to` addresses. |
### transferOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferownership) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data key `_LSP8_TOKENID_FORMAT_KEY` cannot be changed once the identifiable digital asset contract has been deployed.
### \_isOperatorOrOwner ```solidity function _isOperatorOrOwner( address caller, bytes32 tokenId ) internal view returns (bool); ``` verifies if the `caller` is operator or owner for the `tokenId` #### Returns | Name | Type | Description | | ---- | :----: | -------------------------------------------- | | `0` | `bool` | true if `caller` is either operator or owner |
### \_revokeOperator ```solidity function _revokeOperator( address operator, address tokenOwner, bytes32 tokenId, bool notified, bytes operatorNotificationData ) internal nonpayable; ``` removes `operator` from the list of operators for the `tokenId`
### \_clearOperators ```solidity function _clearOperators( address tokenOwner, bytes32 tokenId ) internal nonpayable; ``` revoke all the current operators for a specific `tokenId` token which belongs to `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ------------------------------------------------- | | `tokenOwner` | `address` | The address that is the owner of the `tokenId`. | | `tokenId` | `bytes32` | The token to remove the associated operators for. |
### \_exists ```solidity function _exists(bytes32 tokenId) internal view returns (bool); ``` Returns whether `tokenId` exists. Tokens start existing when they are minted ([`_mint`](#_mint)), and stop existing when they are burned ([`_burn`](#_burn)).
### \_existsOrError ```solidity function _existsOrError(bytes32 tokenId) internal view; ``` When `tokenId` does not exist then revert with an error.
### \_mint :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the recipient via LSP1**. ::: ```solidity function _mint( address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Create `tokenId` by minting it and transfers it to `to`.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as `from` address.
#### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------- | | `to` | `address` | @param tokenId The token ID to create (= mint). | | `tokenId` | `bytes32` | The token ID to create (= mint). | | `force` | `bool` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hook of the `to` address. |
### \_burn :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender via LSP1**. ::: :::tip Hint In dApps, you can know which addresses are burning tokens by listening for the `Transfer` event and filter with the zero address as `to`. ::: ```solidity function _burn(bytes32 tokenId, bytes data) internal nonpayable; ``` Burn a specific `tokenId`, removing the `tokenId` from the [`tokenIdsOf`](#tokenidsof) the caller and decreasing its [`balanceOf`](#balanceof) by -1. This will also clear all the operators allowed to transfer the `tokenId`. The owner of the `tokenId` will be notified about the `tokenId` being transferred through its LSP1 [`universalReceiver`](#universalreceiver) function, if it is a contract that supports the LSP1 interface. Its [`universalReceiver`](#universalreceiver) function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as the `to` address.
#### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------------------------------------------------------------------------------------- | | `tokenId` | `bytes32` | The token to burn. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the LSP1 hook on the token owner's address. |
### \_transfer :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender/recipient via LSP1**. ::: :::danger This internal function does not check if the sender is authorized or not to operate on the `tokenId`. ::: ```solidity function _transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Change the owner of the `tokenId` from `from` to `to`. Both the sender and recipient will be notified of the `tokenId` being transferred through their LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event.
#### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The sender address. | | `to` | `address` | @param tokenId The token to transfer. | | `tokenId` | `bytes32` | The token to transfer. | | `force` | `bool` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. |
### \_setDataForTokenId ```solidity function _setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) internal nonpayable; ``` Sets data for a specific `tokenId` and `dataKey` in the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated
**Emitted events:** - [`TokenIdDataChanged`](#tokeniddatachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### \_getDataForTokenId ```solidity function _getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) internal view returns (bytes dataValues); ``` Retrieves data for a specific `tokenId` and `dataKey` from the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ------------ | :-----: | ----------------------------------------------------------------- | | `dataValues` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### \_beforeTokenTransfer ```solidity function _beforeTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` Hook that is called before any token transfer, including minting and burning. Allows to run custom logic before updating balances and notifying sender/recipient by overriding this function. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `from` | `address` | The sender address | | `to` | `address` | @param tokenId The tokenId to transfer | | `tokenId` | `bytes32` | The tokenId to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_afterTokenTransfer ```solidity function _afterTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` Hook that is called after any token transfer, including minting and burning. Allows to run custom logic after updating balances, but **before notifying sender/recipient via LSP1** by overriding this function. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `from` | `address` | The sender address | | `to` | `address` | @param tokenId The tokenId to transfer | | `tokenId` | `bytes32` | The tokenId to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_notifyTokenOperator ```solidity function _notifyTokenOperator( address operator, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the operator `operator` about the `tokenId` being authorized. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENOPERATOR` as typeId, if `operator` is a contract that supports the LSP1 interface. If `operator` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `operator` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `operator` address in the `universalReceiver` call. |
### \_notifyTokenSender ```solidity function _notifyTokenSender(address from, bytes lsp1Data) internal nonpayable; ``` Attempt to notify the token sender `from` about the `tokenId` being transferred. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. If `from` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. |
### \_notifyTokenReceiver ```solidity function _notifyTokenReceiver( address to, bool force, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the token receiver `to` about the `tokenId` being received. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. If `to` is is an EOA or a contract that does not support the LSP1 interface, the behaviour will depend on the `force` boolean flag. - if `force` is set to `true`, nothing will happen and no notification will be sent. - if `force` is set to `false, the transaction will revert. #### Parameters | Name | Type | Description | | ---------- | :-------: | --------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `lsp1Data` | `bytes` | The data to be sent to the `to` address in the `universalReceiver(...)` call. |
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0).
### \_fallbackLSP17Extendable :::info The LSP8 Token contract should not hold any native tokens. Any native tokens received by the contract will be forwarded to the extension address mapped to the selector from `msg.sig`. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call with the received value to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the address(0) will be returned. We will always forward the value to the extension, as the LSP8 contract is not supposed to hold any native tokens. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the CALL opcode, passing the [`msg.data`](#msg.data) appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the [`msg.value`](#msg.value)
## Events ### DataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#datachanged) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OperatorAuthorizationChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorauthorizationchanged) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorAuthorizationChanged(address,address,bytes32,bytes)` - Event topic hash: `0x1b1b58aa2ec0cec2228b2d37124556d41f5a1f7b12f089171f896cc236671215` ::: ```solidity event OperatorAuthorizationChanged( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` enables `operator` to transfer or burn the `tokenId`. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address authorized as an operator. | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` address has access on behalf of `tokenOwner`. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OperatorRevoked :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorrevoked) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorRevoked(address,address,bytes32,bool,bytes)` - Event topic hash: `0xc78cd419d6136f9f1c1c6aec1d3fae098cffaf8bc86314a8f2685e32fe574e3c` ::: ```solidity event OperatorRevoked( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bool notified, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` disables `operator` to transfer or burn `tokenId` on its behalf. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ---------------------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address revoked from the operator array ([`getOperatorsOf`](#getoperatorsof)). | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notified` | `bool` | Bool indicating whether the operator has been notified or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OwnershipTransferred :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownershiptransferred) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### TokenIdDataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokeniddatachanged) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `TokenIdDataChanged(bytes32,bytes32,bytes)` - Event topic hash: `0xa6e4251f855f750545fe414f120db91c76b88def14d120969e5bb2d3f05debbb` ::: ```solidity event TokenIdDataChanged( bytes32 indexed tokenId, bytes32 indexed dataKey, bytes dataValue ); ``` Emitted when setting data for `tokenId`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `tokenId` **`indexed`** | `bytes32` | The tokenId which data is set for. | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `Transfer(address,address,address,bytes32,bool,bytes)` - Event topic hash: `0xb333c813a7426a7a11e2b190cad52c44119421594b47f6f32ace6d8c7207b2bf` ::: ```solidity event Transfer( address operator, address indexed from, address indexed to, bytes32 indexed tokenId, bool force, bytes data ); ``` Emitted when `tokenId` token is transferred from the `from` to the `to` address. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ---------------------------------------------------------------------------------------------------------------------------------- | | `operator` | `address` | The address of operator that sent the `tokenId` | | `from` **`indexed`** | `address` | The previous owner of the `tokenId` | | `to` **`indexed`** | `address` | The new owner of `tokenId` | | `tokenId` **`indexed`** | `bytes32` | The tokenId that was transferred | | `force` | `bool` | If the token transfer enforces the `to` recipient address to be a contract that implements the LSP1 standard or not. | | `data` | `bytes` | Any additional data the caller included by the caller during the transfer, and sent in the hooks to the `from` and `to` addresses. |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### InvalidExtensionAddress :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidextensionaddress) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidExtensionAddress(bytes)` - Error hash: `0x42bfe79f` ::: ```solidity error InvalidExtensionAddress(bytes storedData); ``` reverts when the bytes retrieved from the LSP17 data key is not a valid address (not 20 bytes) #### Parameters | Name | Type | Description | | ------------ | :-----: | ----------- | | `storedData` | `bytes` | - |
### InvalidFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidfunctionselector) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidFunctionSelector(bytes)` - Error hash: `0xe5099ee3` ::: ```solidity error InvalidFunctionSelector(bytes data); ``` reverts when the contract is called with a function selector not valid (less than 4 bytes of data) #### Parameters | Name | Type | Description | | ------ | :-----: | ----------- | | `data` | `bytes` | - |
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### LSP8BatchCallFailed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8batchcallfailed) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8BatchCallFailed(uint256)` - Error hash: `0x234eb819` ::: ```solidity error LSP8BatchCallFailed(uint256 callIndex); ``` _Batch call failed._ Reverts when a batch call failed. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------- | | `callIndex` | `uint256` | - |
### LSP8CannotSendToAddressZero :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoaddresszero) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotSendToAddressZero()` - Error hash: `0x24ecef4d` ::: ```solidity error LSP8CannotSendToAddressZero(); ``` Reverts when trying to send token to the zero address.
### LSP8CannotUseAddressZeroAsOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotuseaddresszeroasoperator) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotUseAddressZeroAsOperator()` - Error hash: `0x9577b8b3` ::: ```solidity error LSP8CannotUseAddressZeroAsOperator(); ``` Reverts when trying to set the zero address as an operator.
### LSP8InvalidTransferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8invalidtransferbatch) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8InvalidTransferBatch()` - Error hash: `0x93a83119` ::: ```solidity error LSP8InvalidTransferBatch(); ``` Reverts when the parameters used for `transferBatch` have different lengths.
### LSP8NonExistentTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistenttokenid) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistentTokenId(bytes32)` - Error hash: `0xae8f9a36` ::: ```solidity error LSP8NonExistentTokenId(bytes32 tokenId); ``` Reverts when `tokenId` has not been minted. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - |
### LSP8NonExistingOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistingoperator) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistingOperator(address,bytes32)` - Error hash: `0x4aa31a8c` ::: ```solidity error LSP8NonExistingOperator(address operator, bytes32 tokenId); ``` Reverts when `operator` is not an operator for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8NotTokenOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenoperator) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOperator(bytes32,address)` - Error hash: `0x1294d2a9` ::: ```solidity error LSP8NotTokenOperator(bytes32 tokenId, address caller); ``` Reverts when `caller` is not an allowed operator for `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotTokenOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenowner) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOwner(address,bytes32,address)` - Error hash: `0x5b271ea2` ::: ```solidity error LSP8NotTokenOwner(address tokenOwner, bytes32 tokenId, address caller); ``` Reverts when `caller` is not the `tokenOwner` of the `tokenId`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotifyTokenReceiverContractMissingLSP1Interface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceivercontractmissinglsp1interface) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverContractMissingLSP1Interface(address)` - Error hash: `0x4349776d` ::: ```solidity error LSP8NotifyTokenReceiverContractMissingLSP1Interface( address tokenReceiver ); ``` Reverts if the `tokenReceiver` does not implement LSP1 when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8NotifyTokenReceiverIsEOA :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceiveriseoa) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverIsEOA(address)` - Error hash: `0x03173137` ::: ```solidity error LSP8NotifyTokenReceiverIsEOA(address tokenReceiver); ``` Reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8OperatorAlreadyAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8operatoralreadyauthorized) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8OperatorAlreadyAuthorized(address,bytes32)` - Error hash: `0xa7626b68` ::: ```solidity error LSP8OperatorAlreadyAuthorized(address operator, bytes32 tokenId); ``` Reverts when `operator` is already authorized for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8RevokeOperatorNotAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8RevokeOperatorNotAuthorized(address,address,bytes32)` - Error hash: `0x760b5acd` ::: ```solidity error LSP8RevokeOperatorNotAuthorized( address caller, address tokenOwner, bytes32 tokenId ); ``` Reverts when the call to revoke operator is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8TokenContractCannotHoldValue :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokencontractcannotholdvalue) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenContractCannotHoldValue()` - Error hash: `0x61f49442` ::: ```solidity error LSP8TokenContractCannotHoldValue(); ``` _LSP8 contract cannot receive native tokens._ Error occurs when sending native tokens to the LSP8 contract without sending any data. E.g. Sending value without passing a bytes4 function selector to call a LSP17 Extension.
### LSP8TokenIdFormatNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformatnoteditable) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdFormatNotEditable()` - Error hash: `0x3664800a` ::: ```solidity error LSP8TokenIdFormatNotEditable(); ``` Reverts when trying to edit the data key `LSP8TokenIdFormat` after the identifiable digital asset contract has been deployed. The `LSP8TokenIdFormat` data key is located inside the ERC725Y Data key-value store of the identifiable digital asset contract. It can be set only once inside the constructor/initializer when the identifiable digital asset contract is being deployed.
### LSP8TokenIdsDataEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdataemptyarray) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataEmptyArray()` - Error hash: `0x80c98305` ::: ```solidity error LSP8TokenIdsDataEmptyArray(); ``` Reverts when empty arrays is passed to the function
### LSP8TokenIdsDataLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdatalengthmismatch) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataLengthMismatch()` - Error hash: `0x2fa71dfe` ::: ```solidity error LSP8TokenIdsDataLengthMismatch(); ``` Reverts when the length of the token IDs data arrays is not equal
### LSP8TokenOwnerCannotBeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownercannotbeoperator) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerCannotBeOperator()` - Error hash: `0x89fdad62` ::: ```solidity error LSP8TokenOwnerCannotBeOperator(); ``` Reverts when trying to authorize or revoke the token's owner as an operator.
### LSP8TokenOwnerChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownerchanged) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerChanged(bytes32,address,address)` - Error hash: `0x5a9c31d3` ::: ```solidity error LSP8TokenOwnerChanged( bytes32 tokenId, address oldOwner, address newOwner ); ``` Reverts when the token owner changed inside the [`_beforeTokenTransfer`](#_beforetokentransfer) hook. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `oldOwner` | `address` | - | | `newOwner` | `address` | - |
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecallernottheowner) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP8Burnable :::info Standard Specifications [`LSP-8-IdentifiableDigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md) ::: :::info Solidity implementation [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: LSP8 token extension that allows token holders to destroy both their own tokens and those that they have an allowance for as an operator. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### fallback :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#fallback) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), revert.
### receive :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#receive) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity receive() external payable; ``` _LSP8 contract cannot receive native tokens._ Reverts whenever someone tries to send native tokens to a LSP8 contract.
### authorizeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#authorizeoperator) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `authorizeOperator(address,bytes32,bytes)` - Function selector: `0x86a10ddd` ::: ```solidity function authorizeOperator( address operator, bytes32 tokenId, bytes operatorNotificationData ) external nonpayable; ``` Allow an `operator` address to transfer or burn a specific `tokenId` on behalf of its token owner. See [`isOperatorFor`](#isoperatorfor). Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------- | | `operator` | `address` | The address to authorize as an operator. | | `tokenId` | `bytes32` | The token ID operator has access to. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### balanceOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#balanceof) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `balanceOf(address)` - Function selector: `0x70a08231` ::: ```solidity function balanceOf(address tokenOwner) external view returns (uint256); ``` Get the number of token IDs owned by `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------- | | `tokenOwner` | `address` | The address to query \* | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------------------- | | `0` | `uint256` | The total number of token IDs that `tokenOwner` owns. |
### batchCalls :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#batchcalls) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### burn :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#burn) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `burn(bytes32,bytes)` - Function selector: `0x6c79b70b` ::: ```solidity function burn(bytes32 tokenId, bytes data) external nonpayable; ``` _Burning tokenId `tokenId`. This tokenId will not be recoverable! (additional data sent: `data`)._ See internal [`_burn`](#_burn) function for details. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------- | | `tokenId` | `bytes32` | The tokenId to burn. | | `data` | `bytes` | Any extra data to be sent alongside burning the tokenId. |
### getData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdata) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatch) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### getDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatchfortokenids) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatchForTokenIds(bytes32[],bytes32[])` - Function selector: `0x1d26fce6` ::: ```solidity function getDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Retrieves data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ---------- | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------------------------------- | | `dataValues` | `bytes[]` | An array of data values for each pair of `tokenId` and `dataKey`. |
### getDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatafortokenid) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataForTokenId(bytes32,bytes32)` - Function selector: `0x16e023b3` ::: ```solidity function getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) external view returns (bytes dataValue); ``` _Retrieves data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------- | | `dataValue` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### getOperatorsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getoperatorsof) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getOperatorsOf(bytes32)` - Function selector: `0x49a6078d` ::: ```solidity function getOperatorsOf(bytes32 tokenId) external view returns (address[]); ``` Returns all `operator` addresses that are allowed to transfer or burn a specific `tokenId` on behalf of its owner. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `tokenId` | `bytes32` | The token ID to get the operators for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------------------------------------------------------------ | | `0` | `address[]` | An array of operators allowed to transfer or burn a specific `tokenId`. Requirements - `tokenId` must exist. |
### isOperatorFor :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#isoperatorfor) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `isOperatorFor(address,bytes32)` - Function selector: `0x2a3654a4` ::: ```solidity function isOperatorFor( address operator, bytes32 tokenId ) external view returns (bool); ``` Returns whether `operator` address is an operator for a given `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------- | | `operator` | `address` | The address to query operator status for. | | `tokenId` | `bytes32` | The token ID to check if `operator` is allowed to operate on. | #### Returns | Name | Type | Description | | ---- | :----: | --------------------------------------------------------------------- | | `0` | `bool` | `true` if `operator` is an operator for `tokenId`, `false` otherwise. |
### owner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#owner) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#renounceownership) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### revokeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `revokeOperator(address,bytes32,bool,bytes)` - Function selector: `0xdb8c9663` ::: ```solidity function revokeOperator( address operator, bytes32 tokenId, bool notify, bytes operatorNotificationData ) external nonpayable; ``` Remove access of `operator` for a given `tokenId`, disallowing it to transfer `tokenId` on behalf of its owner. See also [`isOperatorFor`](#isoperatorfor). #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------- | | `operator` | `address` | The address to revoke as an operator. | | `tokenId` | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notify` | `bool` | Boolean indicating whether to notify the operator or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### setData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdata) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatch) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### setDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatchfortokenids) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` - Function selector: `0xbe9f0e6f` ::: ```solidity function setDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys, bytes[] dataValues ) external nonpayable; ``` _Sets data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ------------ | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | | `dataValues` | `bytes[]` | An array of values to set for the given data keys. |
### setDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatafortokenid) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataForTokenId(bytes32,bytes32,bytes)` - Function selector: `0xd6c1407c` ::: ```solidity function setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) external nonpayable; ``` _Sets data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### supportsInterface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#supportsinterface) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas. #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### tokenIdsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenidsof) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenIdsOf(address)` - Function selector: `0xa3b261f2` ::: ```solidity function tokenIdsOf(address tokenOwner) external view returns (bytes32[]); ``` Returns the list of token IDs that the `tokenOwner` address owns. #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------- | | `tokenOwner` | `address` | The address that we want to get the list of token IDs for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------- | | `0` | `bytes32[]` | An array of `bytes32[] tokenIds` owned by `tokenOwner`. |
### tokenOwnerOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenownerof) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenOwnerOf(bytes32)` - Function selector: `0x217b2270` ::: ```solidity function tokenOwnerOf(bytes32 tokenId) external view returns (address); ``` Returns the address that owns a given `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------ | | `tokenId` | `bytes32` | The token ID to query the owner for. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------- | | `0` | `address` | The owner address of the given `tokenId`. |
### totalSupply :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#totalsupply) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `totalSupply()` - Function selector: `0x18160ddd` ::: ```solidity function totalSupply() external view returns (uint256); ``` Returns the number of existing tokens that have been minted in this contract. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------ | | `0` | `uint256` | The number of existing tokens. |
### transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transfer(address,address,bytes32,bool,bytes)` - Function selector: `0x511b6952` ::: ```solidity function transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) external nonpayable; ``` Transfer a given `tokenId` token from the `from` address to the `to` address. If operators are set for a specific `tokenId`, all the operators are revoked after the tokenId have been transferred. The `force` parameter MUST be set to `true` when transferring tokens to Externally Owned Accounts (EOAs) or contracts that do not implement the LSP1 standard. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address that owns the given `tokenId`. | | `to` | `address` | The address that will receive the `tokenId`. | | `tokenId` | `bytes32` | The token ID to transfer. | | `force` | `bool` | When set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. |
### transferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferbatch) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferBatch(address[],address[],bytes32[],bool[],bytes[])` - Function selector: `0x7e87632c` ::: ```solidity function transferBatch( address[] from, address[] to, bytes32[] tokenId, bool[] force, bytes[] data ) external nonpayable; ``` Transfers multiple tokens at once based on the arrays of `from`, `to` and `tokenId`. If any transfer fails, the whole call will revert. #### Parameters | Name | Type | Description | | --------- | :---------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address[]` | An array of sending addresses. | | `to` | `address[]` | An array of recipient addresses. | | `tokenId` | `bytes32[]` | An array of token IDs to transfer. | | `force` | `bool[]` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard and not revert. | | `data` | `bytes[]` | Any additional data the caller wants included in the emitted event, and sent in the hooks to the `from` and `to` addresses. |
### transferOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferownership) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data key `_LSP8_TOKENID_FORMAT_KEY` cannot be changed once the identifiable digital asset contract has been deployed.
### \_isOperatorOrOwner ```solidity function _isOperatorOrOwner( address caller, bytes32 tokenId ) internal view returns (bool); ``` verifies if the `caller` is operator or owner for the `tokenId` #### Returns | Name | Type | Description | | ---- | :----: | -------------------------------------------- | | `0` | `bool` | true if `caller` is either operator or owner |
### \_revokeOperator ```solidity function _revokeOperator( address operator, address tokenOwner, bytes32 tokenId, bool notified, bytes operatorNotificationData ) internal nonpayable; ``` removes `operator` from the list of operators for the `tokenId`
### \_clearOperators ```solidity function _clearOperators( address tokenOwner, bytes32 tokenId ) internal nonpayable; ``` revoke all the current operators for a specific `tokenId` token which belongs to `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ------------------------------------------------- | | `tokenOwner` | `address` | The address that is the owner of the `tokenId`. | | `tokenId` | `bytes32` | The token to remove the associated operators for. |
### \_exists ```solidity function _exists(bytes32 tokenId) internal view returns (bool); ``` Returns whether `tokenId` exists. Tokens start existing when they are minted ([`_mint`](#_mint)), and stop existing when they are burned ([`_burn`](#_burn)).
### \_existsOrError ```solidity function _existsOrError(bytes32 tokenId) internal view; ``` When `tokenId` does not exist then revert with an error.
### \_mint :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the recipient via LSP1**. ::: ```solidity function _mint( address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Create `tokenId` by minting it and transfers it to `to`.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as `from` address.
#### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------- | | `to` | `address` | @param tokenId The token ID to create (= mint). | | `tokenId` | `bytes32` | The token ID to create (= mint). | | `force` | `bool` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hook of the `to` address. |
### \_burn :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender via LSP1**. ::: :::tip Hint In dApps, you can know which addresses are burning tokens by listening for the `Transfer` event and filter with the zero address as `to`. ::: ```solidity function _burn(bytes32 tokenId, bytes data) internal nonpayable; ``` Burn a specific `tokenId`, removing the `tokenId` from the [`tokenIdsOf`](#tokenidsof) the caller and decreasing its [`balanceOf`](#balanceof) by -1. This will also clear all the operators allowed to transfer the `tokenId`. The owner of the `tokenId` will be notified about the `tokenId` being transferred through its LSP1 [`universalReceiver`](#universalreceiver) function, if it is a contract that supports the LSP1 interface. Its [`universalReceiver`](#universalreceiver) function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as the `to` address.
#### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------------------------------------------------------------------------------------- | | `tokenId` | `bytes32` | The token to burn. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the LSP1 hook on the token owner's address. |
### \_transfer :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender/recipient via LSP1**. ::: :::danger This internal function does not check if the sender is authorized or not to operate on the `tokenId`. ::: ```solidity function _transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Change the owner of the `tokenId` from `from` to `to`. Both the sender and recipient will be notified of the `tokenId` being transferred through their LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event.
#### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The sender address. | | `to` | `address` | @param tokenId The token to transfer. | | `tokenId` | `bytes32` | The token to transfer. | | `force` | `bool` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. |
### \_setDataForTokenId ```solidity function _setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) internal nonpayable; ``` Sets data for a specific `tokenId` and `dataKey` in the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated
**Emitted events:** - [`TokenIdDataChanged`](#tokeniddatachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### \_getDataForTokenId ```solidity function _getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) internal view returns (bytes dataValues); ``` Retrieves data for a specific `tokenId` and `dataKey` from the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ------------ | :-----: | ----------------------------------------------------------------- | | `dataValues` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### \_beforeTokenTransfer ```solidity function _beforeTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` Hook that is called before any token transfer, including minting and burning. Allows to run custom logic before updating balances and notifying sender/recipient by overriding this function. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `from` | `address` | The sender address | | `to` | `address` | @param tokenId The tokenId to transfer | | `tokenId` | `bytes32` | The tokenId to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_afterTokenTransfer ```solidity function _afterTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` Hook that is called after any token transfer, including minting and burning. Allows to run custom logic after updating balances, but **before notifying sender/recipient via LSP1** by overriding this function. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `from` | `address` | The sender address | | `to` | `address` | @param tokenId The tokenId to transfer | | `tokenId` | `bytes32` | The tokenId to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_notifyTokenOperator ```solidity function _notifyTokenOperator( address operator, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the operator `operator` about the `tokenId` being authorized. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENOPERATOR` as typeId, if `operator` is a contract that supports the LSP1 interface. If `operator` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `operator` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `operator` address in the `universalReceiver` call. |
### \_notifyTokenSender ```solidity function _notifyTokenSender(address from, bytes lsp1Data) internal nonpayable; ``` Attempt to notify the token sender `from` about the `tokenId` being transferred. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. If `from` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. |
### \_notifyTokenReceiver ```solidity function _notifyTokenReceiver( address to, bool force, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the token receiver `to` about the `tokenId` being received. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. If `to` is is an EOA or a contract that does not support the LSP1 interface, the behaviour will depend on the `force` boolean flag. - if `force` is set to `true`, nothing will happen and no notification will be sent. - if `force` is set to `false, the transaction will revert. #### Parameters | Name | Type | Description | | ---------- | :-------: | --------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `lsp1Data` | `bytes` | The data to be sent to the `to` address in the `universalReceiver(...)` call. |
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0).
### \_fallbackLSP17Extendable :::info The LSP8 Token contract should not hold any native tokens. Any native tokens received by the contract will be forwarded to the extension address mapped to the selector from `msg.sig`. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call with the received value to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the address(0) will be returned. We will always forward the value to the extension, as the LSP8 contract is not supposed to hold any native tokens. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the CALL opcode, passing the [`msg.data`](#msg.data) appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the [`msg.value`](#msg.value)
## Events ### DataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#datachanged) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OperatorAuthorizationChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorauthorizationchanged) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorAuthorizationChanged(address,address,bytes32,bytes)` - Event topic hash: `0x1b1b58aa2ec0cec2228b2d37124556d41f5a1f7b12f089171f896cc236671215` ::: ```solidity event OperatorAuthorizationChanged( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` enables `operator` to transfer or burn the `tokenId`. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address authorized as an operator. | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` address has access on behalf of `tokenOwner`. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OperatorRevoked :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorrevoked) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorRevoked(address,address,bytes32,bool,bytes)` - Event topic hash: `0xc78cd419d6136f9f1c1c6aec1d3fae098cffaf8bc86314a8f2685e32fe574e3c` ::: ```solidity event OperatorRevoked( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bool notified, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` disables `operator` to transfer or burn `tokenId` on its behalf. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ---------------------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address revoked from the operator array ([`getOperatorsOf`](#getoperatorsof)). | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notified` | `bool` | Bool indicating whether the operator has been notified or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OwnershipTransferred :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownershiptransferred) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### TokenIdDataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokeniddatachanged) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `TokenIdDataChanged(bytes32,bytes32,bytes)` - Event topic hash: `0xa6e4251f855f750545fe414f120db91c76b88def14d120969e5bb2d3f05debbb` ::: ```solidity event TokenIdDataChanged( bytes32 indexed tokenId, bytes32 indexed dataKey, bytes dataValue ); ``` Emitted when setting data for `tokenId`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `tokenId` **`indexed`** | `bytes32` | The tokenId which data is set for. | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `Transfer(address,address,address,bytes32,bool,bytes)` - Event topic hash: `0xb333c813a7426a7a11e2b190cad52c44119421594b47f6f32ace6d8c7207b2bf` ::: ```solidity event Transfer( address operator, address indexed from, address indexed to, bytes32 indexed tokenId, bool force, bytes data ); ``` Emitted when `tokenId` token is transferred from the `from` to the `to` address. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ---------------------------------------------------------------------------------------------------------------------------------- | | `operator` | `address` | The address of operator that sent the `tokenId` | | `from` **`indexed`** | `address` | The previous owner of the `tokenId` | | `to` **`indexed`** | `address` | The new owner of `tokenId` | | `tokenId` **`indexed`** | `bytes32` | The tokenId that was transferred | | `force` | `bool` | If the token transfer enforces the `to` recipient address to be a contract that implements the LSP1 standard or not. | | `data` | `bytes` | Any additional data the caller included by the caller during the transfer, and sent in the hooks to the `from` and `to` addresses. |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### InvalidExtensionAddress :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidextensionaddress) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidExtensionAddress(bytes)` - Error hash: `0x42bfe79f` ::: ```solidity error InvalidExtensionAddress(bytes storedData); ``` reverts when the bytes retrieved from the LSP17 data key is not a valid address (not 20 bytes) #### Parameters | Name | Type | Description | | ------------ | :-----: | ----------- | | `storedData` | `bytes` | - |
### InvalidFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidfunctionselector) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidFunctionSelector(bytes)` - Error hash: `0xe5099ee3` ::: ```solidity error InvalidFunctionSelector(bytes data); ``` reverts when the contract is called with a function selector not valid (less than 4 bytes of data) #### Parameters | Name | Type | Description | | ------ | :-----: | ----------- | | `data` | `bytes` | - |
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### LSP8BatchCallFailed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8batchcallfailed) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8BatchCallFailed(uint256)` - Error hash: `0x234eb819` ::: ```solidity error LSP8BatchCallFailed(uint256 callIndex); ``` _Batch call failed._ Reverts when a batch call failed. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------- | | `callIndex` | `uint256` | - |
### LSP8CannotSendToAddressZero :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoaddresszero) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotSendToAddressZero()` - Error hash: `0x24ecef4d` ::: ```solidity error LSP8CannotSendToAddressZero(); ``` Reverts when trying to send token to the zero address.
### LSP8CannotUseAddressZeroAsOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotuseaddresszeroasoperator) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotUseAddressZeroAsOperator()` - Error hash: `0x9577b8b3` ::: ```solidity error LSP8CannotUseAddressZeroAsOperator(); ``` Reverts when trying to set the zero address as an operator.
### LSP8InvalidTransferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8invalidtransferbatch) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8InvalidTransferBatch()` - Error hash: `0x93a83119` ::: ```solidity error LSP8InvalidTransferBatch(); ``` Reverts when the parameters used for `transferBatch` have different lengths.
### LSP8NonExistentTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistenttokenid) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistentTokenId(bytes32)` - Error hash: `0xae8f9a36` ::: ```solidity error LSP8NonExistentTokenId(bytes32 tokenId); ``` Reverts when `tokenId` has not been minted. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - |
### LSP8NonExistingOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistingoperator) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistingOperator(address,bytes32)` - Error hash: `0x4aa31a8c` ::: ```solidity error LSP8NonExistingOperator(address operator, bytes32 tokenId); ``` Reverts when `operator` is not an operator for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8NotTokenOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenoperator) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOperator(bytes32,address)` - Error hash: `0x1294d2a9` ::: ```solidity error LSP8NotTokenOperator(bytes32 tokenId, address caller); ``` Reverts when `caller` is not an allowed operator for `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotTokenOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenowner) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOwner(address,bytes32,address)` - Error hash: `0x5b271ea2` ::: ```solidity error LSP8NotTokenOwner(address tokenOwner, bytes32 tokenId, address caller); ``` Reverts when `caller` is not the `tokenOwner` of the `tokenId`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotifyTokenReceiverContractMissingLSP1Interface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceivercontractmissinglsp1interface) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverContractMissingLSP1Interface(address)` - Error hash: `0x4349776d` ::: ```solidity error LSP8NotifyTokenReceiverContractMissingLSP1Interface( address tokenReceiver ); ``` Reverts if the `tokenReceiver` does not implement LSP1 when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8NotifyTokenReceiverIsEOA :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceiveriseoa) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverIsEOA(address)` - Error hash: `0x03173137` ::: ```solidity error LSP8NotifyTokenReceiverIsEOA(address tokenReceiver); ``` Reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8OperatorAlreadyAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8operatoralreadyauthorized) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8OperatorAlreadyAuthorized(address,bytes32)` - Error hash: `0xa7626b68` ::: ```solidity error LSP8OperatorAlreadyAuthorized(address operator, bytes32 tokenId); ``` Reverts when `operator` is already authorized for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8RevokeOperatorNotAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8RevokeOperatorNotAuthorized(address,address,bytes32)` - Error hash: `0x760b5acd` ::: ```solidity error LSP8RevokeOperatorNotAuthorized( address caller, address tokenOwner, bytes32 tokenId ); ``` Reverts when the call to revoke operator is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8TokenContractCannotHoldValue :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokencontractcannotholdvalue) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenContractCannotHoldValue()` - Error hash: `0x61f49442` ::: ```solidity error LSP8TokenContractCannotHoldValue(); ``` _LSP8 contract cannot receive native tokens._ Error occurs when sending native tokens to the LSP8 contract without sending any data. E.g. Sending value without passing a bytes4 function selector to call a LSP17 Extension.
### LSP8TokenIdFormatNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformatnoteditable) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdFormatNotEditable()` - Error hash: `0x3664800a` ::: ```solidity error LSP8TokenIdFormatNotEditable(); ``` Reverts when trying to edit the data key `LSP8TokenIdFormat` after the identifiable digital asset contract has been deployed. The `LSP8TokenIdFormat` data key is located inside the ERC725Y Data key-value store of the identifiable digital asset contract. It can be set only once inside the constructor/initializer when the identifiable digital asset contract is being deployed.
### LSP8TokenIdsDataEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdataemptyarray) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataEmptyArray()` - Error hash: `0x80c98305` ::: ```solidity error LSP8TokenIdsDataEmptyArray(); ``` Reverts when empty arrays is passed to the function
### LSP8TokenIdsDataLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdatalengthmismatch) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataLengthMismatch()` - Error hash: `0x2fa71dfe` ::: ```solidity error LSP8TokenIdsDataLengthMismatch(); ``` Reverts when the length of the token IDs data arrays is not equal
### LSP8TokenOwnerCannotBeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownercannotbeoperator) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerCannotBeOperator()` - Error hash: `0x89fdad62` ::: ```solidity error LSP8TokenOwnerCannotBeOperator(); ``` Reverts when trying to authorize or revoke the token's owner as an operator.
### LSP8TokenOwnerChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownerchanged) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerChanged(bytes32,address,address)` - Error hash: `0x5a9c31d3` ::: ```solidity error LSP8TokenOwnerChanged( bytes32 tokenId, address oldOwner, address newOwner ); ``` Reverts when the token owner changed inside the [`_beforeTokenTransfer`](#_beforetokentransfer) hook. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `oldOwner` | `address` | - | | `newOwner` | `address` | - |
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecallernottheowner) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP8CappedSupply :::info Standard Specifications [`LSP-8-IdentifiableDigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md) ::: :::info Solidity implementation [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: LSP8 token extension to add a max token supply cap. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### fallback :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#fallback) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), revert.
### receive :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#receive) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity receive() external payable; ``` _LSP8 contract cannot receive native tokens._ Reverts whenever someone tries to send native tokens to a LSP8 contract.
### authorizeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#authorizeoperator) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `authorizeOperator(address,bytes32,bytes)` - Function selector: `0x86a10ddd` ::: ```solidity function authorizeOperator( address operator, bytes32 tokenId, bytes operatorNotificationData ) external nonpayable; ``` Allow an `operator` address to transfer or burn a specific `tokenId` on behalf of its token owner. See [`isOperatorFor`](#isoperatorfor). Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------- | | `operator` | `address` | The address to authorize as an operator. | | `tokenId` | `bytes32` | The token ID operator has access to. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### balanceOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#balanceof) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `balanceOf(address)` - Function selector: `0x70a08231` ::: ```solidity function balanceOf(address tokenOwner) external view returns (uint256); ``` Get the number of token IDs owned by `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------- | | `tokenOwner` | `address` | The address to query \* | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------------------- | | `0` | `uint256` | The total number of token IDs that `tokenOwner` owns. |
### batchCalls :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#batchcalls) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### getData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdata) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatch) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### getDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatchfortokenids) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatchForTokenIds(bytes32[],bytes32[])` - Function selector: `0x1d26fce6` ::: ```solidity function getDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Retrieves data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ---------- | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------------------------------- | | `dataValues` | `bytes[]` | An array of data values for each pair of `tokenId` and `dataKey`. |
### getDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatafortokenid) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataForTokenId(bytes32,bytes32)` - Function selector: `0x16e023b3` ::: ```solidity function getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) external view returns (bytes dataValue); ``` _Retrieves data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------- | | `dataValue` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### getOperatorsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getoperatorsof) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getOperatorsOf(bytes32)` - Function selector: `0x49a6078d` ::: ```solidity function getOperatorsOf(bytes32 tokenId) external view returns (address[]); ``` Returns all `operator` addresses that are allowed to transfer or burn a specific `tokenId` on behalf of its owner. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `tokenId` | `bytes32` | The token ID to get the operators for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------------------------------------------------------------ | | `0` | `address[]` | An array of operators allowed to transfer or burn a specific `tokenId`. Requirements - `tokenId` must exist. |
### isOperatorFor :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#isoperatorfor) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `isOperatorFor(address,bytes32)` - Function selector: `0x2a3654a4` ::: ```solidity function isOperatorFor( address operator, bytes32 tokenId ) external view returns (bool); ``` Returns whether `operator` address is an operator for a given `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------- | | `operator` | `address` | The address to query operator status for. | | `tokenId` | `bytes32` | The token ID to check if `operator` is allowed to operate on. | #### Returns | Name | Type | Description | | ---- | :----: | --------------------------------------------------------------------- | | `0` | `bool` | `true` if `operator` is an operator for `tokenId`, `false` otherwise. |
### owner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#owner) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#renounceownership) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### revokeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `revokeOperator(address,bytes32,bool,bytes)` - Function selector: `0xdb8c9663` ::: ```solidity function revokeOperator( address operator, bytes32 tokenId, bool notify, bytes operatorNotificationData ) external nonpayable; ``` Remove access of `operator` for a given `tokenId`, disallowing it to transfer `tokenId` on behalf of its owner. See also [`isOperatorFor`](#isoperatorfor). #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------- | | `operator` | `address` | The address to revoke as an operator. | | `tokenId` | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notify` | `bool` | Boolean indicating whether to notify the operator or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### setData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdata) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatch) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### setDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatchfortokenids) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` - Function selector: `0xbe9f0e6f` ::: ```solidity function setDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys, bytes[] dataValues ) external nonpayable; ``` _Sets data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ------------ | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | | `dataValues` | `bytes[]` | An array of values to set for the given data keys. |
### setDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatafortokenid) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataForTokenId(bytes32,bytes32,bytes)` - Function selector: `0xd6c1407c` ::: ```solidity function setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) external nonpayable; ``` _Sets data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### supportsInterface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#supportsinterface) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas. #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### tokenIdsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenidsof) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenIdsOf(address)` - Function selector: `0xa3b261f2` ::: ```solidity function tokenIdsOf(address tokenOwner) external view returns (bytes32[]); ``` Returns the list of token IDs that the `tokenOwner` address owns. #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------- | | `tokenOwner` | `address` | The address that we want to get the list of token IDs for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------- | | `0` | `bytes32[]` | An array of `bytes32[] tokenIds` owned by `tokenOwner`. |
### tokenOwnerOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenownerof) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenOwnerOf(bytes32)` - Function selector: `0x217b2270` ::: ```solidity function tokenOwnerOf(bytes32 tokenId) external view returns (address); ``` Returns the address that owns a given `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------ | | `tokenId` | `bytes32` | The token ID to query the owner for. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------- | | `0` | `address` | The owner address of the given `tokenId`. |
### tokenSupplyCap :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokensupplycap) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenSupplyCap()` - Function selector: `0x52058d8a` ::: ```solidity function tokenSupplyCap() external view returns (uint256); ``` _The maximum supply amount of tokens allowed to exist is `_TOKEN_SUPPLY_CAP`._ Get the maximum number of tokens that can exist to circulate. Once [`totalSupply`](#totalsupply) reaches reaches [`totalSuuplyCap`](#totalsuuplycap), it is not possible to mint more tokens. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------------ | | `0` | `uint256` | The maximum number of tokens that can exist in the contract. |
### totalSupply :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#totalsupply) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `totalSupply()` - Function selector: `0x18160ddd` ::: ```solidity function totalSupply() external view returns (uint256); ``` Returns the number of existing tokens that have been minted in this contract. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------ | | `0` | `uint256` | The number of existing tokens. |
### transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transfer(address,address,bytes32,bool,bytes)` - Function selector: `0x511b6952` ::: ```solidity function transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) external nonpayable; ``` Transfer a given `tokenId` token from the `from` address to the `to` address. If operators are set for a specific `tokenId`, all the operators are revoked after the tokenId have been transferred. The `force` parameter MUST be set to `true` when transferring tokens to Externally Owned Accounts (EOAs) or contracts that do not implement the LSP1 standard. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address that owns the given `tokenId`. | | `to` | `address` | The address that will receive the `tokenId`. | | `tokenId` | `bytes32` | The token ID to transfer. | | `force` | `bool` | When set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. |
### transferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferbatch) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferBatch(address[],address[],bytes32[],bool[],bytes[])` - Function selector: `0x7e87632c` ::: ```solidity function transferBatch( address[] from, address[] to, bytes32[] tokenId, bool[] force, bytes[] data ) external nonpayable; ``` Transfers multiple tokens at once based on the arrays of `from`, `to` and `tokenId`. If any transfer fails, the whole call will revert. #### Parameters | Name | Type | Description | | --------- | :---------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address[]` | An array of sending addresses. | | `to` | `address[]` | An array of recipient addresses. | | `tokenId` | `bytes32[]` | An array of token IDs to transfer. | | `force` | `bool[]` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard and not revert. | | `data` | `bytes[]` | Any additional data the caller wants included in the emitted event, and sent in the hooks to the `from` and `to` addresses. |
### transferOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferownership) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data key `_LSP8_TOKENID_FORMAT_KEY` cannot be changed once the identifiable digital asset contract has been deployed.
### \_isOperatorOrOwner ```solidity function _isOperatorOrOwner( address caller, bytes32 tokenId ) internal view returns (bool); ``` verifies if the `caller` is operator or owner for the `tokenId` #### Returns | Name | Type | Description | | ---- | :----: | -------------------------------------------- | | `0` | `bool` | true if `caller` is either operator or owner |
### \_revokeOperator ```solidity function _revokeOperator( address operator, address tokenOwner, bytes32 tokenId, bool notified, bytes operatorNotificationData ) internal nonpayable; ``` removes `operator` from the list of operators for the `tokenId`
### \_clearOperators ```solidity function _clearOperators( address tokenOwner, bytes32 tokenId ) internal nonpayable; ``` revoke all the current operators for a specific `tokenId` token which belongs to `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ------------------------------------------------- | | `tokenOwner` | `address` | The address that is the owner of the `tokenId`. | | `tokenId` | `bytes32` | The token to remove the associated operators for. |
### \_exists ```solidity function _exists(bytes32 tokenId) internal view returns (bool); ``` Returns whether `tokenId` exists. Tokens start existing when they are minted ([`_mint`](#_mint)), and stop existing when they are burned ([`_burn`](#_burn)).
### \_existsOrError ```solidity function _existsOrError(bytes32 tokenId) internal view; ``` When `tokenId` does not exist then revert with an error.
### \_mint ```solidity function _mint( address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Same as [`_mint`](#_mint) but allows to mint only if newly minted `tokenId` does not increase the [`totalSupply`](#totalsupply) over the [`tokenSupplyCap`](#tokensupplycap). after a new `tokenId` has of tokens have been minted.
### \_burn :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender via LSP1**. ::: :::tip Hint In dApps, you can know which addresses are burning tokens by listening for the `Transfer` event and filter with the zero address as `to`. ::: ```solidity function _burn(bytes32 tokenId, bytes data) internal nonpayable; ``` Burn a specific `tokenId`, removing the `tokenId` from the [`tokenIdsOf`](#tokenidsof) the caller and decreasing its [`balanceOf`](#balanceof) by -1. This will also clear all the operators allowed to transfer the `tokenId`. The owner of the `tokenId` will be notified about the `tokenId` being transferred through its LSP1 [`universalReceiver`](#universalreceiver) function, if it is a contract that supports the LSP1 interface. Its [`universalReceiver`](#universalreceiver) function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as the `to` address.
#### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------------------------------------------------------------------------------------- | | `tokenId` | `bytes32` | The token to burn. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the LSP1 hook on the token owner's address. |
### \_transfer :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender/recipient via LSP1**. ::: :::danger This internal function does not check if the sender is authorized or not to operate on the `tokenId`. ::: ```solidity function _transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Change the owner of the `tokenId` from `from` to `to`. Both the sender and recipient will be notified of the `tokenId` being transferred through their LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event.
#### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The sender address. | | `to` | `address` | @param tokenId The token to transfer. | | `tokenId` | `bytes32` | The token to transfer. | | `force` | `bool` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. |
### \_setDataForTokenId ```solidity function _setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) internal nonpayable; ``` Sets data for a specific `tokenId` and `dataKey` in the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated
**Emitted events:** - [`TokenIdDataChanged`](#tokeniddatachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### \_getDataForTokenId ```solidity function _getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) internal view returns (bytes dataValues); ``` Retrieves data for a specific `tokenId` and `dataKey` from the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ------------ | :-----: | ----------------------------------------------------------------- | | `dataValues` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### \_beforeTokenTransfer ```solidity function _beforeTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` Hook that is called before any token transfer, including minting and burning. Allows to run custom logic before updating balances and notifying sender/recipient by overriding this function. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `from` | `address` | The sender address | | `to` | `address` | @param tokenId The tokenId to transfer | | `tokenId` | `bytes32` | The tokenId to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_afterTokenTransfer ```solidity function _afterTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` Hook that is called after any token transfer, including minting and burning. Allows to run custom logic after updating balances, but **before notifying sender/recipient via LSP1** by overriding this function. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `from` | `address` | The sender address | | `to` | `address` | @param tokenId The tokenId to transfer | | `tokenId` | `bytes32` | The tokenId to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_notifyTokenOperator ```solidity function _notifyTokenOperator( address operator, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the operator `operator` about the `tokenId` being authorized. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENOPERATOR` as typeId, if `operator` is a contract that supports the LSP1 interface. If `operator` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `operator` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `operator` address in the `universalReceiver` call. |
### \_notifyTokenSender ```solidity function _notifyTokenSender(address from, bytes lsp1Data) internal nonpayable; ``` Attempt to notify the token sender `from` about the `tokenId` being transferred. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. If `from` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. |
### \_notifyTokenReceiver ```solidity function _notifyTokenReceiver( address to, bool force, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the token receiver `to` about the `tokenId` being received. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. If `to` is is an EOA or a contract that does not support the LSP1 interface, the behaviour will depend on the `force` boolean flag. - if `force` is set to `true`, nothing will happen and no notification will be sent. - if `force` is set to `false, the transaction will revert. #### Parameters | Name | Type | Description | | ---------- | :-------: | --------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `lsp1Data` | `bytes` | The data to be sent to the `to` address in the `universalReceiver(...)` call. |
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0).
### \_fallbackLSP17Extendable :::info The LSP8 Token contract should not hold any native tokens. Any native tokens received by the contract will be forwarded to the extension address mapped to the selector from `msg.sig`. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call with the received value to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the address(0) will be returned. We will always forward the value to the extension, as the LSP8 contract is not supposed to hold any native tokens. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the CALL opcode, passing the [`msg.data`](#msg.data) appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the [`msg.value`](#msg.value)
## Events ### DataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#datachanged) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OperatorAuthorizationChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorauthorizationchanged) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorAuthorizationChanged(address,address,bytes32,bytes)` - Event topic hash: `0x1b1b58aa2ec0cec2228b2d37124556d41f5a1f7b12f089171f896cc236671215` ::: ```solidity event OperatorAuthorizationChanged( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` enables `operator` to transfer or burn the `tokenId`. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address authorized as an operator. | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` address has access on behalf of `tokenOwner`. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OperatorRevoked :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorrevoked) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorRevoked(address,address,bytes32,bool,bytes)` - Event topic hash: `0xc78cd419d6136f9f1c1c6aec1d3fae098cffaf8bc86314a8f2685e32fe574e3c` ::: ```solidity event OperatorRevoked( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bool notified, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` disables `operator` to transfer or burn `tokenId` on its behalf. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ---------------------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address revoked from the operator array ([`getOperatorsOf`](#getoperatorsof)). | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notified` | `bool` | Bool indicating whether the operator has been notified or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OwnershipTransferred :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownershiptransferred) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### TokenIdDataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokeniddatachanged) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `TokenIdDataChanged(bytes32,bytes32,bytes)` - Event topic hash: `0xa6e4251f855f750545fe414f120db91c76b88def14d120969e5bb2d3f05debbb` ::: ```solidity event TokenIdDataChanged( bytes32 indexed tokenId, bytes32 indexed dataKey, bytes dataValue ); ``` Emitted when setting data for `tokenId`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `tokenId` **`indexed`** | `bytes32` | The tokenId which data is set for. | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `Transfer(address,address,address,bytes32,bool,bytes)` - Event topic hash: `0xb333c813a7426a7a11e2b190cad52c44119421594b47f6f32ace6d8c7207b2bf` ::: ```solidity event Transfer( address operator, address indexed from, address indexed to, bytes32 indexed tokenId, bool force, bytes data ); ``` Emitted when `tokenId` token is transferred from the `from` to the `to` address. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ---------------------------------------------------------------------------------------------------------------------------------- | | `operator` | `address` | The address of operator that sent the `tokenId` | | `from` **`indexed`** | `address` | The previous owner of the `tokenId` | | `to` **`indexed`** | `address` | The new owner of `tokenId` | | `tokenId` **`indexed`** | `bytes32` | The tokenId that was transferred | | `force` | `bool` | If the token transfer enforces the `to` recipient address to be a contract that implements the LSP1 standard or not. | | `data` | `bytes` | Any additional data the caller included by the caller during the transfer, and sent in the hooks to the `from` and `to` addresses. |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### InvalidExtensionAddress :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidextensionaddress) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidExtensionAddress(bytes)` - Error hash: `0x42bfe79f` ::: ```solidity error InvalidExtensionAddress(bytes storedData); ``` reverts when the bytes retrieved from the LSP17 data key is not a valid address (not 20 bytes) #### Parameters | Name | Type | Description | | ------------ | :-----: | ----------- | | `storedData` | `bytes` | - |
### InvalidFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidfunctionselector) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidFunctionSelector(bytes)` - Error hash: `0xe5099ee3` ::: ```solidity error InvalidFunctionSelector(bytes data); ``` reverts when the contract is called with a function selector not valid (less than 4 bytes of data) #### Parameters | Name | Type | Description | | ------ | :-----: | ----------- | | `data` | `bytes` | - |
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### LSP8BatchCallFailed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8batchcallfailed) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8BatchCallFailed(uint256)` - Error hash: `0x234eb819` ::: ```solidity error LSP8BatchCallFailed(uint256 callIndex); ``` _Batch call failed._ Reverts when a batch call failed. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------- | | `callIndex` | `uint256` | - |
### LSP8CannotSendToAddressZero :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoaddresszero) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotSendToAddressZero()` - Error hash: `0x24ecef4d` ::: ```solidity error LSP8CannotSendToAddressZero(); ``` Reverts when trying to send token to the zero address.
### LSP8CannotUseAddressZeroAsOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotuseaddresszeroasoperator) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotUseAddressZeroAsOperator()` - Error hash: `0x9577b8b3` ::: ```solidity error LSP8CannotUseAddressZeroAsOperator(); ``` Reverts when trying to set the zero address as an operator.
### LSP8CappedSupplyCannotMintOverCap :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cappedsupplycannotmintovercap) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CappedSupplyCannotMintOverCap()` - Error hash: `0xe8ba2291` ::: ```solidity error LSP8CappedSupplyCannotMintOverCap(); ``` _Cannot mint anymore as total supply reached the maximum cap._ Reverts when trying to mint tokens but the [`totalSupply`](#totalsupply) has reached the maximum [`tokenSupplyCap`](#tokensupplycap).
### LSP8CappedSupplyRequired :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cappedsupplyrequired) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CappedSupplyRequired()` - Error hash: `0x38d9fc30` ::: ```solidity error LSP8CappedSupplyRequired(); ``` _The `tokenSupplyCap` must be set and cannot be `0`._ Reverts when setting `0` for the [`tokenSupplyCap`](#tokensupplycap). The max token supply MUST be set to a number greater than 0.
### LSP8InvalidTransferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8invalidtransferbatch) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8InvalidTransferBatch()` - Error hash: `0x93a83119` ::: ```solidity error LSP8InvalidTransferBatch(); ``` Reverts when the parameters used for `transferBatch` have different lengths.
### LSP8NonExistentTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistenttokenid) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistentTokenId(bytes32)` - Error hash: `0xae8f9a36` ::: ```solidity error LSP8NonExistentTokenId(bytes32 tokenId); ``` Reverts when `tokenId` has not been minted. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - |
### LSP8NonExistingOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistingoperator) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistingOperator(address,bytes32)` - Error hash: `0x4aa31a8c` ::: ```solidity error LSP8NonExistingOperator(address operator, bytes32 tokenId); ``` Reverts when `operator` is not an operator for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8NotTokenOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenoperator) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOperator(bytes32,address)` - Error hash: `0x1294d2a9` ::: ```solidity error LSP8NotTokenOperator(bytes32 tokenId, address caller); ``` Reverts when `caller` is not an allowed operator for `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotTokenOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenowner) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOwner(address,bytes32,address)` - Error hash: `0x5b271ea2` ::: ```solidity error LSP8NotTokenOwner(address tokenOwner, bytes32 tokenId, address caller); ``` Reverts when `caller` is not the `tokenOwner` of the `tokenId`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotifyTokenReceiverContractMissingLSP1Interface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceivercontractmissinglsp1interface) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverContractMissingLSP1Interface(address)` - Error hash: `0x4349776d` ::: ```solidity error LSP8NotifyTokenReceiverContractMissingLSP1Interface( address tokenReceiver ); ``` Reverts if the `tokenReceiver` does not implement LSP1 when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8NotifyTokenReceiverIsEOA :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceiveriseoa) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverIsEOA(address)` - Error hash: `0x03173137` ::: ```solidity error LSP8NotifyTokenReceiverIsEOA(address tokenReceiver); ``` Reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8OperatorAlreadyAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8operatoralreadyauthorized) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8OperatorAlreadyAuthorized(address,bytes32)` - Error hash: `0xa7626b68` ::: ```solidity error LSP8OperatorAlreadyAuthorized(address operator, bytes32 tokenId); ``` Reverts when `operator` is already authorized for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8RevokeOperatorNotAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8RevokeOperatorNotAuthorized(address,address,bytes32)` - Error hash: `0x760b5acd` ::: ```solidity error LSP8RevokeOperatorNotAuthorized( address caller, address tokenOwner, bytes32 tokenId ); ``` Reverts when the call to revoke operator is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8TokenContractCannotHoldValue :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokencontractcannotholdvalue) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenContractCannotHoldValue()` - Error hash: `0x61f49442` ::: ```solidity error LSP8TokenContractCannotHoldValue(); ``` _LSP8 contract cannot receive native tokens._ Error occurs when sending native tokens to the LSP8 contract without sending any data. E.g. Sending value without passing a bytes4 function selector to call a LSP17 Extension.
### LSP8TokenIdFormatNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformatnoteditable) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdFormatNotEditable()` - Error hash: `0x3664800a` ::: ```solidity error LSP8TokenIdFormatNotEditable(); ``` Reverts when trying to edit the data key `LSP8TokenIdFormat` after the identifiable digital asset contract has been deployed. The `LSP8TokenIdFormat` data key is located inside the ERC725Y Data key-value store of the identifiable digital asset contract. It can be set only once inside the constructor/initializer when the identifiable digital asset contract is being deployed.
### LSP8TokenIdsDataEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdataemptyarray) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataEmptyArray()` - Error hash: `0x80c98305` ::: ```solidity error LSP8TokenIdsDataEmptyArray(); ``` Reverts when empty arrays is passed to the function
### LSP8TokenIdsDataLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdatalengthmismatch) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataLengthMismatch()` - Error hash: `0x2fa71dfe` ::: ```solidity error LSP8TokenIdsDataLengthMismatch(); ``` Reverts when the length of the token IDs data arrays is not equal
### LSP8TokenOwnerCannotBeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownercannotbeoperator) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerCannotBeOperator()` - Error hash: `0x89fdad62` ::: ```solidity error LSP8TokenOwnerCannotBeOperator(); ``` Reverts when trying to authorize or revoke the token's owner as an operator.
### LSP8TokenOwnerChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownerchanged) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerChanged(bytes32,address,address)` - Error hash: `0x5a9c31d3` ::: ```solidity error LSP8TokenOwnerChanged( bytes32 tokenId, address oldOwner, address newOwner ); ``` Reverts when the token owner changed inside the [`_beforeTokenTransfer`](#_beforetokentransfer) hook. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `oldOwner` | `address` | - | | `newOwner` | `address` | - |
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecallernottheowner) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP8Enumerable :::info Standard Specifications [`LSP-8-IdentifiableDigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md) ::: :::info Solidity implementation [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: LSP8 extension that enables to enumerate over all the `tokenIds` ever minted. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### fallback :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#fallback) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), revert.
### receive :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#receive) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity receive() external payable; ``` _LSP8 contract cannot receive native tokens._ Reverts whenever someone tries to send native tokens to a LSP8 contract.
### authorizeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#authorizeoperator) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `authorizeOperator(address,bytes32,bytes)` - Function selector: `0x86a10ddd` ::: ```solidity function authorizeOperator( address operator, bytes32 tokenId, bytes operatorNotificationData ) external nonpayable; ``` Allow an `operator` address to transfer or burn a specific `tokenId` on behalf of its token owner. See [`isOperatorFor`](#isoperatorfor). Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------- | | `operator` | `address` | The address to authorize as an operator. | | `tokenId` | `bytes32` | The token ID operator has access to. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### balanceOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#balanceof) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `balanceOf(address)` - Function selector: `0x70a08231` ::: ```solidity function balanceOf(address tokenOwner) external view returns (uint256); ``` Get the number of token IDs owned by `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------- | | `tokenOwner` | `address` | The address to query \* | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------------------- | | `0` | `uint256` | The total number of token IDs that `tokenOwner` owns. |
### batchCalls :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#batchcalls) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### getData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdata) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatch) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### getDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatchfortokenids) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatchForTokenIds(bytes32[],bytes32[])` - Function selector: `0x1d26fce6` ::: ```solidity function getDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Retrieves data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ---------- | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------------------------------- | | `dataValues` | `bytes[]` | An array of data values for each pair of `tokenId` and `dataKey`. |
### getDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatafortokenid) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataForTokenId(bytes32,bytes32)` - Function selector: `0x16e023b3` ::: ```solidity function getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) external view returns (bytes dataValue); ``` _Retrieves data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------- | | `dataValue` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### getOperatorsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getoperatorsof) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getOperatorsOf(bytes32)` - Function selector: `0x49a6078d` ::: ```solidity function getOperatorsOf(bytes32 tokenId) external view returns (address[]); ``` Returns all `operator` addresses that are allowed to transfer or burn a specific `tokenId` on behalf of its owner. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `tokenId` | `bytes32` | The token ID to get the operators for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------------------------------------------------------------ | | `0` | `address[]` | An array of operators allowed to transfer or burn a specific `tokenId`. Requirements - `tokenId` must exist. |
### isOperatorFor :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#isoperatorfor) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `isOperatorFor(address,bytes32)` - Function selector: `0x2a3654a4` ::: ```solidity function isOperatorFor( address operator, bytes32 tokenId ) external view returns (bool); ``` Returns whether `operator` address is an operator for a given `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------- | | `operator` | `address` | The address to query operator status for. | | `tokenId` | `bytes32` | The token ID to check if `operator` is allowed to operate on. | #### Returns | Name | Type | Description | | ---- | :----: | --------------------------------------------------------------------- | | `0` | `bool` | `true` if `operator` is an operator for `tokenId`, `false` otherwise. |
### owner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#owner) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#renounceownership) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### revokeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `revokeOperator(address,bytes32,bool,bytes)` - Function selector: `0xdb8c9663` ::: ```solidity function revokeOperator( address operator, bytes32 tokenId, bool notify, bytes operatorNotificationData ) external nonpayable; ``` Remove access of `operator` for a given `tokenId`, disallowing it to transfer `tokenId` on behalf of its owner. See also [`isOperatorFor`](#isoperatorfor). #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------- | | `operator` | `address` | The address to revoke as an operator. | | `tokenId` | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notify` | `bool` | Boolean indicating whether to notify the operator or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### setData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdata) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatch) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### setDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatchfortokenids) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` - Function selector: `0xbe9f0e6f` ::: ```solidity function setDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys, bytes[] dataValues ) external nonpayable; ``` _Sets data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ------------ | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | | `dataValues` | `bytes[]` | An array of values to set for the given data keys. |
### setDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatafortokenid) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataForTokenId(bytes32,bytes32,bytes)` - Function selector: `0xd6c1407c` ::: ```solidity function setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) external nonpayable; ``` _Sets data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### supportsInterface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#supportsinterface) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas. #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### tokenAt :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenat) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenAt(uint256)` - Function selector: `0x92a91a3a` ::: ```solidity function tokenAt(uint256 index) external view returns (bytes32); ``` _Retrieving the `tokenId` for `msg.sender` located in its list at index number `index`._ Returns a token id at index. See [`totalSupply`](#totalsupply) to get total number of minted tokens. #### Parameters | Name | Type | Description | | ------- | :-------: | -------------------------------------------------------- | | `index` | `uint256` | The index to search to search in the enumerable mapping. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------- | | `0` | `bytes32` | TokenId or `bytes32(0)` if no tokenId exist at `index`. |
### tokenIdsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenidsof) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenIdsOf(address)` - Function selector: `0xa3b261f2` ::: ```solidity function tokenIdsOf(address tokenOwner) external view returns (bytes32[]); ``` Returns the list of token IDs that the `tokenOwner` address owns. #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------- | | `tokenOwner` | `address` | The address that we want to get the list of token IDs for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------- | | `0` | `bytes32[]` | An array of `bytes32[] tokenIds` owned by `tokenOwner`. |
### tokenOwnerOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenownerof) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenOwnerOf(bytes32)` - Function selector: `0x217b2270` ::: ```solidity function tokenOwnerOf(bytes32 tokenId) external view returns (address); ``` Returns the address that owns a given `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------ | | `tokenId` | `bytes32` | The token ID to query the owner for. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------- | | `0` | `address` | The owner address of the given `tokenId`. |
### totalSupply :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#totalsupply) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `totalSupply()` - Function selector: `0x18160ddd` ::: ```solidity function totalSupply() external view returns (uint256); ``` Returns the number of existing tokens that have been minted in this contract. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------ | | `0` | `uint256` | The number of existing tokens. |
### transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transfer(address,address,bytes32,bool,bytes)` - Function selector: `0x511b6952` ::: ```solidity function transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) external nonpayable; ``` Transfer a given `tokenId` token from the `from` address to the `to` address. If operators are set for a specific `tokenId`, all the operators are revoked after the tokenId have been transferred. The `force` parameter MUST be set to `true` when transferring tokens to Externally Owned Accounts (EOAs) or contracts that do not implement the LSP1 standard. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address that owns the given `tokenId`. | | `to` | `address` | The address that will receive the `tokenId`. | | `tokenId` | `bytes32` | The token ID to transfer. | | `force` | `bool` | When set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. |
### transferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferbatch) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferBatch(address[],address[],bytes32[],bool[],bytes[])` - Function selector: `0x7e87632c` ::: ```solidity function transferBatch( address[] from, address[] to, bytes32[] tokenId, bool[] force, bytes[] data ) external nonpayable; ``` Transfers multiple tokens at once based on the arrays of `from`, `to` and `tokenId`. If any transfer fails, the whole call will revert. #### Parameters | Name | Type | Description | | --------- | :---------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address[]` | An array of sending addresses. | | `to` | `address[]` | An array of recipient addresses. | | `tokenId` | `bytes32[]` | An array of token IDs to transfer. | | `force` | `bool[]` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard and not revert. | | `data` | `bytes[]` | Any additional data the caller wants included in the emitted event, and sent in the hooks to the `from` and `to` addresses. |
### transferOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferownership) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data key `_LSP8_TOKENID_FORMAT_KEY` cannot be changed once the identifiable digital asset contract has been deployed.
### \_isOperatorOrOwner ```solidity function _isOperatorOrOwner( address caller, bytes32 tokenId ) internal view returns (bool); ``` verifies if the `caller` is operator or owner for the `tokenId` #### Returns | Name | Type | Description | | ---- | :----: | -------------------------------------------- | | `0` | `bool` | true if `caller` is either operator or owner |
### \_revokeOperator ```solidity function _revokeOperator( address operator, address tokenOwner, bytes32 tokenId, bool notified, bytes operatorNotificationData ) internal nonpayable; ``` removes `operator` from the list of operators for the `tokenId`
### \_clearOperators ```solidity function _clearOperators( address tokenOwner, bytes32 tokenId ) internal nonpayable; ``` revoke all the current operators for a specific `tokenId` token which belongs to `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ------------------------------------------------- | | `tokenOwner` | `address` | The address that is the owner of the `tokenId`. | | `tokenId` | `bytes32` | The token to remove the associated operators for. |
### \_exists ```solidity function _exists(bytes32 tokenId) internal view returns (bool); ``` Returns whether `tokenId` exists. Tokens start existing when they are minted ([`_mint`](#_mint)), and stop existing when they are burned ([`_burn`](#_burn)).
### \_existsOrError ```solidity function _existsOrError(bytes32 tokenId) internal view; ``` When `tokenId` does not exist then revert with an error.
### \_mint :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the recipient via LSP1**. ::: ```solidity function _mint( address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Create `tokenId` by minting it and transfers it to `to`.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as `from` address.
#### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------- | | `to` | `address` | @param tokenId The token ID to create (= mint). | | `tokenId` | `bytes32` | The token ID to create (= mint). | | `force` | `bool` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hook of the `to` address. |
### \_burn :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender via LSP1**. ::: :::tip Hint In dApps, you can know which addresses are burning tokens by listening for the `Transfer` event and filter with the zero address as `to`. ::: ```solidity function _burn(bytes32 tokenId, bytes data) internal nonpayable; ``` Burn a specific `tokenId`, removing the `tokenId` from the [`tokenIdsOf`](#tokenidsof) the caller and decreasing its [`balanceOf`](#balanceof) by -1. This will also clear all the operators allowed to transfer the `tokenId`. The owner of the `tokenId` will be notified about the `tokenId` being transferred through its LSP1 [`universalReceiver`](#universalreceiver) function, if it is a contract that supports the LSP1 interface. Its [`universalReceiver`](#universalreceiver) function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as the `to` address.
#### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------------------------------------------------------------------------------------- | | `tokenId` | `bytes32` | The token to burn. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the LSP1 hook on the token owner's address. |
### \_transfer :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender/recipient via LSP1**. ::: :::danger This internal function does not check if the sender is authorized or not to operate on the `tokenId`. ::: ```solidity function _transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Change the owner of the `tokenId` from `from` to `to`. Both the sender and recipient will be notified of the `tokenId` being transferred through their LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event.
#### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The sender address. | | `to` | `address` | @param tokenId The token to transfer. | | `tokenId` | `bytes32` | The token to transfer. | | `force` | `bool` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. |
### \_setDataForTokenId ```solidity function _setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) internal nonpayable; ``` Sets data for a specific `tokenId` and `dataKey` in the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated
**Emitted events:** - [`TokenIdDataChanged`](#tokeniddatachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### \_getDataForTokenId ```solidity function _getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) internal view returns (bytes dataValues); ``` Retrieves data for a specific `tokenId` and `dataKey` from the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ------------ | :-----: | ----------------------------------------------------------------- | | `dataValues` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### \_beforeTokenTransfer ```solidity function _beforeTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------- | | `from` | `address` | The address sending the `tokenId` (`address(0)` when `tokenId` is being minted). | | `to` | `address` | @param tokenId The bytes32 identifier of the token being transferred. | | `tokenId` | `bytes32` | The bytes32 identifier of the token being transferred. | | `data` | `bytes` | The data sent alongside the the token transfer. |
### \_afterTokenTransfer ```solidity function _afterTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` Hook that is called after any token transfer, including minting and burning. Allows to run custom logic after updating balances, but **before notifying sender/recipient via LSP1** by overriding this function. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `from` | `address` | The sender address | | `to` | `address` | @param tokenId The tokenId to transfer | | `tokenId` | `bytes32` | The tokenId to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_notifyTokenOperator ```solidity function _notifyTokenOperator( address operator, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the operator `operator` about the `tokenId` being authorized. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENOPERATOR` as typeId, if `operator` is a contract that supports the LSP1 interface. If `operator` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `operator` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `operator` address in the `universalReceiver` call. |
### \_notifyTokenSender ```solidity function _notifyTokenSender(address from, bytes lsp1Data) internal nonpayable; ``` Attempt to notify the token sender `from` about the `tokenId` being transferred. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. If `from` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. |
### \_notifyTokenReceiver ```solidity function _notifyTokenReceiver( address to, bool force, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the token receiver `to` about the `tokenId` being received. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. If `to` is is an EOA or a contract that does not support the LSP1 interface, the behaviour will depend on the `force` boolean flag. - if `force` is set to `true`, nothing will happen and no notification will be sent. - if `force` is set to `false, the transaction will revert. #### Parameters | Name | Type | Description | | ---------- | :-------: | --------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `lsp1Data` | `bytes` | The data to be sent to the `to` address in the `universalReceiver(...)` call. |
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0).
### \_fallbackLSP17Extendable :::info The LSP8 Token contract should not hold any native tokens. Any native tokens received by the contract will be forwarded to the extension address mapped to the selector from `msg.sig`. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call with the received value to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the address(0) will be returned. We will always forward the value to the extension, as the LSP8 contract is not supposed to hold any native tokens. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the CALL opcode, passing the [`msg.data`](#msg.data) appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the [`msg.value`](#msg.value)
## Events ### DataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#datachanged) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OperatorAuthorizationChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorauthorizationchanged) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorAuthorizationChanged(address,address,bytes32,bytes)` - Event topic hash: `0x1b1b58aa2ec0cec2228b2d37124556d41f5a1f7b12f089171f896cc236671215` ::: ```solidity event OperatorAuthorizationChanged( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` enables `operator` to transfer or burn the `tokenId`. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address authorized as an operator. | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` address has access on behalf of `tokenOwner`. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OperatorRevoked :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorrevoked) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorRevoked(address,address,bytes32,bool,bytes)` - Event topic hash: `0xc78cd419d6136f9f1c1c6aec1d3fae098cffaf8bc86314a8f2685e32fe574e3c` ::: ```solidity event OperatorRevoked( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bool notified, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` disables `operator` to transfer or burn `tokenId` on its behalf. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ---------------------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address revoked from the operator array ([`getOperatorsOf`](#getoperatorsof)). | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notified` | `bool` | Bool indicating whether the operator has been notified or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OwnershipTransferred :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownershiptransferred) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### TokenIdDataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokeniddatachanged) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `TokenIdDataChanged(bytes32,bytes32,bytes)` - Event topic hash: `0xa6e4251f855f750545fe414f120db91c76b88def14d120969e5bb2d3f05debbb` ::: ```solidity event TokenIdDataChanged( bytes32 indexed tokenId, bytes32 indexed dataKey, bytes dataValue ); ``` Emitted when setting data for `tokenId`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `tokenId` **`indexed`** | `bytes32` | The tokenId which data is set for. | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `Transfer(address,address,address,bytes32,bool,bytes)` - Event topic hash: `0xb333c813a7426a7a11e2b190cad52c44119421594b47f6f32ace6d8c7207b2bf` ::: ```solidity event Transfer( address operator, address indexed from, address indexed to, bytes32 indexed tokenId, bool force, bytes data ); ``` Emitted when `tokenId` token is transferred from the `from` to the `to` address. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ---------------------------------------------------------------------------------------------------------------------------------- | | `operator` | `address` | The address of operator that sent the `tokenId` | | `from` **`indexed`** | `address` | The previous owner of the `tokenId` | | `to` **`indexed`** | `address` | The new owner of `tokenId` | | `tokenId` **`indexed`** | `bytes32` | The tokenId that was transferred | | `force` | `bool` | If the token transfer enforces the `to` recipient address to be a contract that implements the LSP1 standard or not. | | `data` | `bytes` | Any additional data the caller included by the caller during the transfer, and sent in the hooks to the `from` and `to` addresses. |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### InvalidExtensionAddress :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidextensionaddress) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidExtensionAddress(bytes)` - Error hash: `0x42bfe79f` ::: ```solidity error InvalidExtensionAddress(bytes storedData); ``` reverts when the bytes retrieved from the LSP17 data key is not a valid address (not 20 bytes) #### Parameters | Name | Type | Description | | ------------ | :-----: | ----------- | | `storedData` | `bytes` | - |
### InvalidFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidfunctionselector) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidFunctionSelector(bytes)` - Error hash: `0xe5099ee3` ::: ```solidity error InvalidFunctionSelector(bytes data); ``` reverts when the contract is called with a function selector not valid (less than 4 bytes of data) #### Parameters | Name | Type | Description | | ------ | :-----: | ----------- | | `data` | `bytes` | - |
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### LSP8BatchCallFailed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8batchcallfailed) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8BatchCallFailed(uint256)` - Error hash: `0x234eb819` ::: ```solidity error LSP8BatchCallFailed(uint256 callIndex); ``` _Batch call failed._ Reverts when a batch call failed. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------- | | `callIndex` | `uint256` | - |
### LSP8CannotSendToAddressZero :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoaddresszero) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotSendToAddressZero()` - Error hash: `0x24ecef4d` ::: ```solidity error LSP8CannotSendToAddressZero(); ``` Reverts when trying to send token to the zero address.
### LSP8CannotUseAddressZeroAsOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotuseaddresszeroasoperator) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotUseAddressZeroAsOperator()` - Error hash: `0x9577b8b3` ::: ```solidity error LSP8CannotUseAddressZeroAsOperator(); ``` Reverts when trying to set the zero address as an operator.
### LSP8InvalidTransferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8invalidtransferbatch) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8InvalidTransferBatch()` - Error hash: `0x93a83119` ::: ```solidity error LSP8InvalidTransferBatch(); ``` Reverts when the parameters used for `transferBatch` have different lengths.
### LSP8NonExistentTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistenttokenid) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistentTokenId(bytes32)` - Error hash: `0xae8f9a36` ::: ```solidity error LSP8NonExistentTokenId(bytes32 tokenId); ``` Reverts when `tokenId` has not been minted. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - |
### LSP8NonExistingOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistingoperator) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistingOperator(address,bytes32)` - Error hash: `0x4aa31a8c` ::: ```solidity error LSP8NonExistingOperator(address operator, bytes32 tokenId); ``` Reverts when `operator` is not an operator for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8NotTokenOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenoperator) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOperator(bytes32,address)` - Error hash: `0x1294d2a9` ::: ```solidity error LSP8NotTokenOperator(bytes32 tokenId, address caller); ``` Reverts when `caller` is not an allowed operator for `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotTokenOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenowner) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOwner(address,bytes32,address)` - Error hash: `0x5b271ea2` ::: ```solidity error LSP8NotTokenOwner(address tokenOwner, bytes32 tokenId, address caller); ``` Reverts when `caller` is not the `tokenOwner` of the `tokenId`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotifyTokenReceiverContractMissingLSP1Interface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceivercontractmissinglsp1interface) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverContractMissingLSP1Interface(address)` - Error hash: `0x4349776d` ::: ```solidity error LSP8NotifyTokenReceiverContractMissingLSP1Interface( address tokenReceiver ); ``` Reverts if the `tokenReceiver` does not implement LSP1 when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8NotifyTokenReceiverIsEOA :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceiveriseoa) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverIsEOA(address)` - Error hash: `0x03173137` ::: ```solidity error LSP8NotifyTokenReceiverIsEOA(address tokenReceiver); ``` Reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8OperatorAlreadyAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8operatoralreadyauthorized) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8OperatorAlreadyAuthorized(address,bytes32)` - Error hash: `0xa7626b68` ::: ```solidity error LSP8OperatorAlreadyAuthorized(address operator, bytes32 tokenId); ``` Reverts when `operator` is already authorized for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8RevokeOperatorNotAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8RevokeOperatorNotAuthorized(address,address,bytes32)` - Error hash: `0x760b5acd` ::: ```solidity error LSP8RevokeOperatorNotAuthorized( address caller, address tokenOwner, bytes32 tokenId ); ``` Reverts when the call to revoke operator is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8TokenContractCannotHoldValue :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokencontractcannotholdvalue) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenContractCannotHoldValue()` - Error hash: `0x61f49442` ::: ```solidity error LSP8TokenContractCannotHoldValue(); ``` _LSP8 contract cannot receive native tokens._ Error occurs when sending native tokens to the LSP8 contract without sending any data. E.g. Sending value without passing a bytes4 function selector to call a LSP17 Extension.
### LSP8TokenIdFormatNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformatnoteditable) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdFormatNotEditable()` - Error hash: `0x3664800a` ::: ```solidity error LSP8TokenIdFormatNotEditable(); ``` Reverts when trying to edit the data key `LSP8TokenIdFormat` after the identifiable digital asset contract has been deployed. The `LSP8TokenIdFormat` data key is located inside the ERC725Y Data key-value store of the identifiable digital asset contract. It can be set only once inside the constructor/initializer when the identifiable digital asset contract is being deployed.
### LSP8TokenIdsDataEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdataemptyarray) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataEmptyArray()` - Error hash: `0x80c98305` ::: ```solidity error LSP8TokenIdsDataEmptyArray(); ``` Reverts when empty arrays is passed to the function
### LSP8TokenIdsDataLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdatalengthmismatch) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataLengthMismatch()` - Error hash: `0x2fa71dfe` ::: ```solidity error LSP8TokenIdsDataLengthMismatch(); ``` Reverts when the length of the token IDs data arrays is not equal
### LSP8TokenOwnerCannotBeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownercannotbeoperator) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerCannotBeOperator()` - Error hash: `0x89fdad62` ::: ```solidity error LSP8TokenOwnerCannotBeOperator(); ``` Reverts when trying to authorize or revoke the token's owner as an operator.
### LSP8TokenOwnerChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownerchanged) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerChanged(bytes32,address,address)` - Error hash: `0x5a9c31d3` ::: ```solidity error LSP8TokenOwnerChanged( bytes32 tokenId, address oldOwner, address newOwner ); ``` Reverts when the token owner changed inside the [`_beforeTokenTransfer`](#_beforetokentransfer) hook. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `oldOwner` | `address` | - | | `newOwner` | `address` | - |
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecallernottheowner) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP8Mintable :::info Standard Specifications [`LSP-8-IdentifiableDigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md) ::: :::info Solidity implementation [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: > LSP8IdentifiableDigitalAsset deployable preset contract with a public [`mint`](#mint) function callable only by the contract [`owner`](#owner). ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#constructor) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity constructor( string name_, string symbol_, address newOwner_, uint256 lsp4TokenType_, uint256 lsp8TokenIdFormat_ ); ``` _Deploying a `LSP8Mintable` token contract with: token name = `name_`, token symbol = `symbol_`, and address `newOwner_` as the token contract owner._ #### Parameters | Name | Type | Description | | -------------------- | :-------: | ---------------------------------------------------------------------------------------------------- | | `name_` | `string` | The name of the token. | | `symbol_` | `string` | The symbol of the token. | | `newOwner_` | `address` | The owner of the token contract. | | `lsp4TokenType_` | `uint256` | The type of token this digital asset contract represents (`0` = Token, `1` = NFT, `2` = Collection). | | `lsp8TokenIdFormat_` | `uint256` | The format of tokenIds (= NFTs) that this contract will create. |
### fallback :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#fallback) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), revert.
### receive :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#receive) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) ::: ```solidity receive() external payable; ``` _LSP8 contract cannot receive native tokens._ Reverts whenever someone tries to send native tokens to a LSP8 contract.
### authorizeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#authorizeoperator) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `authorizeOperator(address,bytes32,bytes)` - Function selector: `0x86a10ddd` ::: ```solidity function authorizeOperator( address operator, bytes32 tokenId, bytes operatorNotificationData ) external nonpayable; ``` Allow an `operator` address to transfer or burn a specific `tokenId` on behalf of its token owner. See [`isOperatorFor`](#isoperatorfor). Notify the operator based on the LSP1-UniversalReceiver standard #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ----------------------------------------------- | | `operator` | `address` | The address to authorize as an operator. | | `tokenId` | `bytes32` | The token ID operator has access to. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### balanceOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#balanceof) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `balanceOf(address)` - Function selector: `0x70a08231` ::: ```solidity function balanceOf(address tokenOwner) external view returns (uint256); ``` Get the number of token IDs owned by `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------- | | `tokenOwner` | `address` | The address to query \* | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------------------- | | `0` | `uint256` | The total number of token IDs that `tokenOwner` owns. |
### batchCalls :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#batchcalls) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### getData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdata) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatch) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### getDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatabatchfortokenids) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataBatchForTokenIds(bytes32[],bytes32[])` - Function selector: `0x1d26fce6` ::: ```solidity function getDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Retrieves data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ---------- | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------------------------------- | | `dataValues` | `bytes[]` | An array of data values for each pair of `tokenId` and `dataKey`. |
### getDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatafortokenid) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getDataForTokenId(bytes32,bytes32)` - Function selector: `0x16e023b3` ::: ```solidity function getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) external view returns (bytes dataValue); ``` _Retrieves data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------- | | `dataValue` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### getOperatorsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getoperatorsof) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `getOperatorsOf(bytes32)` - Function selector: `0x49a6078d` ::: ```solidity function getOperatorsOf(bytes32 tokenId) external view returns (address[]); ``` Returns all `operator` addresses that are allowed to transfer or burn a specific `tokenId` on behalf of its owner. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `tokenId` | `bytes32` | The token ID to get the operators for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------------------------------------------------------------ | | `0` | `address[]` | An array of operators allowed to transfer or burn a specific `tokenId`. Requirements - `tokenId` must exist. |
### isOperatorFor :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#isoperatorfor) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `isOperatorFor(address,bytes32)` - Function selector: `0x2a3654a4` ::: ```solidity function isOperatorFor( address operator, bytes32 tokenId ) external view returns (bool); ``` Returns whether `operator` address is an operator for a given `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------- | | `operator` | `address` | The address to query operator status for. | | `tokenId` | `bytes32` | The token ID to check if `operator` is allowed to operate on. | #### Returns | Name | Type | Description | | ---- | :----: | --------------------------------------------------------------------- | | `0` | `bool` | `true` if `operator` is an operator for `tokenId`, `false` otherwise. |
### mint :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#mint) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `mint(address,bytes32,bool,bytes)` - Function selector: `0xaf255b61` ::: ```solidity function mint( address to, bytes32 tokenId, bool force, bytes data ) external nonpayable; ``` _Minting tokenId `tokenId` for address `to` with the additional data `data` (Note: allow non-LSP1 recipient is set to `force`)._ Public [`_mint`](#_mint) function only callable by the [`owner`](#owner). #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------------------------------------------------------------------------------------------------ | | `to` | `address` | The address that will receive the minted `tokenId`. | | `tokenId` | `bytes32` | The tokenId to mint. | | `force` | `bool` | Set to `false` to ensure that you are minting for a recipient that implements LSP1, `false` otherwise for forcing the minting. | | `data` | `bytes` | Any addition data to be sent alongside the minting. |
### owner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#owner) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#renounceownership) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: ```solidity function renounceOwnership() external nonpayable; ``` Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.
### revokeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `revokeOperator(address,bytes32,bool,bytes)` - Function selector: `0xdb8c9663` ::: ```solidity function revokeOperator( address operator, bytes32 tokenId, bool notify, bytes operatorNotificationData ) external nonpayable; ``` Remove access of `operator` for a given `tokenId`, disallowing it to transfer `tokenId` on behalf of its owner. See also [`isOperatorFor`](#isoperatorfor). #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------- | | `operator` | `address` | The address to revoke as an operator. | | `tokenId` | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notify` | `bool` | Boolean indicating whether to notify the operator or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### setData :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdata) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner).
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatch) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: :::caution Warning **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - SHOULD only be callable by the [`owner`](#owner) of the contract.
**Emitted events:** - [`DataChanged`](#datachanged) event **for each data key/value pair set**.
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### setDataBatchForTokenIds :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatabatchfortokenids) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` - Function selector: `0xbe9f0e6f` ::: ```solidity function setDataBatchForTokenIds( bytes32[] tokenIds, bytes32[] dataKeys, bytes[] dataValues ) external nonpayable; ``` _Sets data in batch for multiple `tokenId` and `dataKey` pairs._ #### Parameters | Name | Type | Description | | ------------ | :---------: | ----------------------------------------------------- | | `tokenIds` | `bytes32[]` | An array of token IDs. | | `dataKeys` | `bytes32[]` | An array of data keys corresponding to the token IDs. | | `dataValues` | `bytes[]` | An array of values to set for the given data keys. |
### setDataForTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatafortokenid) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `setDataForTokenId(bytes32,bytes32,bytes)` - Function selector: `0xd6c1407c` ::: ```solidity function setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) external nonpayable; ``` _Sets data for a specific `tokenId` and `dataKey`._ #### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### supportsInterface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#supportsinterface) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas. #### Parameters | Name | Type | Description | | ------------- | :------: | ----------- | | `interfaceId` | `bytes4` | - | #### Returns | Name | Type | Description | | ---- | :----: | ----------- | | `0` | `bool` | - |
### tokenIdsOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenidsof) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenIdsOf(address)` - Function selector: `0xa3b261f2` ::: ```solidity function tokenIdsOf(address tokenOwner) external view returns (bytes32[]); ``` Returns the list of token IDs that the `tokenOwner` address owns. #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------- | | `tokenOwner` | `address` | The address that we want to get the list of token IDs for. | #### Returns | Name | Type | Description | | ---- | :---------: | ------------------------------------------------------- | | `0` | `bytes32[]` | An array of `bytes32[] tokenIds` owned by `tokenOwner`. |
### tokenOwnerOf :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokenownerof) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `tokenOwnerOf(bytes32)` - Function selector: `0x217b2270` ::: ```solidity function tokenOwnerOf(bytes32 tokenId) external view returns (address); ``` Returns the address that owns a given `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------ | | `tokenId` | `bytes32` | The token ID to query the owner for. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------- | | `0` | `address` | The owner address of the given `tokenId`. |
### totalSupply :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#totalsupply) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `totalSupply()` - Function selector: `0x18160ddd` ::: ```solidity function totalSupply() external view returns (uint256); ``` Returns the number of existing tokens that have been minted in this contract. #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------ | | `0` | `uint256` | The number of existing tokens. |
### transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transfer(address,address,bytes32,bool,bytes)` - Function selector: `0x511b6952` ::: ```solidity function transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) external nonpayable; ``` Transfer a given `tokenId` token from the `from` address to the `to` address. If operators are set for a specific `tokenId`, all the operators are revoked after the tokenId have been transferred. The `force` parameter MUST be set to `true` when transferring tokens to Externally Owned Accounts (EOAs) or contracts that do not implement the LSP1 standard. #### Parameters | Name | Type | Description | | --------- | :-------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The address that owns the given `tokenId`. | | `to` | `address` | The address that will receive the `tokenId`. | | `tokenId` | `bytes32` | The token ID to transfer. | | `force` | `bool` | When set to `true`, the `to` address CAN be any address. When set to `false`, the `to` address MUST be a contract that supports the LSP1 UniversalReceiver standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. |
### transferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferbatch) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferBatch(address[],address[],bytes32[],bool[],bytes[])` - Function selector: `0x7e87632c` ::: ```solidity function transferBatch( address[] from, address[] to, bytes32[] tokenId, bool[] force, bytes[] data ) external nonpayable; ``` Transfers multiple tokens at once based on the arrays of `from`, `to` and `tokenId`. If any transfer fails, the whole call will revert. #### Parameters | Name | Type | Description | | --------- | :---------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `from` | `address[]` | An array of sending addresses. | | `to` | `address[]` | An array of recipient addresses. | | `tokenId` | `bytes32[]` | An array of token IDs to transfer. | | `force` | `bool[]` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard and not revert. | | `data` | `bytes[]` | Any additional data the caller wants included in the emitted event, and sent in the hooks to the `from` and `to` addresses. |
### transferOwnership :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transferownership) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `newOwner` | `address` | - |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` The ERC725Y data key `_LSP8_TOKENID_FORMAT_KEY` cannot be changed once the identifiable digital asset contract has been deployed.
### \_isOperatorOrOwner ```solidity function _isOperatorOrOwner( address caller, bytes32 tokenId ) internal view returns (bool); ``` verifies if the `caller` is operator or owner for the `tokenId` #### Returns | Name | Type | Description | | ---- | :----: | -------------------------------------------- | | `0` | `bool` | true if `caller` is either operator or owner |
### \_revokeOperator ```solidity function _revokeOperator( address operator, address tokenOwner, bytes32 tokenId, bool notified, bytes operatorNotificationData ) internal nonpayable; ``` removes `operator` from the list of operators for the `tokenId`
### \_clearOperators ```solidity function _clearOperators( address tokenOwner, bytes32 tokenId ) internal nonpayable; ``` revoke all the current operators for a specific `tokenId` token which belongs to `tokenOwner`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ------------------------------------------------- | | `tokenOwner` | `address` | The address that is the owner of the `tokenId`. | | `tokenId` | `bytes32` | The token to remove the associated operators for. |
### \_exists ```solidity function _exists(bytes32 tokenId) internal view returns (bool); ``` Returns whether `tokenId` exists. Tokens start existing when they are minted ([`_mint`](#_mint)), and stop existing when they are burned ([`_burn`](#_burn)).
### \_existsOrError ```solidity function _existsOrError(bytes32 tokenId) internal view; ``` When `tokenId` does not exist then revert with an error.
### \_mint :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the recipient via LSP1**. ::: ```solidity function _mint( address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Create `tokenId` by minting it and transfers it to `to`.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as `from` address.
#### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------- | | `to` | `address` | @param tokenId The token ID to create (= mint). | | `tokenId` | `bytes32` | The token ID to create (= mint). | | `force` | `bool` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the hook of the `to` address. |
### \_burn :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender via LSP1**. ::: :::tip Hint In dApps, you can know which addresses are burning tokens by listening for the `Transfer` event and filter with the zero address as `to`. ::: ```solidity function _burn(bytes32 tokenId, bytes data) internal nonpayable; ``` Burn a specific `tokenId`, removing the `tokenId` from the [`tokenIdsOf`](#tokenidsof) the caller and decreasing its [`balanceOf`](#balanceof) by -1. This will also clear all the operators allowed to transfer the `tokenId`. The owner of the `tokenId` will be notified about the `tokenId` being transferred through its LSP1 [`universalReceiver`](#universalreceiver) function, if it is a contract that supports the LSP1 interface. Its [`universalReceiver`](#universalreceiver) function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event with `address(0)` as the `to` address.
#### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------------------------------------------------------------------------------------- | | `tokenId` | `bytes32` | The token to burn. | | `data` | `bytes` | Any additional data the caller wants included in the emitted event, and sent in the LSP1 hook on the token owner's address. |
### \_transfer :::info Any logic in the: - [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances and ownership of `tokenId`s. - [`_afterTokenTransfer`](#_aftertokentransfer) function will run after updating the balances and ownership of `tokenId`s, **but before notifying the sender/recipient via LSP1**. ::: :::danger This internal function does not check if the sender is authorized or not to operate on the `tokenId`. ::: ```solidity function _transfer( address from, address to, bytes32 tokenId, bool force, bytes data ) internal nonpayable; ``` Change the owner of the `tokenId` from `from` to `to`. Both the sender and recipient will be notified of the `tokenId` being transferred through their LSP1 [`universalReceiver`](#universalreceiver) function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive all the parameters in the calldata packed encoded.
**Emitted events:** - [`Transfer`](#transfer) event.
#### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------- | | `from` | `address` | The sender address. | | `to` | `address` | @param tokenId The token to transfer. | | `tokenId` | `bytes32` | The token to transfer. | | `force` | `bool` | When set to `true`, `to` may be any address. When set to `false`, `to` must be a contract that supports the LSP1 standard. | | `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. |
### \_setDataForTokenId ```solidity function _setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes dataValue ) internal nonpayable; ``` Sets data for a specific `tokenId` and `dataKey` in the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated
**Emitted events:** - [`TokenIdDataChanged`](#tokeniddatachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### \_getDataForTokenId ```solidity function _getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) internal view returns (bytes dataValues); ``` Retrieves data for a specific `tokenId` and `dataKey` from the ERC725Y storage The ERC725Y data key is the hash of the `tokenId` and `dataKey` concatenated #### Parameters | Name | Type | Description | | --------- | :-------: | ---------------------------------- | | `tokenId` | `bytes32` | The unique identifier for a token. | | `dataKey` | `bytes32` | The key for the data to retrieve. | #### Returns | Name | Type | Description | | ------------ | :-----: | ----------------------------------------------------------------- | | `dataValues` | `bytes` | The data value associated with the given `tokenId` and `dataKey`. |
### \_beforeTokenTransfer ```solidity function _beforeTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` Hook that is called before any token transfer, including minting and burning. Allows to run custom logic before updating balances and notifying sender/recipient by overriding this function. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `from` | `address` | The sender address | | `to` | `address` | @param tokenId The tokenId to transfer | | `tokenId` | `bytes32` | The tokenId to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_afterTokenTransfer ```solidity function _afterTokenTransfer( address from, address to, bytes32 tokenId, bytes data ) internal nonpayable; ``` Hook that is called after any token transfer, including minting and burning. Allows to run custom logic after updating balances, but **before notifying sender/recipient via LSP1** by overriding this function. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------- | | `from` | `address` | The sender address | | `to` | `address` | @param tokenId The tokenId to transfer | | `tokenId` | `bytes32` | The tokenId to transfer | | `data` | `bytes` | The data sent alongside the transfer |
### \_notifyTokenOperator ```solidity function _notifyTokenOperator( address operator, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the operator `operator` about the `tokenId` being authorized. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENOPERATOR` as typeId, if `operator` is a contract that supports the LSP1 interface. If `operator` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `operator` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `operator` address in the `universalReceiver` call. |
### \_notifyTokenSender ```solidity function _notifyTokenSender(address from, bytes lsp1Data) internal nonpayable; ``` Attempt to notify the token sender `from` about the `tokenId` being transferred. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. If `from` is an EOA or a contract that does not support the LSP1 interface, nothing will happen and no notification will be sent. #### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------------------------------------------------ | | `from` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. |
### \_notifyTokenReceiver ```solidity function _notifyTokenReceiver( address to, bool force, bytes lsp1Data ) internal nonpayable; ``` Attempt to notify the token receiver `to` about the `tokenId` being received. This is done by calling its [`universalReceiver`](#universalreceiver) function with the `_TYPEID_LSP8_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. If `to` is is an EOA or a contract that does not support the LSP1 interface, the behaviour will depend on the `force` boolean flag. - if `force` is set to `true`, nothing will happen and no notification will be sent. - if `force` is set to `false, the transaction will revert. #### Parameters | Name | Type | Description | | ---------- | :-------: | --------------------------------------------------------------------------------------------------- | | `to` | `address` | The address to call the [`universalReceiver`](#universalreceiver) function on. | | `force` | `bool` | A boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. | | `lsp1Data` | `bytes` | The data to be sent to the `to` address in the `universalReceiver(...)` call. |
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0).
### \_fallbackLSP17Extendable :::info The LSP8 Token contract should not hold any native tokens. Any native tokens received by the contract will be forwarded to the extension address mapped to the selector from `msg.sig`. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call with the received value to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the address(0) will be returned. We will always forward the value to the extension, as the LSP8 contract is not supposed to hold any native tokens. Reverts if there is no extension for the function being called. If there is an extension for the function selector being called, it calls the extension with the CALL opcode, passing the [`msg.data`](#msg.data) appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the [`msg.value`](#msg.value)
## Events ### DataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#datachanged) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### OperatorAuthorizationChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorauthorizationchanged) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorAuthorizationChanged(address,address,bytes32,bytes)` - Event topic hash: `0x1b1b58aa2ec0cec2228b2d37124556d41f5a1f7b12f089171f896cc236671215` ::: ```solidity event OperatorAuthorizationChanged( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` enables `operator` to transfer or burn the `tokenId`. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | -------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address authorized as an operator. | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` address has access on behalf of `tokenOwner`. | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OperatorRevoked :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#operatorrevoked) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OperatorRevoked(address,address,bytes32,bool,bytes)` - Event topic hash: `0xc78cd419d6136f9f1c1c6aec1d3fae098cffaf8bc86314a8f2685e32fe574e3c` ::: ```solidity event OperatorRevoked( address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bool notified, bytes operatorNotificationData ); ``` Emitted when `tokenOwner` disables `operator` to transfer or burn `tokenId` on its behalf. #### Parameters | Name | Type | Description | | -------------------------- | :-------: | ---------------------------------------------------------------------------------- | | `operator` **`indexed`** | `address` | The address revoked from the operator array ([`getOperatorsOf`](#getoperatorsof)). | | `tokenOwner` **`indexed`** | `address` | The owner of the `tokenId`. | | `tokenId` **`indexed`** | `bytes32` | The tokenId `operator` is revoked from operating on. | | `notified` | `bool` | Bool indicating whether the operator has been notified or not | | `operatorNotificationData` | `bytes` | The data to notify the operator about via LSP1. |
### OwnershipTransferred :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownershiptransferred) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### TokenIdDataChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#tokeniddatachanged) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `TokenIdDataChanged(bytes32,bytes32,bytes)` - Event topic hash: `0xa6e4251f855f750545fe414f120db91c76b88def14d120969e5bb2d3f05debbb` ::: ```solidity event TokenIdDataChanged( bytes32 indexed tokenId, bytes32 indexed dataKey, bytes dataValue ); ``` Emitted when setting data for `tokenId`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `tokenId` **`indexed`** | `bytes32` | The tokenId which data is set for. | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Transfer :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#transfer) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Event signature: `Transfer(address,address,address,bytes32,bool,bytes)` - Event topic hash: `0xb333c813a7426a7a11e2b190cad52c44119421594b47f6f32ace6d8c7207b2bf` ::: ```solidity event Transfer( address operator, address indexed from, address indexed to, bytes32 indexed tokenId, bool force, bytes data ); ``` Emitted when `tokenId` token is transferred from the `from` to the `to` address. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ---------------------------------------------------------------------------------------------------------------------------------- | | `operator` | `address` | The address of operator that sent the `tokenId` | | `from` **`indexed`** | `address` | The previous owner of the `tokenId` | | `to` **`indexed`** | `address` | The new owner of `tokenId` | | `tokenId` **`indexed`** | `bytes32` | The tokenId that was transferred | | `force` | `bool` | If the token transfer enforces the `to` recipient address to be a contract that implements the LSP1 standard or not. | | `data` | `bytes` | Any additional data the caller included by the caller during the transfer, and sent in the hooks to the `from` and `to` addresses. |
## Errors ### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### InvalidExtensionAddress :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidextensionaddress) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidExtensionAddress(bytes)` - Error hash: `0x42bfe79f` ::: ```solidity error InvalidExtensionAddress(bytes storedData); ``` reverts when the bytes retrieved from the LSP17 data key is not a valid address (not 20 bytes) #### Parameters | Name | Type | Description | | ------------ | :-----: | ----------- | | `storedData` | `bytes` | - |
### InvalidFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#invalidfunctionselector) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `InvalidFunctionSelector(bytes)` - Error hash: `0xe5099ee3` ::: ```solidity error InvalidFunctionSelector(bytes data); ``` reverts when the contract is called with a function selector not valid (less than 4 bytes of data) #### Parameters | Name | Type | Description | | ------ | :-----: | ----------- | | `data` | `bytes` | - |
### LSP4TokenNameNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokennamenoteditable) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenNameNotEditable()` - Error hash: `0x85c169bd` ::: ```solidity error LSP4TokenNameNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenName` after the digital asset contract has been deployed / initialized. The `LSP4TokenName` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenSymbolNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokensymbolnoteditable) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenSymbolNotEditable()` - Error hash: `0x76755b38` ::: ```solidity error LSP4TokenSymbolNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenSymbol` after the digital asset contract has been deployed / initialized. The `LSP4TokenSymbol` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor/initializer when the digital asset contract is being deployed / initialized.
### LSP4TokenTypeNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp4tokentypenoteditable) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP4TokenTypeNotEditable()` - Error hash: `0x4ef6d7fb` ::: ```solidity error LSP4TokenTypeNotEditable(); ``` Reverts when trying to edit the data key `LSP4TokenType` after the digital asset contract has been deployed / initialized. The `LSP4TokenType` data key is located inside the ERC725Y data key-value store of the digital asset contract. It can be set only once inside the constructor / initializer when the digital asset contract is being deployed / initialized.
### LSP8BatchCallFailed :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8batchcallfailed) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8BatchCallFailed(uint256)` - Error hash: `0x234eb819` ::: ```solidity error LSP8BatchCallFailed(uint256 callIndex); ``` _Batch call failed._ Reverts when a batch call failed. #### Parameters | Name | Type | Description | | ----------- | :-------: | ----------- | | `callIndex` | `uint256` | - |
### LSP8CannotSendToAddressZero :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoaddresszero) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotSendToAddressZero()` - Error hash: `0x24ecef4d` ::: ```solidity error LSP8CannotSendToAddressZero(); ``` Reverts when trying to send token to the zero address.
### LSP8CannotUseAddressZeroAsOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotuseaddresszeroasoperator) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8CannotUseAddressZeroAsOperator()` - Error hash: `0x9577b8b3` ::: ```solidity error LSP8CannotUseAddressZeroAsOperator(); ``` Reverts when trying to set the zero address as an operator.
### LSP8InvalidTransferBatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8invalidtransferbatch) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8InvalidTransferBatch()` - Error hash: `0x93a83119` ::: ```solidity error LSP8InvalidTransferBatch(); ``` Reverts when the parameters used for `transferBatch` have different lengths.
### LSP8NonExistentTokenId :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistenttokenid) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistentTokenId(bytes32)` - Error hash: `0xae8f9a36` ::: ```solidity error LSP8NonExistentTokenId(bytes32 tokenId); ``` Reverts when `tokenId` has not been minted. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - |
### LSP8NonExistingOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nonexistingoperator) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NonExistingOperator(address,bytes32)` - Error hash: `0x4aa31a8c` ::: ```solidity error LSP8NonExistingOperator(address operator, bytes32 tokenId); ``` Reverts when `operator` is not an operator for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8NotTokenOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenoperator) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOperator(bytes32,address)` - Error hash: `0x1294d2a9` ::: ```solidity error LSP8NotTokenOperator(bytes32 tokenId, address caller); ``` Reverts when `caller` is not an allowed operator for `tokenId`. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotTokenOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8nottokenowner) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotTokenOwner(address,bytes32,address)` - Error hash: `0x5b271ea2` ::: ```solidity error LSP8NotTokenOwner(address tokenOwner, bytes32 tokenId, address caller); ``` Reverts when `caller` is not the `tokenOwner` of the `tokenId`. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - | | `caller` | `address` | - |
### LSP8NotifyTokenReceiverContractMissingLSP1Interface :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceivercontractmissinglsp1interface) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverContractMissingLSP1Interface(address)` - Error hash: `0x4349776d` ::: ```solidity error LSP8NotifyTokenReceiverContractMissingLSP1Interface( address tokenReceiver ); ``` Reverts if the `tokenReceiver` does not implement LSP1 when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8NotifyTokenReceiverIsEOA :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8notifytokenreceiveriseoa) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8NotifyTokenReceiverIsEOA(address)` - Error hash: `0x03173137` ::: ```solidity error LSP8NotifyTokenReceiverIsEOA(address tokenReceiver); ``` Reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool force` set as `false`. #### Parameters | Name | Type | Description | | --------------- | :-------: | ----------- | | `tokenReceiver` | `address` | - |
### LSP8OperatorAlreadyAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8operatoralreadyauthorized) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8OperatorAlreadyAuthorized(address,bytes32)` - Error hash: `0xa7626b68` ::: ```solidity error LSP8OperatorAlreadyAuthorized(address operator, bytes32 tokenId); ``` Reverts when `operator` is already authorized for the `tokenId`. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `operator` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8RevokeOperatorNotAuthorized :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8RevokeOperatorNotAuthorized(address,address,bytes32)` - Error hash: `0x760b5acd` ::: ```solidity error LSP8RevokeOperatorNotAuthorized( address caller, address tokenOwner, bytes32 tokenId ); ``` Reverts when the call to revoke operator is not authorized. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------- | | `caller` | `address` | - | | `tokenOwner` | `address` | - | | `tokenId` | `bytes32` | - |
### LSP8TokenContractCannotHoldValue :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokencontractcannotholdvalue) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenContractCannotHoldValue()` - Error hash: `0x61f49442` ::: ```solidity error LSP8TokenContractCannotHoldValue(); ``` _LSP8 contract cannot receive native tokens._ Error occurs when sending native tokens to the LSP8 contract without sending any data. E.g. Sending value without passing a bytes4 function selector to call a LSP17 Extension.
### LSP8TokenIdAlreadyMinted :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidalreadyminted) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdAlreadyMinted(bytes32)` - Error hash: `0x34c7b511` ::: ```solidity error LSP8TokenIdAlreadyMinted(bytes32 tokenId); ``` Reverts when `tokenId` has already been minted. #### Parameters | Name | Type | Description | | --------- | :-------: | ----------- | | `tokenId` | `bytes32` | - |
### LSP8TokenIdFormatNotEditable :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformatnoteditable) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdFormatNotEditable()` - Error hash: `0x3664800a` ::: ```solidity error LSP8TokenIdFormatNotEditable(); ``` Reverts when trying to edit the data key `LSP8TokenIdFormat` after the identifiable digital asset contract has been deployed. The `LSP8TokenIdFormat` data key is located inside the ERC725Y Data key-value store of the identifiable digital asset contract. It can be set only once inside the constructor/initializer when the identifiable digital asset contract is being deployed.
### LSP8TokenIdsDataEmptyArray :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdataemptyarray) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataEmptyArray()` - Error hash: `0x80c98305` ::: ```solidity error LSP8TokenIdsDataEmptyArray(); ``` Reverts when empty arrays is passed to the function
### LSP8TokenIdsDataLengthMismatch :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidsdatalengthmismatch) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenIdsDataLengthMismatch()` - Error hash: `0x2fa71dfe` ::: ```solidity error LSP8TokenIdsDataLengthMismatch(); ``` Reverts when the length of the token IDs data arrays is not equal
### LSP8TokenOwnerCannotBeOperator :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownercannotbeoperator) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerCannotBeOperator()` - Error hash: `0x89fdad62` ::: ```solidity error LSP8TokenOwnerCannotBeOperator(); ``` Reverts when trying to authorize or revoke the token's owner as an operator.
### LSP8TokenOwnerChanged :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenownerchanged) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `LSP8TokenOwnerChanged(bytes32,address,address)` - Error hash: `0x5a9c31d3` ::: ```solidity error LSP8TokenOwnerChanged( bytes32 tokenId, address oldOwner, address newOwner ); ``` Reverts when the token owner changed inside the [`_beforeTokenTransfer`](#_beforetokentransfer) hook. #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------- | | `tokenId` | `bytes32` | - | | `oldOwner` | `address` | - | | `newOwner` | `address` | - |
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecallernottheowner) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
### OwnableCannotSetZeroAddressAsOwner :::note References - Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#ownablecannotsetzeroaddressasowner) - Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol) - Error signature: `OwnableCannotSetZeroAddressAsOwner()` - Error hash: `0x1ad8836c` ::: ```solidity error OwnableCannotSetZeroAddressAsOwner(); ``` Reverts when trying to set `address(0)` as the contract owner when deploying the contract, initializing it or transferring ownership of the contract.
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # LSP9Vault :::info Standard Specifications [`LSP-9-Vault`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md) ::: :::info Solidity implementation [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) ::: > Implementation of LSP9Vault built on top of [ERC725], [LSP-1-UniversalReceiver] Could be owned by an EOA or by a contract and is able to receive and send assets. Also allows for registering received assets by leveraging the key-value storage. ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#constructor) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) ::: ```solidity constructor(address newOwner); ``` _Deploying a LSP9Vault contract with owner set to address `initialOwner`._ Sets `initialOwner` as the contract owner and the `SupportedStandards:LSP9Vault` Data Key. The `constructor` also allows funding the contract on deployment.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event when funding the contract on deployment. - [`OwnershipTransferred`](#ownershiptransferred) event when `initialOwner` is set as the contract [`owner`](#owner). - [`DataChanged`](#datachanged) event when setting the [`_LSP9_SUPPORTED_STANDARDS_KEY`](#_lsp9_supported_standards_key). - [`UniversalReceiver`](#universalreceiver) event when notifying the `initialOwner`.
#### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------ | | `newOwner` | `address` | The new owner of the contract. |
### fallback :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#fallback) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) ::: ```solidity fallback(bytes calldata callData) external payable returns (bytes memory); ``` _The `fallback` function was called with the following amount of native tokens: `msg.value`; and the following calldata: `callData`._ Achieves the goal of [LSP-17-ContractExtension] standard by extending the contract to handle calls of functions that do not exist natively, forwarding the function call to the extension address mapped to the function being called. This function is executed when: - Sending data of length less than 4 bytes to the contract. - The first 4 bytes of the calldata do not match any publicly callable functions from the contract ABI. - Receiving native tokens with some calldata. 1. If the data is equal or longer than 4 bytes, the [ERC-725Y] storage is queried with the following data key: [_LSP17_EXTENSION_PREFIX] + `bytes4(msg.sig)` (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is no address stored under the following data key, revert with [`NoExtensionFoundForFunctionSelector(bytes4)`](#noextensionfoundforfunctionselector). The data key relative to `bytes4(0)` is an exception, where no reverts occurs if there is no extension address stored under. This exception is made to allow users to send random data (graffiti) to the account and to be able to react on it. - If there is an address, forward the `msg.data` to the extension using the CALL opcode, appending 52 bytes (20 bytes of `msg.sender` and 32 bytes of `msg.value`). Return what the calls returns, or revert if the call failed. 2. If the data sent to this function is of length less than 4 bytes (not a function selector), return.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens and extension function selector is not found or not payable.

### receive :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#receive) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) ::: ```solidity receive() external payable; ``` Executed: - When receiving some native tokens without any additional data. - On empty calls to the contract.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) when receiving native tokens.

### RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#renounce_ownership_confirmation_delay) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY()` - Function selector: `0xead3fbdf` ::: ```solidity function RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY() external view returns (uint256); ``` #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `uint256` | - |
### RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#renounce_ownership_confirmation_period) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD()` - Function selector: `0x01bfba61` ::: ```solidity function RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD() external view returns (uint256); ``` #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `uint256` | - |
### VERSION :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#version) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `VERSION()` - Function selector: `0xffa1ad74` ::: ```solidity function VERSION() external view returns (string); ``` _Contract version._ #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `string` | - |
### acceptOwnership :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#acceptownership) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `acceptOwnership()` - Function selector: `0x79ba5097` ::: ```solidity function acceptOwnership() external nonpayable; ``` _`msg.sender` is accepting ownership of contract: `address(this)`._ Transfer ownership of the contract from the current [`owner()`](#owner) to the [`pendingOwner()`](#pendingowner). Once this function is called: - The current [`owner()`](#owner) will lose access to the functions restricted to the [`owner()`](#owner) only. - The [`pendingOwner()`](#pendingowner) will gain access to the functions restricted to the [`owner()`](#owner) only.
**Requirements:** - Only the [`pendingOwner`](#pendingowner) can call this function. - When notifying the previous owner via LSP1, the typeId used must be the `keccak256(...)` hash of [LSP0OwnershipTransferred_SenderNotification]. - When notifying the new owner via LSP1, the typeId used must be the `keccak256(...)` hash of [LSP0OwnershipTransferred_RecipientNotification].

### batchCalls :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#batchcalls) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### execute :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#execute) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `execute(uint256,address,uint256,bytes)` - Function selector: `0x44c028fe` ::: :::info The `operationType` 4 `DELEGATECALL` is disabled by default in the LSP9 Vault. ::: ```solidity function execute( uint256 operationType, address target, uint256 value, bytes data ) external payable returns (bytes); ``` _Calling address `target` using `operationType`, transferring `value` wei and data: `data`._ Generic executor function to: - send native tokens to any address. - interact with any contract by passing an abi-encoded function call in the `data` parameter. - deploy a contract by providing its creation bytecode in the `data` parameter.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner. - If a `value` is provided, the contract must have at least this amount in its balance to execute successfully. - If the operation type is `CREATE` (1) or `CREATE2` (2), `target` must be `address(0)`. - If the operation type is `STATICCALL` (3), `value` transfer is disallowed and must be 0.
**Emitted events:** - [`Executed`](#executed) event for each call that uses under `operationType`: `CALL` (0) and `STATICCALL` (3). - [`ContractCreated`](#contractcreated) event, when a contract is created under `operationType`: `CREATE` (1) and `CREATE2` (2). - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens.
#### Parameters | Name | Type | Description | | --------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `operationType` | `uint256` | The operation type used: CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4 | | `target` | `address` | The address of the EOA or smart contract. (unused if a contract is created via operation type 1 or 2) | | `value` | `uint256` | The amount of native tokens to transfer (in Wei) | | `data` | `bytes` | The call data, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-----: | ----------- | | `0` | `bytes` | - |
### executeBatch :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#executebatch) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `executeBatch(uint256[],address[],uint256[],bytes[])` - Function selector: `0x31858452` ::: :::info The `operationType` 4 `DELEGATECALL` is disabled by default in the LSP9 Vault. ::: ```solidity function executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) external payable returns (bytes[]); ``` _Calling multiple addresses `targets` using `operationsType`, transferring `values` wei and data: `datas`._ Batch executor function that behaves the same as [`execute`](#execute) but allowing multiple operations in the same transaction.
**Requirements:** - The length of the parameters provided must be equal. - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner. - If a `value` is provided, the contract must have at least this amount in its balance to execute successfully. - If the operation type is `CREATE` (1) or `CREATE2` (2), `target` must be `address(0)`. - If the operation type is `STATICCALL` (3), `value` transfer is disallowed and must be 0.
**Emitted events:** - [`Executed`](#executed) event for each call that uses under `operationType`: `CALL` (0) and `STATICCALL` (3). (each iteration) - [`ContractCreated`](#contractcreated) event, when a contract is created under `operationType`: `CREATE` (1) and `CREATE2` (2). (each iteration) - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens.
#### Parameters | Name | Type | Description | | ---------------- | :---------: | --------------------------------------------------------------------------------------------------------------- | | `operationsType` | `uint256[]` | The list of operations type used: `CALL = 0`; `CREATE = 1`; `CREATE2 = 2`; `STATICCALL = 3`; `DELEGATECALL = 4` | | `targets` | `address[]` | The list of addresses to call. `targets` will be unused if a contract is created (operation types 1 and 2). | | `values` | `uint256[]` | The list of native token amounts to transfer (in Wei). | | `datas` | `bytes[]` | The list of calldata, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `bytes[]` | - |
### getData :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#getdata) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#getdatabatch) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### owner :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#owner) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### pendingOwner :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#pendingowner) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `pendingOwner()` - Function selector: `0xe30c3978` ::: :::info If no ownership transfer is in progress, the pendingOwner will be `address(0).`. ::: ```solidity function pendingOwner() external view returns (address); ``` The address that ownership of the contract is transferred to. This address may use [`acceptOwnership()`](#acceptownership) to gain ownership of the contract. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#renounceownership) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: :::danger Leaves the contract without an owner. Once ownership of the contract has been renounced, any functions that are restricted to be called by the owner will be permanently inaccessible, making these functions not callable anymore and unusable. ::: ```solidity function renounceOwnership() external nonpayable; ``` _`msg.sender` is renouncing ownership of contract `address(this)`._ Renounce ownership of the contract in a 2-step process. 1. The first call will initiate the process of renouncing ownership. 2. The second call is used as a confirmation and will leave the contract without an owner.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner.

### setData :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#setdata) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner.
**Emitted events:** - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#setdatabatch) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner.
**Emitted events:** - [`DataChanged`](#datachanged) event. (on each iteration of setting data)
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#supportsinterface) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` _Checking if this contract supports the interface defined by the `bytes4` interface ID `interfaceId`._ Achieves the goal of [ERC-165] to detect supported interfaces and [LSP-17-ContractExtension] by checking if the interfaceId being queried is supported on another linked extension. If the contract doesn't support the `interfaceId`, it forwards the call to the `supportsInterface` extension according to [LSP-17-ContractExtension], and checks if the extension implements the interface defined by `interfaceId`. #### Parameters | Name | Type | Description | | ------------- | :------: | ------------------------------------------------------ | | `interfaceId` | `bytes4` | The interface ID to check if the contract supports it. | #### Returns | Name | Type | Description | | ---- | :----: | --------------------------------------------------------------------------------------------- | | `0` | `bool` | `true` if this contract implements the interface defined by `interfaceId`, `false` otherwise. |
### transferOwnership :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#transferownership) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address newOwner) external nonpayable; ``` _Transfer ownership initiated by `newOwner`._ Initiate the process of transferring ownership of the contract by setting the new owner as the pending owner. If the new owner is a contract that supports + implements LSP1, this will also attempt to notify the new owner that ownership has been transferred to them by calling the [`universalReceiver()`](#universalreceiver) function on the `newOwner` contract.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner. - When notifying the new owner via LSP1, the `typeId` used must be the `keccak256(...)` hash of [LSP0OwnershipTransferStarted]. - Pending owner cannot accept ownership in the same tx via the LSP1 hook.
#### Parameters | Name | Type | Description | | ---------- | :-------: | ----------------------------- | | `newOwner` | `address` | The address of the new owner. |
### universalReceiver :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#universalreceiver) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Function signature: `universalReceiver(bytes32,bytes)` - Function selector: `0x6bb56a14` ::: ```solidity function universalReceiver( bytes32 typeId, bytes receivedData ) external payable returns (bytes returnedValues); ``` _Notifying the contract by calling its `universalReceiver` function with the following information: typeId: `typeId`; data: `data`._ Achieves the goal of [LSP-1-UniversalReceiver] by allowing the account to be notified about incoming/outgoing transactions and enabling reactions to these actions. The reaction is achieved by having two external contracts ([LSP1UniversalReceiverDelegate]) that react on the whole transaction and on the specific typeId, respectively. The function performs the following steps: 1. Query the [ERC-725Y] storage with the data key [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]. - If there is an address stored under the data key, check if this address supports the LSP1 interfaceId. - If yes, call this address with the typeId and data (params), along with additional calldata consisting of 20 bytes of `msg.sender` and 32 bytes of `msg.value`. If not, continue the execution of the function. 2. Query the [ERC-725Y] storage with the data key [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX] + `bytes32(typeId)`. (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is an address stored under the data key, check if this address supports the LSP1 interfaceId. - If yes, call this address with the typeId and data (params), along with additional calldata consisting of 20 bytes of `msg.sender` and 32 bytes of `msg.value`. If not, continue the execution of the function.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event with the function parameters, call options, and the response of the UniversalReceiverDelegates (URD) contract that was called.
#### Parameters | Name | Type | Description | | -------------- | :-------: | -------------------------- | | `typeId` | `bytes32` | The type of call received. | | `receivedData` | `bytes` | The data received. | #### Returns | Name | Type | Description | | ---------------- | :-----: | ------------------------------------------------------------------------------------------------------- | | `returnedValues` | `bytes` | The ABI encoded return value of the LSP1UniversalReceiverDelegate call and the LSP1TypeIdDelegate call. |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_execute :::caution Warning Providing operation type DELEGATECALL (4) as argument will result in custom error [`ERC725X_UnknownOperationType(4)`](#erc725x_unknownoperationtype) ::: ```solidity function _execute( uint256 operationType, address target, uint256 value, bytes data ) internal nonpayable returns (bytes); ``` This function overrides the [`ERC725XCore`](#erc725xcore) internal [`_execute`](#_execute) function to disable operation type DELEGATECALL (4). #### Parameters | Name | Type | Description | | --------------- | :-------: | ------------------------------------------------------------------------------------------------------ | | `operationType` | `uint256` | The operation type used: CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3. | | `target` | `address` | The address of the EOA or smart contract. (unused if a contract is created via operation type 1 or 2). | | `value` | `uint256` | The amount of native tokens to transfer (in Wei). | | `data` | `bytes` | The call data, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. |
### \_executeBatch ```solidity function _executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) internal nonpayable returns (bytes[]); ``` check each `operationType` provided in the batch and perform the associated low-level opcode after checking for requirements (see [`executeBatch`](#executebatch)).
### \_executeCall ```solidity function _executeCall( address target, uint256 value, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level call (operation type = 0) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------- | | `target` | `address` | The address on which call is executed | | `value` | `uint256` | The value to be sent with the call | | `data` | `bytes` | The data to be sent with the call | #### Returns | Name | Type | Description | | -------- | :-----: | ---------------------- | | `result` | `bytes` | The data from the call |
### \_executeStaticCall ```solidity function _executeStaticCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level staticcall (operation type = 3) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------- | | `target` | `address` | The address on which staticcall is executed | | `data` | `bytes` | The data to be sent with the staticcall | #### Returns | Name | Type | Description | | -------- | :-----: | ------------------------------------- | | `result` | `bytes` | The data returned from the staticcall |
### \_executeDelegateCall :::caution Warning The `msg.value` should not be trusted for any method called with `operationType`: `DELEGATECALL` (4). ::: ```solidity function _executeDelegateCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level delegatecall (operation type = 4) #### Parameters | Name | Type | Description | | -------- | :-------: | --------------------------------------------- | | `target` | `address` | The address on which delegatecall is executed | | `data` | `bytes` | The data to be sent with the delegatecall | #### Returns | Name | Type | Description | | -------- | :-----: | --------------------------------------- | | `result` | `bytes` | The data returned from the delegatecall |
### \_deployCreate ```solidity function _deployCreate( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE` opcode (operation type = 1) #### Parameters | Name | Type | Description | | -------------- | :-------: | ---------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_deployCreate2 ```solidity function _deployCreate2( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE2` opcode (operation type = 2) #### Parameters | Name | Type | Description | | -------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) and a bytes32 salt | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` Write a `dataValue` to the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ```
**Emitted events:** - [`DataChanged`](#datachanged) event emitted after a successful `setData` call.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to write the associated `bytes` value to the store. | | `dataValue` | `bytes` | The `bytes` value to associate with the given `dataKey` in the ERC725Y storage. |
### \_transferOwnership ```solidity function _transferOwnership(address newOwner) internal nonpayable; ``` Set the pending owner of the contract and cancel any renounce ownership process that was previously started.
**Requirements:** - `newOwner` cannot be the address of the contract itself.
#### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------- | | `newOwner` | `address` | The address of the new pending owner. |
### \_acceptOwnership ```solidity function _acceptOwnership() internal nonpayable; ``` Set the pending owner of the contract as the new owner.
### \_renounceOwnership ```solidity function _renounceOwnership() internal nonpayable; ``` Initiate or confirm the process of renouncing ownership after a specific delay of blocks have passed.
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0).
### \_fallbackLSP17Extendable :::tip Hint This function does not forward to the extension contract the `msg.value` received by the contract that inherits `LSP17Extendable`. If you would like to forward the `msg.value` to the extension contract, you can override the code of this internal function as follow: ```solidity (bool success, bytes memory result) = extension.call{value: msg.value}( abi.encodePacked(callData, msg.sender, msg.value) ); ``` ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the `address(0)` will be returned. Forwards the value if the extension is payable. Reverts if there is no extension for the function being called, except for the `bytes4(0)` function selector, which passes even if there is no extension for it. If there is an extension for the function selector being called, it calls the extension with the `CALL` opcode, passing the `msg.data` appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the `msg.value`.
### \_validateAndIdentifyCaller ```solidity function _validateAndIdentifyCaller() internal view returns (bool isURD); ``` Internal method restricting the call to the owner of the contract and the UniversalReceiverDelegate
## Events ### ContractCreated :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#contractcreated) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Event signature: `ContractCreated(uint256,address,uint256,bytes32)` - Event topic hash: `0xa1fb700aaee2ae4a2ff6f91ce7eba292f89c2f5488b8ec4c5c5c8150692595c3` ::: ```solidity event ContractCreated( uint256 indexed operationType, address indexed contractAddress, uint256 value, bytes32 indexed salt ); ``` _Deployed new contract at address `contractAddress` and funded with `value` wei (deployed using opcode: `operationType`)._ Emitted when a new contract was created and deployed. #### Parameters | Name | Type | Description | | ------------------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The opcode used to deploy the contract (`CREATE` or `CREATE2`). | | `contractAddress` **`indexed`** | `address` | The created contract address. | | `value` | `uint256` | The amount of native tokens (in Wei) sent to fund the created contract on deployment. | | `salt` **`indexed`** | `bytes32` | The salt used to deterministically deploy the contract (`CREATE2` only). If `CREATE` opcode is used, the salt value will be `bytes32(0)`. |
### DataChanged :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#datachanged) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Executed :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#executed) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Event signature: `Executed(uint256,address,uint256,bytes4)` - Event topic hash: `0x4810874456b8e6487bd861375cf6abd8e1c8bb5858c8ce36a86a04dabfac199e` ::: ```solidity event Executed( uint256 indexed operationType, address indexed target, uint256 value, bytes4 indexed selector ); ``` _Called address `target` using `operationType` with `value` wei and `data`._ Emitted when calling an address `target` (EOA or contract) with `value`. #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ---------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The low-level call opcode used to call the `target` address (`CALL`, `STATICALL` or `DELEGATECALL`). | | `target` **`indexed`** | `address` | The address to call. `target` will be unused if a contract is created (operation types 1 and 2). | | `value` | `uint256` | The amount of native tokens transferred along the call (in Wei). | | `selector` **`indexed`** | `bytes4` | The first 4 bytes (= function selector) of the data sent with the call. |
### OwnershipRenounced :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#ownershiprenounced) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Event signature: `OwnershipRenounced()` - Event topic hash: `0xd1f66c3d2bc1993a86be5e3d33709d98f0442381befcedd29f578b9b2506b1ce` ::: ```solidity event OwnershipRenounced(); ``` _Successfully renounced ownership of the contract. This contract is now owned by anyone, it's owner is `address(0)`._ Emitted when the ownership of the contract has been renounced.
### OwnershipTransferStarted :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#ownershiptransferstarted) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Event signature: `OwnershipTransferStarted(address,address)` - Event topic hash: `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` ::: ```solidity event OwnershipTransferStarted( address indexed previousOwner, address indexed newOwner ); ``` _The transfer of ownership of the contract was initiated. Pending new owner set to: `newOwner`._ Emitted when [`transferOwnership(..)`](#transferownership) was called and the first step of transferring ownership completed successfully which leads to [`pendingOwner`](#pendingowner) being updated. #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ---------------------------------- | | `previousOwner` **`indexed`** | `address` | The address of the previous owner. | | `newOwner` **`indexed`** | `address` | The address of the new owner. |
### OwnershipTransferred :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#ownershiptransferred) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### RenounceOwnershipStarted :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#renounceownershipstarted) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Event signature: `RenounceOwnershipStarted()` - Event topic hash: `0x81b7f830f1f0084db6497c486cbe6974c86488dcc4e3738eab94ab6d6b1653e7` ::: ```solidity event RenounceOwnershipStarted(); ``` _Ownership renouncement initiated._ Emitted when starting the [`renounceOwnership(..)`](#renounceownership) 2-step process.
### UniversalReceiver :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#universalreceiver) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Event signature: `UniversalReceiver(address,uint256,bytes32,bytes,bytes)` - Event topic hash: `0x9c3ba68eb5742b8e3961aea0afc7371a71bf433c8a67a831803b64c064a178c2` ::: ```solidity event UniversalReceiver( address indexed from, uint256 indexed value, bytes32 indexed typeId, bytes receivedData, bytes returnedValue ); ``` \*Address `from` called the `universalReceiver(...)` function while sending `value` LYX. Notification type (typeId): `typeId` - Data received: `receivedData`.\* Emitted when the [`universalReceiver`](#universalreceiver) function was called with a specific `typeId` and some `receivedData` #### Parameters | Name | Type | Description | | ---------------------- | :-------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` **`indexed`** | `address` | The address of the EOA or smart contract that called the [`universalReceiver(...)`](#universalreceiver) function. | | `value` **`indexed`** | `uint256` | The amount sent to the [`universalReceiver(...)`](#universalreceiver) function. | | `typeId` **`indexed`** | `bytes32` | A `bytes32` unique identifier (= _"hook"_)that describe the type of notification, information or transaction received by the contract. Can be related to a specific standard or a hook. | | `receivedData` | `bytes` | Any arbitrary data that was sent to the [`universalReceiver(...)`](#universalreceiver) function. | | `returnedValue` | `bytes` | The value returned by the [`universalReceiver(...)`](#universalreceiver) function. |
## Errors ### ERC725X_ContractDeploymentFailed :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725x_contractdeploymentfailed) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725X_ContractDeploymentFailed()` - Error hash: `0x0b07489b` ::: ```solidity error ERC725X_ContractDeploymentFailed(); ``` Reverts when contract deployment failed via [`execute`](#execute) or [`executeBatch`](#executebatch) functions, This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_CreateOperationsRequireEmptyRecipientAddress :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725x_createoperationsrequireemptyrecipientaddress) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725X_CreateOperationsRequireEmptyRecipientAddress()` - Error hash: `0x3041824a` ::: ```solidity error ERC725X_CreateOperationsRequireEmptyRecipientAddress(); ``` Reverts when passing a `to` address that is not `address(0)` (= address zero) while deploying a contract via [`execute`](#execute) or [`executeBatch`](#executebatch) functions. This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_ExecuteParametersEmptyArray :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725x_executeparametersemptyarray) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725X_ExecuteParametersEmptyArray()` - Error hash: `0xe9ad2b5f` ::: ```solidity error ERC725X_ExecuteParametersEmptyArray(); ``` Reverts when one of the array parameter provided to the [`executeBatch`](#executebatch) function is an empty array.
### ERC725X_ExecuteParametersLengthMismatch :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725x_executeparameterslengthmismatch) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725X_ExecuteParametersLengthMismatch()` - Error hash: `0x3ff55f4d` ::: ```solidity error ERC725X_ExecuteParametersLengthMismatch(); ``` Reverts when there is not the same number of elements in the `operationTypes`, `targets` addresses, `values`, and `datas` array parameters provided when calling the [`executeBatch`](#executebatch) function.
### ERC725X_InsufficientBalance :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725x_insufficientbalance) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725X_InsufficientBalance(uint256,uint256)` - Error hash: `0x0df9a8f8` ::: ```solidity error ERC725X_InsufficientBalance(uint256 balance, uint256 value); ``` Reverts when trying to send more native tokens `value` than available in current `balance`. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `balance` | `uint256` | The balance of native tokens of the ERC725X smart contract. | | `value` | `uint256` | The amount of native tokens sent via `ERC725X.execute(...)`/`ERC725X.executeBatch(...)` that is greater than the contract's `balance`. |
### ERC725X_MsgValueDisallowedInStaticCall :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725x_msgvaluedisallowedinstaticcall) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725X_MsgValueDisallowedInStaticCall()` - Error hash: `0x72f2bc6a` ::: ```solidity error ERC725X_MsgValueDisallowedInStaticCall(); ``` Reverts when trying to send native tokens (`value` / `values[]` parameter of [`execute`](#execute) or [`executeBatch`](#executebatch) functions) while making a `staticcall` (`operationType == 3`). Sending native tokens via `staticcall` is not allowed because it is a state changing operation.
### ERC725X_NoContractBytecodeProvided :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725x_nocontractbytecodeprovided) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725X_NoContractBytecodeProvided()` - Error hash: `0xb81cd8d9` ::: ```solidity error ERC725X_NoContractBytecodeProvided(); ``` Reverts when no contract bytecode was provided as parameter when trying to deploy a contract via [`execute`](#execute) or [`executeBatch`](#executebatch). This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_UnknownOperationType :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725x_unknownoperationtype) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725X_UnknownOperationType(uint256)` - Error hash: `0x7583b3bc` ::: ```solidity error ERC725X_UnknownOperationType(uint256 operationTypeProvided); ``` Reverts when the `operationTypeProvided` is none of the default operation types available. (CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4) #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ------------------------------------------------------------------------------------------------------ | | `operationTypeProvided` | `uint256` | The unrecognised operation type number provided to `ERC725X.execute(...)`/`ERC725X.executeBatch(...)`. |
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### ERC725Y_MsgValueDisallowed :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#erc725y_msgvaluedisallowed) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `ERC725Y_MsgValueDisallowed()` - Error hash: `0xf36ba737` ::: ```solidity error ERC725Y_MsgValueDisallowed(); ``` Reverts when sending value to the [`setData`](#setdata) or [`setDataBatch`](#setdatabatch) function.
### LSP14CallerNotPendingOwner :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#lsp14callernotpendingowner) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `LSP14CallerNotPendingOwner(address)` - Error hash: `0x451e4528` ::: ```solidity error LSP14CallerNotPendingOwner(address caller); ``` Reverts when the `caller` that is trying to accept ownership of the contract is not the pending owner. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------- | | `caller` | `address` | The address that tried to accept ownership. |
### LSP14CannotTransferOwnershipToSelf :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#lsp14cannottransferownershiptoself) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `LSP14CannotTransferOwnershipToSelf()` - Error hash: `0xe052a6f8` ::: ```solidity error LSP14CannotTransferOwnershipToSelf(); ``` _Cannot transfer ownership to the address of the contract itself._ Reverts when trying to transfer ownership to the `address(this)`.
### LSP14MustAcceptOwnershipInSeparateTransaction :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#lsp14mustacceptownershipinseparatetransaction) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `LSP14MustAcceptOwnershipInSeparateTransaction()` - Error hash: `0x5758dd07` ::: ```solidity error LSP14MustAcceptOwnershipInSeparateTransaction(); ``` _Cannot accept ownership in the same transaction with [`transferOwnership(...)`](#transferownership)._ Reverts when pending owner accept ownership in the same transaction of transferring ownership.
### LSP14NotInRenounceOwnershipInterval :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#lsp14notinrenounceownershipinterval) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `LSP14NotInRenounceOwnershipInterval(uint256,uint256)` - Error hash: `0x1b080942` ::: ```solidity error LSP14NotInRenounceOwnershipInterval( uint256 renounceOwnershipStart, uint256 renounceOwnershipEnd ); ``` _Cannot confirm ownership renouncement yet. The ownership renouncement is allowed from: `renounceOwnershipStart` until: `renounceOwnershipEnd`._ Reverts when trying to renounce ownership before the initial confirmation delay. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ----------------------------------------------------------------------- | | `renounceOwnershipStart` | `uint256` | The start timestamp when one can confirm the renouncement of ownership. | | `renounceOwnershipEnd` | `uint256` | The end timestamp when one can confirm the renouncement of ownership. |
### LSP1DelegateNotAllowedToSetDataKey :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#lsp1delegatenotallowedtosetdatakey) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `LSP1DelegateNotAllowedToSetDataKey(bytes32)` - Error hash: `0x199611f1` ::: ```solidity error LSP1DelegateNotAllowedToSetDataKey(bytes32 dataKey); ``` _The `LSP1UniversalReceiverDelegate` is not allowed to set the following data key: `dataKey`._ Reverts when the Vault version of [LSP1UniversalReceiverDelegate] sets @lukso/lsp1-contracts/6/17 Data Keys. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------------------------------------------------------- | | `dataKey` | `bytes32` | The data key that the Vault version of [LSP1UniversalReceiverDelegate] is not allowed to set. |
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#noextensionfoundforfunctionselector) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
### OwnableCallerNotTheOwner :::note References - Specification details: [**LSP-9-Vault**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md#ownablecallernottheowner) - Solidity implementation: [`LSP9Vault.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts/contracts/LSP9Vault.sol) - Error signature: `OwnableCallerNotTheOwner(address)` - Error hash: `0xbf1169c5` ::: ```solidity error OwnableCallerNotTheOwner(address callerAddress); ``` Reverts when only the owner is allowed to call the function. #### Parameters | Name | Type | Description | | --------------- | :-------: | ---------------------------------------- | | `callerAddress` | `address` | The address that tried to make the call. |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- # UniversalProfile :::info Standard Specifications [`UniversalProfile`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md) [`UniversalProfile`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md) ::: :::info Solidity implementation [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) ::: > implementation of a LUKSO's Universal Profile based on LSP3 Implementation of the ERC725Account + LSP1 universalReceiver ## Public Methods Public methods are accessible externally from users, allowing interaction with this function from dApps or other smart contracts. When marked as 'public', a method can be called both externally and internally, on the other hand, when marked as 'external', a method can only be called externally. ### constructor :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#constructor) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) ::: ```solidity constructor(address initialOwner); ``` _Deploying a UniversalProfile contract with owner set to address `initialOwner`._ Set `initialOwner` as the contract owner and the `SupportedStandards:LSP3Profile` data key in the ERC725Y data key/value store. - The `constructor` is payable and allows funding the contract on deployment. - The `initialOwner` will then be allowed to call protected functions marked with the `onlyOwner` modifier.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event when funding the contract on deployment. - [`OwnershipTransferred`](#ownershiptransferred) event when `initialOwner` is set as the contract [`owner`](#owner). - [`DataChanged`](#datachanged) event when setting the [`_LSP3_SUPPORTED_STANDARDS_KEY`](#_lsp3_supported_standards_key).
#### Parameters | Name | Type | Description | | -------------- | :-------: | ------------------------- | | `initialOwner` | `address` | the owner of the contract |
### fallback :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#fallback) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) ::: ```solidity fallback() external payable; ```
### receive :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#receive) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) ::: ```solidity receive() external payable; ```
### RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#renounce_ownership_confirmation_delay) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY()` - Function selector: `0xead3fbdf` ::: ```solidity function RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY() external view returns (uint256); ``` #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `uint256` | - |
### RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#renounce_ownership_confirmation_period) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD()` - Function selector: `0x01bfba61` ::: ```solidity function RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD() external view returns (uint256); ``` #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `uint256` | - |
### VERSION :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#version) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `VERSION()` - Function selector: `0xffa1ad74` ::: ```solidity function VERSION() external view returns (string); ``` _Contract version._ #### Returns | Name | Type | Description | | ---- | :------: | ----------- | | `0` | `string` | - |
### acceptOwnership :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `acceptOwnership()` - Function selector: `0x79ba5097` ::: ```solidity function acceptOwnership() external nonpayable; ``` _`msg.sender` is accepting ownership of contract: `address(this)`._ Transfer ownership of the contract from the current [`owner()`](#owner) to the [`pendingOwner()`](#pendingowner). Once this function is called: - The current [`owner()`](#owner) will lose access to the functions restricted to the [`owner()`](#owner) only. - The [`pendingOwner()`](#pendingowner) will gain access to the functions restricted to the [`owner()`](#owner) only.
**Requirements:** - Only the [`pendingOwner`](#pendingowner) can call this function. - When notifying the previous owner via LSP1, the typeId used must be the `keccak256(...)` hash of [LSP0OwnershipTransferred_SenderNotification]. - When notifying the new owner via LSP1, the typeId used must be the `keccak256(...)` hash of [LSP0OwnershipTransferred_RecipientNotification].

### batchCalls :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#batchcalls) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `batchCalls(bytes[])` - Function selector: `0x6963d438` ::: :::info It's not possible to send value along the functions call due to the use of `delegatecall`. ::: ```solidity function batchCalls(bytes[] data) external nonpayable returns (bytes[] results); ``` _Executing the following batch of abi-encoded function calls on the contract: `data`._ Allows a caller to batch different function calls in one call. Perform a `delegatecall` on self, to call different functions with preserving the context. #### Parameters | Name | Type | Description | | ------ | :-------: | -------------------------------------------------------------------- | | `data` | `bytes[]` | An array of ABI encoded function calls to be called on the contract. | #### Returns | Name | Type | Description | | --------- | :-------: | ---------------------------------------------------------------- | | `results` | `bytes[]` | An array of abi-encoded data returned by the functions executed. |
### execute :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#execute) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `execute(uint256,address,uint256,bytes)` - Function selector: `0x44c028fe` ::: ```solidity function execute( uint256 operationType, address target, uint256 value, bytes data ) external payable returns (bytes); ``` _Calling address `target` using `operationType`, transferring `value` wei and data: `data`._ Generic executor function to: - send native tokens to any address. - interact with any contract by passing an abi-encoded function call in the `data` parameter. - deploy a contract by providing its creation bytecode in the `data` parameter.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner. - If a `value` is provided, the contract must have at least this amount in its balance to execute successfully. - If the operation type is `CREATE` (1) or `CREATE2` (2), `target` must be `address(0)`. - If the operation type is `STATICCALL` (3) or `DELEGATECALL` (4), `value` transfer is disallowed and must be 0.
**Emitted events:** - [`Executed`](#executed) event for each call that uses under `operationType`: `CALL` (0), `STATICCALL` (3) and `DELEGATECALL` (4). - [`ContractCreated`](#contractcreated) event, when a contract is created under `operationType`: `CREATE` (1) and `CREATE2` (2). - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens.
#### Parameters | Name | Type | Description | | --------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `operationType` | `uint256` | The operation type used: CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4 | | `target` | `address` | The address of the EOA or smart contract. (unused if a contract is created via operation type 1 or 2) | | `value` | `uint256` | The amount of native tokens to transfer (in Wei) | | `data` | `bytes` | The call data, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-----: | ----------- | | `0` | `bytes` | - |
### executeBatch :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#executebatch) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `executeBatch(uint256[],address[],uint256[],bytes[])` - Function selector: `0x31858452` ::: :::caution Warning - The `msg.value` should not be trusted for any method called within the batch with `operationType`: `DELEGATECALL` (4). ::: ```solidity function executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) external payable returns (bytes[]); ``` _Calling multiple addresses `targets` using `operationsType`, transferring `values` wei and data: `datas`._ Batch executor function that behaves the same as [`execute`](#execute) but allowing multiple operations in the same transaction.
**Requirements:** - The length of the parameters provided must be equal. - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner. - If a `value` is provided, the contract must have at least this amount in its balance to execute successfully. - If the operation type is `CREATE` (1) or `CREATE2` (2), `target` must be `address(0)`. - If the operation type is `STATICCALL` (3) or `DELEGATECALL` (4), `value` transfer is disallowed and must be 0.
**Emitted events:** - [`Executed`](#executed) event for each call that uses under `operationType`: `CALL` (0), `STATICCALL` (3) and `DELEGATECALL` (4). (each iteration) - [`ContractCreated`](#contractcreated) event, when a contract is created under `operationType`: `CREATE` (1) and `CREATE2` (2) (each iteration) - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens.
#### Parameters | Name | Type | Description | | ---------------- | :---------: | --------------------------------------------------------------------------------------------------------------- | | `operationsType` | `uint256[]` | The list of operations type used: `CALL = 0`; `CREATE = 1`; `CREATE2 = 2`; `STATICCALL = 3`; `DELEGATECALL = 4` | | `targets` | `address[]` | The list of addresses to call. `targets` will be unused if a contract is created (operation types 1 and 2). | | `values` | `uint256[]` | The list of native token amounts to transfer (in Wei). | | `datas` | `bytes[]` | The list of calldata, or the creation bytecode of the contract to deploy if `operationType` is `1` or `2`. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `bytes[]` | - |
### getData :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#getdata) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `getData(bytes32)` - Function selector: `0x54f6127f` ::: ```solidity function getData(bytes32 dataKey) external view returns (bytes dataValue); ``` _Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`._ Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. #### Parameters | Name | Type | Description | | --------- | :-------: | --------------------------------------------- | | `dataKey` | `bytes32` | The data key for which to retrieve the value. | #### Returns | Name | Type | Description | | ----------- | :-----: | ---------------------------------------------------- | | `dataValue` | `bytes` | The bytes value stored under the specified data key. |
### getDataBatch :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#getdatabatch) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `getDataBatch(bytes32[])` - Function selector: `0xdedff9c6` ::: ```solidity function getDataBatch( bytes32[] dataKeys ) external view returns (bytes[] dataValues); ``` _Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`._ Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. #### Parameters | Name | Type | Description | | ---------- | :---------: | ------------------------------------------ | | `dataKeys` | `bytes32[]` | The array of keys which values to retrieve | #### Returns | Name | Type | Description | | ------------ | :-------: | ----------------------------------------- | | `dataValues` | `bytes[]` | The array of data stored at multiple keys |
### isValidSignature :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#isvalidsignature) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `isValidSignature(bytes32,bytes)` - Function selector: `0x1626ba7e` ::: :::caution Warning This function does not enforce by default the inclusion of the address of this contract in the signature digest. It is recommended that protocols or applications using this contract include the targeted address (= this contract) in the data to sign. To ensure that a signature is valid for a specific LSP0ERC725Account and prevent signatures from the same EOA to be replayed across different LSP0ERC725Accounts. ::: ```solidity function isValidSignature( bytes32 dataHash, bytes signature ) external view returns (bytes4 returnedStatus); ``` _Achieves the goal of [EIP-1271] by validating signatures of smart contracts according to their own logic._ Handles two cases: 1. If the owner is an EOA, recovers an address from the hash and the signature provided: - Returns the `_ERC1271_SUCCESSVALUE` if the address recovered is the same as the owner, indicating that it was a valid signature. - If the address is different, it returns the `_ERC1271_FAILVALUE` indicating that the signature is not valid. 2. If the owner is a smart contract, it forwards the call of [`isValidSignature()`](#isvalidsignature) to the owner contract: - If the contract fails or returns the `_ERC1271_FAILVALUE`, the [`isValidSignature()`](#isvalidsignature) on the account returns the `_ERC1271_FAILVALUE`, indicating that the signature is not valid. - If the [`isValidSignature()`](#isvalidsignature) on the owner returned the `_ERC1271_SUCCESSVALUE`, the [`isValidSignature()`](#isvalidsignature) on the account returns the `_ERC1271_SUCCESSVALUE`, indicating that it's a valid signature. #### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------------------------ | | `dataHash` | `bytes32` | The hash of the data to be validated. | | `signature` | `bytes` | A signature that can validate the previous parameter (Hash). | #### Returns | Name | Type | Description | | ---------------- | :------: | ----------------------------------------------------------------- | | `returnedStatus` | `bytes4` | A `bytes4` value that indicates if the signature is valid or not. |
### owner :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#owner) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `owner()` - Function selector: `0x8da5cb5b` ::: ```solidity function owner() external view returns (address); ``` Returns the address of the current owner. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### pendingOwner :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#pendingowner) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `pendingOwner()` - Function selector: `0xe30c3978` ::: :::info If no ownership transfer is in progress, the pendingOwner will be `address(0).`. ::: ```solidity function pendingOwner() external view returns (address); ``` The address that ownership of the contract is transferred to. This address may use [`acceptOwnership()`](#acceptownership) to gain ownership of the contract. #### Returns | Name | Type | Description | | ---- | :-------: | ----------- | | `0` | `address` | - |
### renounceOwnership :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#renounceownership) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `renounceOwnership()` - Function selector: `0x715018a6` ::: :::danger Leaves the contract without an owner. Once ownership of the contract has been renounced, any functions that are restricted to be called by the owner or an address allowed by the owner will be permanently inaccessible, making these functions not callable anymore and unusable. ::: ```solidity function renounceOwnership() external nonpayable; ``` _`msg.sender` is renouncing ownership of contract `address(this)`._ Renounce ownership of the contract in a 2-step process. 1. The first call will initiate the process of renouncing ownership. 2. The second call is used as a confirmation and will leave the contract without an owner.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner.

### setData :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#setdata) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `setData(bytes32,bytes)` - Function selector: `0x7f23690c` ::: ```solidity function setData(bytes32 dataKey, bytes dataValue) external payable; ``` _Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`._ Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. The function is marked as payable to enable flexibility on child contracts. For instance to implement a fee mechanism for setting specific data.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens. - [`DataChanged`](#datachanged) event.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------ | | `dataKey` | `bytes32` | The data key for which to set a new value. | | `dataValue` | `bytes` | The new bytes value to set. |
### setDataBatch :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#setdatabatch) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `setDataBatch(bytes32[],bytes[])` - Function selector: `0x97902421` ::: ```solidity function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; ``` _Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`._ Batch data setting function that behaves the same as [`setData`](#setdata) but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) event when receiving native tokens. - [`DataChanged`](#datachanged) event. (on each iteration of setting data)
#### Parameters | Name | Type | Description | | ------------ | :---------: | ---------------------------------------------------- | | `dataKeys` | `bytes32[]` | An array of data keys to set bytes values for. | | `dataValues` | `bytes[]` | An array of bytes values to set for each `dataKeys`. |
### supportsInterface :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#supportsinterface) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `supportsInterface(bytes4)` - Function selector: `0x01ffc9a7` ::: ```solidity function supportsInterface(bytes4 interfaceId) external view returns (bool); ``` _Checking if this contract supports the interface defined by the `bytes4` interface ID `interfaceId`._ Achieves the goal of [ERC-165] to detect supported interfaces and [LSP-17-ContractExtension] by checking if the interfaceId being queried is supported on another linked extension. If the contract doesn't support the `interfaceId`, it forwards the call to the `supportsInterface` extension according to [LSP-17-ContractExtension], and checks if the extension implements the interface defined by `interfaceId`. #### Parameters | Name | Type | Description | | ------------- | :------: | ------------------------------------------------------ | | `interfaceId` | `bytes4` | The interface ID to check if the contract supports it. | #### Returns | Name | Type | Description | | ---- | :----: | --------------------------------------------------------------------------------------------- | | `0` | `bool` | `true` if this contract implements the interface defined by `interfaceId`, `false` otherwise. |
### transferOwnership :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `transferOwnership(address)` - Function selector: `0xf2fde38b` ::: ```solidity function transferOwnership(address pendingNewOwner) external nonpayable; ``` _Transfer ownership initiated by `newOwner`._ Initiate the process of transferring ownership of the contract by setting the new owner as the pending owner. If the new owner is a contract that supports + implements LSP1, this will also attempt to notify the new owner that ownership has been transferred to them by calling the [`universalReceiver()`](#universalreceiver) function on the `newOwner` contract.
**Requirements:** - Can be only called by the [`owner`](#owner) or by an authorised address that pass the verification check performed on the owner. - When notifying the new owner via LSP1, the `typeId` used must be the `keccak256(...)` hash of [LSP0OwnershipTransferStarted]. - Pending owner cannot accept ownership in the same tx via the LSP1 hook.
#### Parameters | Name | Type | Description | | ----------------- | :-------: | ----------- | | `pendingNewOwner` | `address` | - |
### universalReceiver :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#universalreceiver) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Function signature: `universalReceiver(bytes32,bytes)` - Function selector: `0x6bb56a14` ::: ```solidity function universalReceiver( bytes32 typeId, bytes receivedData ) external payable returns (bytes returnedValues); ``` _Notifying the contract by calling its `universalReceiver` function with the following information: typeId: `typeId`; data: `data`._ Achieves the goal of [LSP-1-UniversalReceiver] by allowing the account to be notified about incoming/outgoing transactions and enabling reactions to these actions. The reaction is achieved by having two external contracts ([LSP1UniversalReceiverDelegate]) that react on the whole transaction and on the specific typeId, respectively. The function performs the following steps: 1. Query the [ERC-725Y] storage with the data key [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]. - If there is an address stored under the data key, check if this address supports the LSP1 interfaceId. - If yes, call this address with the typeId and data (params), along with additional calldata consisting of 20 bytes of `msg.sender` and 32 bytes of `msg.value`. If not, continue the execution of the function. 2. Query the [ERC-725Y] storage with the data key [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX] + `bytes32(typeId)`. (Check [LSP-2-ERC725YJSONSchema] for encoding the data key) - If there is an address stored under the data key, check if this address supports the LSP1 interfaceId. - If yes, call this address with the typeId and data (params), along with additional calldata consisting of 20 bytes of `msg.sender` and 32 bytes of `msg.value`. If not, continue the execution of the function. This function delegates internally the handling of native tokens to the [`universalReceiver`](#universalreceiver) function itself passing `_TYPEID_LSP0_VALUE_RECEIVED` as typeId and the calldata as received data.
**Emitted events:** - [`UniversalReceiver`](#universalreceiver) when receiving native tokens. - [`UniversalReceiver`](#universalreceiver) event with the function parameters, call options, and the response of the UniversalReceiverDelegates (URD) contract that was called.
#### Parameters | Name | Type | Description | | -------------- | :-------: | -------------------------- | | `typeId` | `bytes32` | The type of call received. | | `receivedData` | `bytes` | The data received. | #### Returns | Name | Type | Description | | ---------------- | :-----: | ------------------------------------------------------------------------------------------------------- | | `returnedValues` | `bytes` | The ABI encoded return value of the LSP1UniversalReceiverDelegate call and the LSP1TypeIdDelegate call. |
## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### \_checkOwner ```solidity function _checkOwner() internal view; ``` Throws if the sender is not the owner.
### \_setOwner ```solidity function _setOwner(address newOwner) internal nonpayable; ``` Changes the owner if `newOwner` and oldOwner are different This pattern is useful in inheritance.
### \_execute ```solidity function _execute( uint256 operationType, address target, uint256 value, bytes data ) internal nonpayable returns (bytes); ``` check the `operationType` provided and perform the associated low-level opcode after checking for requirements (see [`execute`](#execute)).
### \_executeBatch ```solidity function _executeBatch( uint256[] operationsType, address[] targets, uint256[] values, bytes[] datas ) internal nonpayable returns (bytes[]); ``` check each `operationType` provided in the batch and perform the associated low-level opcode after checking for requirements (see [`executeBatch`](#executebatch)).
### \_executeCall ```solidity function _executeCall( address target, uint256 value, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level call (operation type = 0) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------- | | `target` | `address` | The address on which call is executed | | `value` | `uint256` | The value to be sent with the call | | `data` | `bytes` | The data to be sent with the call | #### Returns | Name | Type | Description | | -------- | :-----: | ---------------------- | | `result` | `bytes` | The data from the call |
### \_executeStaticCall ```solidity function _executeStaticCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level staticcall (operation type = 3) #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------- | | `target` | `address` | The address on which staticcall is executed | | `data` | `bytes` | The data to be sent with the staticcall | #### Returns | Name | Type | Description | | -------- | :-----: | ------------------------------------- | | `result` | `bytes` | The data returned from the staticcall |
### \_executeDelegateCall :::caution Warning The `msg.value` should not be trusted for any method called with `operationType`: `DELEGATECALL` (4). ::: ```solidity function _executeDelegateCall( address target, bytes data ) internal nonpayable returns (bytes result); ``` Perform low-level delegatecall (operation type = 4) #### Parameters | Name | Type | Description | | -------- | :-------: | --------------------------------------------- | | `target` | `address` | The address on which delegatecall is executed | | `data` | `bytes` | The data to be sent with the delegatecall | #### Returns | Name | Type | Description | | -------- | :-----: | --------------------------------------- | | `result` | `bytes` | The data returned from the delegatecall |
### \_deployCreate ```solidity function _deployCreate( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE` opcode (operation type = 1) #### Parameters | Name | Type | Description | | -------------- | :-------: | ---------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_deployCreate2 ```solidity function _deployCreate2( uint256 value, bytes creationCode ) internal nonpayable returns (bytes newContract); ``` Deploy a contract using the `CREATE2` opcode (operation type = 2) #### Parameters | Name | Type | Description | | -------------- | :-------: | ----------------------------------------------------------------------------------------------------- | | `value` | `uint256` | The value to be sent to the contract created | | `creationCode` | `bytes` | The contract creation bytecode to deploy appended with the constructor argument(s) and a bytes32 salt | #### Returns | Name | Type | Description | | ------------- | :-----: | -------------------------------------------- | | `newContract` | `bytes` | The address of the contract created as bytes |
### \_getData ```solidity function _getData(bytes32 dataKey) internal view returns (bytes dataValue); ``` Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ``` #### Parameters | Name | Type | Description | | --------- | :-------: | ----------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to read the associated `bytes` value from the store. | #### Returns | Name | Type | Description | | ----------- | :-----: | ----------------------------------------------------------------------------- | | `dataValue` | `bytes` | The `bytes` value associated with the given `dataKey` in the ERC725Y storage. |
### \_setData ```solidity function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; ``` Write a `dataValue` to the underlying ERC725Y storage, represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. ```solidity mapping(bytes32 => bytes) _store ```
**Emitted events:** - [`DataChanged`](#datachanged) event emitted after a successful `setData` call.
#### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------------------------------------------- | | `dataKey` | `bytes32` | A bytes32 data key to write the associated `bytes` value to the store. | | `dataValue` | `bytes` | The `bytes` value to associate with the given `dataKey` in the ERC725Y storage. |
### \_transferOwnership ```solidity function _transferOwnership(address newOwner) internal nonpayable; ``` Set the pending owner of the contract and cancel any renounce ownership process that was previously started.
**Requirements:** - `newOwner` cannot be the address of the contract itself.
#### Parameters | Name | Type | Description | | ---------- | :-------: | ------------------------------------- | | `newOwner` | `address` | The address of the new pending owner. |
### \_acceptOwnership ```solidity function _acceptOwnership() internal nonpayable; ``` Set the pending owner of the contract as the new owner.
### \_renounceOwnership ```solidity function _renounceOwnership() internal nonpayable; ``` Initiate or confirm the process of renouncing ownership after a specific delay of blocks have passed.
### \_supportsInterfaceInERC165Extension ```solidity function _supportsInterfaceInERC165Extension( bytes4 interfaceId ) internal view returns (bool); ``` Returns whether the interfaceId being checked is supported in the extension of the [`supportsInterface`](#supportsinterface) selector. To be used by extendable contracts wishing to extend the ERC165 interfaceIds originally supported by reading whether the interfaceId queried is supported in the `supportsInterface` extension if the extension is set, if not it returns false.
### \_getExtensionAndForwardValue ```solidity function _getExtensionAndForwardValue( bytes4 functionSelector ) internal view returns (address, bool); ``` Returns the extension address and the boolean indicating whether to forward the value received to the extension, stored under the following data key: - [`_LSP17_EXTENSION_PREFIX`](#_lsp17_extension_prefix) + `` (Check [LSP2-ERC725YJSONSchema] for encoding the data key). - If no extension is stored, returns the address(0). - If the stored value is 20 bytes, return false for the boolean
### \_fallbackLSP17Extendable :::tip Hint If you would like to forward the `msg.value` to the extension contract, you should store an additional `0x01` byte after the address of the extension under the corresponding LSP17 data key. ::: ```solidity function _fallbackLSP17Extendable( bytes callData ) internal nonpayable returns (bytes); ``` Forwards the call to an extension mapped to a function selector. Calls [`_getExtensionAndForwardValue`](#_getextensionandforwardvalue) to get the address of the extension mapped to the function selector being called on the account. If there is no extension, the `address(0)` will be returned. Forwards the value sent with the call to the extension if the function selector is mapped to a payable extension. Reverts if there is no extension for the function being called, except for the `bytes4(0)` function selector, which passes even if there is no extension for it. If there is an extension for the function selector being called, it calls the extension with the `CALL` opcode, passing the `msg.data` appended with the 20 bytes of the [`msg.sender`](#msg.sender) and 32 bytes of the `msg.value`.
### \_verifyCall ```solidity function _verifyCall( address logicVerifier ) internal nonpayable returns (bool verifyAfter); ``` Calls [`lsp20VerifyCall`](#lsp20verifycall) function on the logicVerifier.
### \_verifyCallResult ```solidity function _verifyCallResult( address logicVerifier, bytes callResult ) internal nonpayable; ``` Calls [`lsp20VerifyCallResult`](#lsp20verifycallresult) function on the logicVerifier.
### \_revertWithLSP20DefaultError ```solidity function _revertWithLSP20DefaultError( bool postCall, bytes returnedData ) internal pure; ```
## Events ### ContractCreated :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#contractcreated) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Event signature: `ContractCreated(uint256,address,uint256,bytes32)` - Event topic hash: `0xa1fb700aaee2ae4a2ff6f91ce7eba292f89c2f5488b8ec4c5c5c8150692595c3` ::: ```solidity event ContractCreated( uint256 indexed operationType, address indexed contractAddress, uint256 value, bytes32 indexed salt ); ``` _Deployed new contract at address `contractAddress` and funded with `value` wei (deployed using opcode: `operationType`)._ Emitted when a new contract was created and deployed. #### Parameters | Name | Type | Description | | ------------------------------- | :-------: | ----------------------------------------------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The opcode used to deploy the contract (`CREATE` or `CREATE2`). | | `contractAddress` **`indexed`** | `address` | The created contract address. | | `value` | `uint256` | The amount of native tokens (in Wei) sent to fund the created contract on deployment. | | `salt` **`indexed`** | `bytes32` | The salt used to deterministically deploy the contract (`CREATE2` only). If `CREATE` opcode is used, the salt value will be `bytes32(0)`. |
### DataChanged :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#datachanged) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Event signature: `DataChanged(bytes32,bytes)` - Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` ::: ```solidity event DataChanged(bytes32 indexed dataKey, bytes dataValue); ``` _The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`._ Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | -------------------------------------------- | | `dataKey` **`indexed`** | `bytes32` | The data key for which a bytes value is set. | | `dataValue` | `bytes` | The value to set for the given data key. |
### Executed :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#executed) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Event signature: `Executed(uint256,address,uint256,bytes4)` - Event topic hash: `0x4810874456b8e6487bd861375cf6abd8e1c8bb5858c8ce36a86a04dabfac199e` ::: ```solidity event Executed( uint256 indexed operationType, address indexed target, uint256 value, bytes4 indexed selector ); ``` _Called address `target` using `operationType` with `value` wei and `data`._ Emitted when calling an address `target` (EOA or contract) with `value`. #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ---------------------------------------------------------------------------------------------------- | | `operationType` **`indexed`** | `uint256` | The low-level call opcode used to call the `target` address (`CALL`, `STATICALL` or `DELEGATECALL`). | | `target` **`indexed`** | `address` | The address to call. `target` will be unused if a contract is created (operation types 1 and 2). | | `value` | `uint256` | The amount of native tokens transferred along the call (in Wei). | | `selector` **`indexed`** | `bytes4` | The first 4 bytes (= function selector) of the data sent with the call. |
### OwnershipRenounced :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#ownershiprenounced) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Event signature: `OwnershipRenounced()` - Event topic hash: `0xd1f66c3d2bc1993a86be5e3d33709d98f0442381befcedd29f578b9b2506b1ce` ::: ```solidity event OwnershipRenounced(); ``` _Successfully renounced ownership of the contract. This contract is now owned by anyone, it's owner is `address(0)`._ Emitted when the ownership of the contract has been renounced.
### OwnershipTransferStarted :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#ownershiptransferstarted) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Event signature: `OwnershipTransferStarted(address,address)` - Event topic hash: `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` ::: ```solidity event OwnershipTransferStarted( address indexed previousOwner, address indexed newOwner ); ``` _The transfer of ownership of the contract was initiated. Pending new owner set to: `newOwner`._ Emitted when [`transferOwnership(..)`](#transferownership) was called and the first step of transferring ownership completed successfully which leads to [`pendingOwner`](#pendingowner) being updated. #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ---------------------------------- | | `previousOwner` **`indexed`** | `address` | The address of the previous owner. | | `newOwner` **`indexed`** | `address` | The address of the new owner. |
### OwnershipTransferred :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#ownershiptransferred) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Event signature: `OwnershipTransferred(address,address)` - Event topic hash: `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` ::: ```solidity event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); ``` #### Parameters | Name | Type | Description | | ----------------------------- | :-------: | ----------- | | `previousOwner` **`indexed`** | `address` | - | | `newOwner` **`indexed`** | `address` | - |
### RenounceOwnershipStarted :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#renounceownershipstarted) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Event signature: `RenounceOwnershipStarted()` - Event topic hash: `0x81b7f830f1f0084db6497c486cbe6974c86488dcc4e3738eab94ab6d6b1653e7` ::: ```solidity event RenounceOwnershipStarted(); ``` _Ownership renouncement initiated._ Emitted when starting the [`renounceOwnership(..)`](#renounceownership) 2-step process.
### UniversalReceiver :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#universalreceiver) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Event signature: `UniversalReceiver(address,uint256,bytes32,bytes,bytes)` - Event topic hash: `0x9c3ba68eb5742b8e3961aea0afc7371a71bf433c8a67a831803b64c064a178c2` ::: ```solidity event UniversalReceiver( address indexed from, uint256 indexed value, bytes32 indexed typeId, bytes receivedData, bytes returnedValue ); ``` \*Address `from` called the `universalReceiver(...)` function while sending `value` LYX. Notification type (typeId): `typeId` - Data received: `receivedData`.\* Emitted when the [`universalReceiver`](#universalreceiver) function was called with a specific `typeId` and some `receivedData` #### Parameters | Name | Type | Description | | ---------------------- | :-------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `from` **`indexed`** | `address` | The address of the EOA or smart contract that called the [`universalReceiver(...)`](#universalreceiver) function. | | `value` **`indexed`** | `uint256` | The amount sent to the [`universalReceiver(...)`](#universalreceiver) function. | | `typeId` **`indexed`** | `bytes32` | A `bytes32` unique identifier (= _"hook"_)that describe the type of notification, information or transaction received by the contract. Can be related to a specific standard or a hook. | | `receivedData` | `bytes` | Any arbitrary data that was sent to the [`universalReceiver(...)`](#universalreceiver) function. | | `returnedValue` | `bytes` | The value returned by the [`universalReceiver(...)`](#universalreceiver) function. |
## Errors ### ERC725X_ContractDeploymentFailed :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_contractdeploymentfailed) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725X_ContractDeploymentFailed()` - Error hash: `0x0b07489b` ::: ```solidity error ERC725X_ContractDeploymentFailed(); ``` Reverts when contract deployment failed via [`execute`](#execute) or [`executeBatch`](#executebatch) functions, This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_CreateOperationsRequireEmptyRecipientAddress :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_createoperationsrequireemptyrecipientaddress) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725X_CreateOperationsRequireEmptyRecipientAddress()` - Error hash: `0x3041824a` ::: ```solidity error ERC725X_CreateOperationsRequireEmptyRecipientAddress(); ``` Reverts when passing a `to` address that is not `address(0)` (= address zero) while deploying a contract via [`execute`](#execute) or [`executeBatch`](#executebatch) functions. This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_ExecuteParametersEmptyArray :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_executeparametersemptyarray) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725X_ExecuteParametersEmptyArray()` - Error hash: `0xe9ad2b5f` ::: ```solidity error ERC725X_ExecuteParametersEmptyArray(); ``` Reverts when one of the array parameter provided to the [`executeBatch`](#executebatch) function is an empty array.
### ERC725X_ExecuteParametersLengthMismatch :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_executeparameterslengthmismatch) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725X_ExecuteParametersLengthMismatch()` - Error hash: `0x3ff55f4d` ::: ```solidity error ERC725X_ExecuteParametersLengthMismatch(); ``` Reverts when there is not the same number of elements in the `operationTypes`, `targets` addresses, `values`, and `datas` array parameters provided when calling the [`executeBatch`](#executebatch) function.
### ERC725X_InsufficientBalance :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_insufficientbalance) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725X_InsufficientBalance(uint256,uint256)` - Error hash: `0x0df9a8f8` ::: ```solidity error ERC725X_InsufficientBalance(uint256 balance, uint256 value); ``` Reverts when trying to send more native tokens `value` than available in current `balance`. #### Parameters | Name | Type | Description | | --------- | :-------: | -------------------------------------------------------------------------------------------------------------------------------------- | | `balance` | `uint256` | The balance of native tokens of the ERC725X smart contract. | | `value` | `uint256` | The amount of native tokens sent via `ERC725X.execute(...)`/`ERC725X.executeBatch(...)` that is greater than the contract's `balance`. |
### ERC725X_MsgValueDisallowedInDelegateCall :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_msgvaluedisallowedindelegatecall) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725X_MsgValueDisallowedInDelegateCall()` - Error hash: `0x5ac83135` ::: ```solidity error ERC725X_MsgValueDisallowedInDelegateCall(); ``` Reverts when trying to send native tokens (`value` / `values[]` parameter of [`execute`](#execute) or [`executeBatch`](#executebatch) functions) while making a `delegatecall` (`operationType == 4`). Sending native tokens via `staticcall` is not allowed because `msg.value` is persisting.
### ERC725X_MsgValueDisallowedInStaticCall :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_msgvaluedisallowedinstaticcall) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725X_MsgValueDisallowedInStaticCall()` - Error hash: `0x72f2bc6a` ::: ```solidity error ERC725X_MsgValueDisallowedInStaticCall(); ``` Reverts when trying to send native tokens (`value` / `values[]` parameter of [`execute`](#execute) or [`executeBatch`](#executebatch) functions) while making a `staticcall` (`operationType == 3`). Sending native tokens via `staticcall` is not allowed because it is a state changing operation.
### ERC725X_NoContractBytecodeProvided :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_nocontractbytecodeprovided) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725X_NoContractBytecodeProvided()` - Error hash: `0xb81cd8d9` ::: ```solidity error ERC725X_NoContractBytecodeProvided(); ``` Reverts when no contract bytecode was provided as parameter when trying to deploy a contract via [`execute`](#execute) or [`executeBatch`](#executebatch). This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`).
### ERC725X_UnknownOperationType :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725x_unknownoperationtype) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725X_UnknownOperationType(uint256)` - Error hash: `0x7583b3bc` ::: ```solidity error ERC725X_UnknownOperationType(uint256 operationTypeProvided); ``` Reverts when the `operationTypeProvided` is none of the default operation types available. (CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4) #### Parameters | Name | Type | Description | | ----------------------- | :-------: | ------------------------------------------------------------------------------------------------------ | | `operationTypeProvided` | `uint256` | The unrecognised operation type number provided to `ERC725X.execute(...)`/`ERC725X.executeBatch(...)`. |
### ERC725Y_DataKeysValuesEmptyArray :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725y_datakeysvaluesemptyarray) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725Y_DataKeysValuesEmptyArray()` - Error hash: `0x97da5f95` ::: ```solidity error ERC725Y_DataKeysValuesEmptyArray(); ``` Reverts when one of the array parameter provided to [`setDataBatch`](#setdatabatch) function is an empty array.
### ERC725Y_DataKeysValuesLengthMismatch :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#erc725y_datakeysvalueslengthmismatch) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `ERC725Y_DataKeysValuesLengthMismatch()` - Error hash: `0x3bcc8979` ::: ```solidity error ERC725Y_DataKeysValuesLengthMismatch(); ``` Reverts when there is not the same number of elements in the `datakeys` and `dataValues` array parameters provided when calling the [`setDataBatch`](#setdatabatch) function.
### LSP14CallerNotPendingOwner :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp14callernotpendingowner) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `LSP14CallerNotPendingOwner(address)` - Error hash: `0x451e4528` ::: ```solidity error LSP14CallerNotPendingOwner(address caller); ``` Reverts when the `caller` that is trying to accept ownership of the contract is not the pending owner. #### Parameters | Name | Type | Description | | -------- | :-------: | ------------------------------------------- | | `caller` | `address` | The address that tried to accept ownership. |
### LSP14CannotTransferOwnershipToSelf :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp14cannottransferownershiptoself) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `LSP14CannotTransferOwnershipToSelf()` - Error hash: `0xe052a6f8` ::: ```solidity error LSP14CannotTransferOwnershipToSelf(); ``` _Cannot transfer ownership to the address of the contract itself._ Reverts when trying to transfer ownership to the `address(this)`.
### LSP14MustAcceptOwnershipInSeparateTransaction :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp14mustacceptownershipinseparatetransaction) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `LSP14MustAcceptOwnershipInSeparateTransaction()` - Error hash: `0x5758dd07` ::: ```solidity error LSP14MustAcceptOwnershipInSeparateTransaction(); ``` _Cannot accept ownership in the same transaction with [`transferOwnership(...)`](#transferownership)._ Reverts when pending owner accept ownership in the same transaction of transferring ownership.
### LSP14NotInRenounceOwnershipInterval :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp14notinrenounceownershipinterval) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `LSP14NotInRenounceOwnershipInterval(uint256,uint256)` - Error hash: `0x1b080942` ::: ```solidity error LSP14NotInRenounceOwnershipInterval( uint256 renounceOwnershipStart, uint256 renounceOwnershipEnd ); ``` _Cannot confirm ownership renouncement yet. The ownership renouncement is allowed from: `renounceOwnershipStart` until: `renounceOwnershipEnd`._ Reverts when trying to renounce ownership before the initial confirmation delay. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ----------------------------------------------------------------------- | | `renounceOwnershipStart` | `uint256` | The start timestamp when one can confirm the renouncement of ownership. | | `renounceOwnershipEnd` | `uint256` | The end timestamp when one can confirm the renouncement of ownership. |
### LSP20CallVerificationFailed :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp20callverificationfailed) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `LSP20CallVerificationFailed(bool,bytes4)` - Error hash: `0x9d6741e3` ::: ```solidity error LSP20CallVerificationFailed(bool postCall, bytes4 returnedStatus); ``` reverts when the call to the owner does not return the LSP20 success value #### Parameters | Name | Type | Description | | ---------------- | :------: | ------------------------------------------------------- | | `postCall` | `bool` | True if the execution call was done, False otherwise | | `returnedStatus` | `bytes4` | The bytes4 decoded data returned by the logic verifier. |
### LSP20CallingVerifierFailed :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp20callingverifierfailed) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `LSP20CallingVerifierFailed(bool)` - Error hash: `0x8c6a8ae3` ::: ```solidity error LSP20CallingVerifierFailed(bool postCall); ``` reverts when the call to the owner fail with no revert reason #### Parameters | Name | Type | Description | | ---------- | :----: | ---------------------------------------------------- | | `postCall` | `bool` | True if the execution call was done, False otherwise |
### LSP20EOACannotVerifyCall :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#lsp20eoacannotverifycall) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `LSP20EOACannotVerifyCall(address)` - Error hash: `0x0c392301` ::: ```solidity error LSP20EOACannotVerifyCall(address logicVerifier); ``` Reverts when the logic verifier is an Externally Owned Account (EOA) that cannot return the LSP20 success value. #### Parameters | Name | Type | Description | | --------------- | :-------: | --------------------------------- | | `logicVerifier` | `address` | The address of the logic verifier |
### NoExtensionFoundForFunctionSelector :::note References - Specification details: [**UniversalProfile**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#noextensionfoundforfunctionselector) - Solidity implementation: [`UniversalProfile.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol) - Error signature: `NoExtensionFoundForFunctionSelector(bytes4)` - Error hash: `0xbb370b2b` ::: ```solidity error NoExtensionFoundForFunctionSelector(bytes4 functionSelector); ``` reverts when there is no extension for the function selector being called with #### Parameters | Name | Type | Description | | ------------------ | :------: | ----------- | | `functionSelector` | `bytes4` | - |
[ERC-165]: https://eips.ethereum.org/EIPS/eip-165 [ERC-173]: https://eips.ethereum.org/EIPS/eip-173 [ERC-191]: https://eips.ethereum.org/EIPS/eip-191 [ERC-725X]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725X [ERC-725Y]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#ERC725Y [ERC-725]: https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md [ERC-1271]: https://eips.ethereum.org/EIPS/eip-1271 [EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 [LSP-0-ERC725Account]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-0-ERC725Account.md [LSP-1-UniversalReceiver]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-1-UniversalReceiver.md [LSP-2-ERC725YJSONSchema]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-2-ERC725YJSONSchema.md [LSP-3-Profile-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-3-Profile-Metadata.md [LSP-4-DigitalAsset-Metadata]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-4-DigitalAsset-Metadata.md [LSP-5-ReceivedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-5-ReceivedAssets.md [LSP-6-KeyManager]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-6-KeyManager.md [LSP-7-DigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-7-DigitalAsset.md [LSP-8-IdentifiableDigitalAsset]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md [LSP-9-Vault.md]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-9-Vault.md.md [LSP-10-ReceivedVaults]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-10-ReceivedVaults.md [LSP-11-BasicSocialRecovery]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-11-BasicSocialRecovery.md [LSP-12-IssuedAssets]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-12-IssuedAssets.md [LSP-14-Ownable2Step]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-14-Ownable2Step.md [LSP-15-TransactionRelayServiceAPI]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-15-TransactionRelayServiceAPI.md [LSP-16-UniversalFactory]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-16-UniversalFactory.md [LSP-17-ContractExtension]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-17-ContractExtension.md [LSP-20-CallVerification]: https://github.com/lukso-network/LIPs/tree/main/LSPs/LSP-20-CallVerification.md [ERC725]: https://docs.lukso.tech/standards/erc725 [UniversalProfile]: https://docs.lukso.tech/standards/accounts/introduction [LSP0ERC725Account]: https://docs.lukso.tech/standards/accounts/lsp0-erc725account [LSP1UniversalReceiver]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver [LSP1UniversalReceiverDelegate]: https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate [LSP2ERC725YJSONSchema]: https://docs.lukso.tech/standards/metadata/lsp2-json-schema [LSP4DigitalAssetMetadata]: https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata [LSP5ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp5-received-assets [LSP6KeyManager]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager [LSP7DigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset [LSP8IdentifiableDigitalAsset]: https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset [LSP10ReceivedVaults]: https://docs.lukso.tech/standards/metadata/lsp10-received-vaults [LSP14Ownable2Step]: https://docs.lukso.tech/standards/access-control/lsp14-ownable-2-step [LSP17ContractExtension]: https://docs.lukso.tech/standards/accounts/lsp17-contract-extension [LSP20CallVerification]: https://docs.lukso.tech/standards/accounts/lsp20-call-verification [_LSP17_EXTENSION_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md#lsp17extendable-specification [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-1 [LSP0OwnershipTransferStarted]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#transferownership [LSP0OwnershipTransferred_SenderNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [LSP0OwnershipTransferred_RecipientNotification]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md#acceptownership [`ERC725.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725.sol [`ERC725Init.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Init.sol [`ERC725InitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725InitAbstract.sol [`IERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725X.sol [`ERC725X.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725X.sol [`ERC725XCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725XCore.sol [`ERC725XInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInit.sol [`ERC725XInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725XInitAbstract.sol [`IERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/interfaces/IERC725Y.sol [`ERC725Y.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725Y.sol [`ERC725YCore.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/ERC725YCore.sol [`ERC725YInit.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInit.sol [`ERC725YInitAbstract.sol`]: https://github.com/ERC725Alliance/ERC725/blob/main/implementations/contracts/ERC725YInitAbstract.soll [`OwnableUnset.sol`]: https://github.com/ERC725Alliance/ERC725/blob/v7.0.0/implementations/contracts/custom/OwnableUnset.sol [`Create2.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Create2.sol [`ECDSA.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/cryptography/ECDSA.sol [`ERC165Checker.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165Checker.sol [`Address.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Address.sol [`ERC165.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/introspection/ERC165.sol [`EnumerableSet.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/structs/EnumerableSet.so [`Initializable.sol`]: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/proxy/utils/Initializable.sol [`BytesLib.sol`]: https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.4/contracts/BytesLib.sol [`LSP0ERC725AccountCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountCore.sol [`LSP0Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Utils.sol [`LSP0ERC725AccountInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInitAbstract.sol [`ILSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/ILSP0ERC725Account.sol [`LSP0ERC725Account.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725Account.sol [`LSP0ERC725AccountInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0ERC725AccountInit.sol [`LSP0Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp0-contracts/contracts/LSP0Constants.sol [`UniversalProfileInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInitAbstract.sol [`UniversalProfile.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfile.sol [`UniversalProfileInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/universalprofile-contracts/contracts/UniversalProfileInit.sol [`LSP1UniversalReceiverDelegateUP.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateUP.sol [`LSP1UniversalReceiverDelegateVault.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1UniversalReceiverDelegateVault.sol [`LSP1Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/blob/main/packages/lsp1delegate-contracts/contracts/LSP1Errors.sol [`LSP1Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Utils.sol [`ILSP1UniversalReceiver.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol [`LSP1Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/LSP1Constants.sol [`LSP4DigitalAssetMetadataInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadataInitAbstract.sol [`LSP4DigitalAssetMetadata.sol`]: chttps://github.com/code-423n4/2023-06-lukso/tree/main/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol [`LSP4Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Constants.sol [`LSP4Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts/contracts/LSP4Errors.sol [`LSP6SetDataModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6SetDataModule.sol [`LSP6KeyManagerCore.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerCore.sol [`LSP6ExecuteModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6ExecuteModule.sol [`LSP6Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Utils.sol [`LSP6Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Constants.sol [`ILSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/ILSP6KeyManager.sol [`LSP6Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Errors.sol [`LSP6OwnershipModule.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6Modules/LSP6OwnershipModule.sol [`LSP6KeyManagerInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInitAbstract.sol [`LSP6KeyManager.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol [`LSP6KeyManagerInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManagerInit.sol [`ILSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/ILSP7DigitalAsset.sol [`LSP7DigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAssetInitAbstract.sol [`LSP7CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol [`LSP7CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7CappedSupplyInitAbstract.sol [`LSP7DigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol [`LSP7MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInitAbstract.sol [`LSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7Mintable.sol [`LSP7Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Errors.sol [`LSP7MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/LSP7MintableInit.sol [`ILSP7Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/presets/ILSP7Mintable.sol [`LSP7Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7Burnable.sol [`LSP7BurnableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/extensions/LSP7BurnableInitAbstract.sol [`LSP7Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts/contracts/LSP7Constants.sol [`ILSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/ILSP8IdentifiableDigitalAsset.sol [`LSP8EnumerableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8EnumerableInitAbstract.sol [`LSP8Enumerable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Enumerable.sol [`LSP8CappedSupplyInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupplyInitAbstract.sol [`LSP8CappedSupply.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8CappedSupply.sol [`LSP8IdentifiableDigitalAssetInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAssetInitAbstract.sol [`LSP8MintableInitAbstract.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInitAbstract.sol [`LSP8IdentifiableDigitalAsset.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol [`LSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8Mintable.sol [`LSP8Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Errors.sol [`LSP8MintableInit.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/LSP8MintableInit.sol [`LSP8Burnable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/extensions/LSP8Burnable.sol [`ILSP8Mintable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/presets/ILSP8Mintable.sol [`LSP8Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts/contracts/LSP8Constants.s [`LSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Ownable2Step.sol [`ILSP14Ownable2Step.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/ILSP14Ownable2Step.sol [`LSP14Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Constants.sol [`LSP14Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts/contracts/LSP14Errors.sol [`LSP17Extendable.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol [`LSP17Extension.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extension.sol [`LSP17Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Constants.sol [`LSP17Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Errors.sol [`LSP17Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Utils.sol [`LSP20CallVerification.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20CallVerification.sol [`ILSP20CallVerifier.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/ILSP20CallVerifier.sol [`LSP20Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Constants.sol [`LSP20Errors.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts/contracts/LSP20Errors.sol [`LSP2Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol [`LSP5Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol [`LSP5Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Constants.sol [`LSP10Utils.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol [`LSP10Constants.sol`]: https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Constants.sol --- --- title: ⛓ Deployed Implementation Contracts description: List of base implementation and factory contracts addresses deployed on LUKSO Mainnet. --- import { BaseContractsTable, FactoryContractsTable } from "@site/src/components/DeployedContractsTable" # Deployed Implementation Contracts on LUKSO Mainnet :::success Deployment Guides Check our guide [**_🏭 Deploy Universal Profile + its Key Manager with LSP23 Factory_**](../learn/universal-profile/advanced-guides/deploy-up-with-lsp23.md) if you are looking for a script to deploy with the LSP23 Factory using _ethers.js_. ::: Below is a list of contracts deployed on the LUKSO Mainnet for production usage. These contracts are deployed with `CREATE2` using the Nick Factory, so that they can be re-deployed at different addresses across multiple chains. ## 🏭 Factory contracts The LSP23 Linked Contract Factory is used to deploy a full Universal Profile (with its Key Manager) and setup the main controller permissions. It is used by the UP Browser Extension and can be leveraged by any other dApp to deploy UPs. ## 📑 Implementation contracts Below are the base implementation contracts deployed on mainnet. They contain all the core logic of the: - **Universal Profile** 🆙 - **LSP6 Key Manager** 🔐 - **LSP1 Universal Receiver Delegate** 📣 - **LSP7 Digital Asset** (Mintable preset where the `owner()` can call the `mint(...)` function) - **LSP8 Identifiable Digital Asset** (Mintable preset where the `owner()` can call the `mint(...)` function) Proxies pointing to these implementations must be initialized via the `initialize(...)` function to work. The Universal Profile and Key Manager contracts of each users are deployed as EIP1167 minimal proxy, with their bytecode pointing to these implementation contracts. Finally, each Universal Profile has its **default** Universal Receiver Delegate contract linked to its 🆙 contract via the [`LSP1UniversalReceiverDelegate`](/standards/accounts/lsp1-universal-receiver-delegate.md#lsp1universalreceiverdelegate-singleton) data key. You can inspect these details via our [_erc725-inspect_](https://erc725-inspect.lukso.tech/inspector?address=0x0F4180da178ed1C71398a57ca8Cb177F69591f1f&network=mainnet) tool. --- --- title: Interfaces IDs --- import InterfaceIdsTable from "./\_interface_ids_table.mdx"; # Interfaces IDs :::caution Interface IDs are not the most secure way to ensure that a contract implements a specific set of functions, as they are manually set and can be set to any value. ::: **Interfaces IDs** help check if a contract supports a specific interface, e.g., its meta-interface. They are helpful if we want to interact with a contract but don't know if it supports an interface such as **[ERC725Y](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y)**, **[LSP1UniversalReceiver](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md)**, etc. The **supportsInterface** function from the **[ERC165](https://eips.ethereum.org/EIPS/eip-165)** standard returns `true` if the standard is supported, `false` otherwise. The interface IDs of each LSP standards can be easily imported in your code from the [`@lukso/lsp-smart-contracts` NPM package](https://www.npmjs.com/package/@lukso/lsp-smart-contracts). They are accessible as follow: ```js import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts'; const LSP0_INTERFACE_ID = INTERFACE_IDS.LSP0ERC725Account; ```
Note on importing INTERFACE_IDS in Hardhat Typescript projects If you are trying to import the `INTERFACE_IDS` within a Hardhat Typescript project, use the following import syntax: ```ts import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts/constants'; // This will raise an error if you have ES Lint enabled, // but will allow you to import the constants in a Hardhat + Typescript based project. const LSP0_INTERFACE_ID = INTERFACE_IDS.LSP0ERC725Account; ``` This is due to the current issue that it is not possible to import ES Modules in Hardhat Typescript projects.
--- --- title: Introduction sidebar_position: 1 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import {ContractCardsGallery} from '@site/src/components/ContractCardsGallery'; # Smart Contracts **Welcome to the LUKSO Smart Contracts documentation!** You will find on this page all the documentation and resources related to the `@lukso/lsp-smart-contracts`, the reference implementation in Solidity of the **[LSPs (LUKSO Standard Proposals)](../standards/introduction.md)**. Each LSP standard and features are implemented in separate contracts under their own package. This allows developers to *"pick and choose"* the contracts for the requirements and behaviours they need for their protocols and applications. The `@lukso/lsp-smart-contracts` package also contains all the LSPs implementations listed below. This modular design also helps in making the codebase easier to navigate and understand for developers using it.
| Package | Version | | :-------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts) | | | [`@lukso/lsp0-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp0-contracts) | | | [`@lukso/lsp1-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts) | | | [`@lukso/lsp1delegate-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1delegate-contracts) | | | [`@lukso/lsp2-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts) | | | [`@lukso/lsp3-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp3-contracts) | | | [`@lukso/lsp4-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp4-contracts) | | | [`@lukso/lsp5-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts) | | | [`@lukso/lsp6-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts) | | | [`@lukso/lsp7-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp7-contracts) | | | [`@lukso/lsp8-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp8-contracts) | | | [`@lukso/lsp9-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp9-contracts) | |
| Package | Version | | :---------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [`@lukso/lsp10-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts) | | | [`@lukso/lsp11-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp11-contracts) | | | [`@lukso/lsp12-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp12-contracts) | | | [`@lukso/lsp14-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp14-contracts) | | | [`@lukso/lsp16-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp16-contracts) | | | [`@lukso/lsp17-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17-contracts) | | | [`@lukso/lsp17contractextension-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts) | | | [`@lukso/lsp20-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp20-contracts) | | | [`@lukso/lsp23-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp23-contracts) | | | [`@lukso/lsp25-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp25-contracts) | | | [`@lukso/lsp26-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp26-contracts) | | | [`@lukso/universalprofile-contracts`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/universalprofile-contracts) | |
## Installation ### with npm, yarn or pnpm To get all the LSP smart contracts, install the `@lukso/lsp-smart-contracts`. ```bash npm install @lukso/lsp-smart-contracts ``` ```bash yarn add @lukso/lsp-smart-contracts ``` ```bash pnpm add @lukso/lsp-smart-contracts ``` You can also install individual package based on the LSP that you need (see table above). For instance, if you only need the LSP7 Digital Asset contract implementation for your project, simply install the `@lukso/lsp7-contracts` package. ```bash npm install @lukso/lsp7-contracts ``` ```bash yarn add @lukso/lsp7-contracts ``` ```bash pnpm add @lukso/lsp7-contracts ``` ### with Foundry Currently, the monorepo structure of the LSP Smart Contracts create issues when installing via Foundry and forge. As a workaround, it is recommend to use the following method: 1. install the smart contract package with your preferred package manager as shown above (npm, yarn or pnpm). ```bash npm i @lukso/lsp7-contracts ``` 2. add the following in your `remappings.txt` or `foundry.toml`. ```txt title="remappings.txt" @lukso/=node_modules/@lukso/ ``` This will install the LUKSO LSP Solidity contracts in your `node_modules/` folder and forge will remap your `import @lukso/...` statements in your `.sol` files by locating the LSP contracts in the `node_modules/` folder. ## Overview Overall the contracts can be divided by their usage. ## Types of contracts :::info If you are using base contracts and are deploying proxies for your application, it is recommended to use a factory pattern to deploy and initialize the proxies to avoid potential front-running issues. The **LSP16 Universal Factory** or **LSP23 Linked Contract Deployment** can help you achieve this. ::: The `@lukso/lsp-smart-contracts` repository contains two types of contracts: | Type | Description | Example | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------- | | **Standard contracts** | One contract deployed per user. Deployed and initialized via a `constructor`. | `LSP0ERC725Account.sol` | | **Base contracts** | Deploy one contract for all users. To be used as base contract behind proxies. Initialized via a `initialize(...)` function. | `LSP0ERC725AccountInit.sol` | ## LSP Recipes Some of the LSP standards do not have a contract implementation as they represent **Metadata-Standards** to be used in the implementation contracts. Each contracts are not just related to one specific section. They could be used in different fashion and combination, with the **Universal Profile**, **Digital Asset**, and **NFT 2.0** contracts. For instance, the **Universal Profile Browser extension** comprises a set of contracts allow a better representation of the identity on the blockchain and better control over it. ## Further Information - [UniversalProfile & Identity Section](https://youtu.be/SbTo_e3l_Lk?t=1727) - [NFT 2.0 Section](https://youtu.be/hg1Ow6u9QVk) - [LSP Smart Contracts - Detailed Architecture Diagram](https://twitter.com/gpersoon/status/1676588871255990272) by [@gpersoon](https://twitter.com/gpersoon) --- # LSP10Utils :::info Standard Specifications [`LSP-10-ReceivedVaults`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-10-ReceivedVaults.md) ::: :::info Solidity implementation [`LSP10Utils.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp10-contracts/contracts/LSP10Utils.sol) ::: > LSP10 Utility library. LSP5Utils is a library of functions that can be used to register and manage vaults received by an ERC725Y smart contract. Based on the LSP10 Received Vaults standard. ## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### generateReceivedVaultKeys :::caution Warning This function returns empty arrays when encountering errors. Otherwise the arrays will contain 3 data keys and 3 data values. ::: ```solidity function generateReceivedVaultKeys( address receiver, address vaultAddress ) internal view returns (bytes32[] lsp10DataKeys, bytes[] lsp10DataValues); ``` Generate an array of data keys/values pairs to be set on the receiver address after receiving vaults. #### Parameters | Name | Type | Description | | -------------- | :-------: | ------------------------------------------------------------------------------ | | `receiver` | `address` | The address receiving the vault and where the LSP10 data keys should be added. | | `vaultAddress` | `address` | The address of the vault being received. | #### Returns | Name | Type | Description | | ----------------- | :---------: | --------------------------------------------------------------------- | | `lsp10DataKeys` | `bytes32[]` | An array data keys used to update the [LSP-10-ReceivedAssets] data. | | `lsp10DataValues` | `bytes[]` | An array data values used to update the [LSP-10-ReceivedAssets] data. |
### generateSentVaultKeys :::caution Warning Returns empty arrays when encountering errors. Otherwise the arrays must have at least 3 data keys and 3 data values. ::: ```solidity function generateSentVaultKeys( address sender, address vaultAddress ) internal view returns (bytes32[] lsp10DataKeys, bytes[] lsp10DataValues); ``` Generate an array of data key/value pairs to be set on the sender address after sending vaults. #### Parameters | Name | Type | Description | | -------------- | :-------: | ------------------------------------------------------------------------------ | | `sender` | `address` | The address sending the vault and where the LSP10 data keys should be updated. | | `vaultAddress` | `address` | The address of the vault that is being sent. | #### Returns | Name | Type | Description | | ----------------- | :---------: | --------------------------------------------------------------------- | | `lsp10DataKeys` | `bytes32[]` | An array data keys used to update the [LSP-10-ReceivedAssets] data. | | `lsp10DataValues` | `bytes[]` | An array data values used to update the [LSP-10-ReceivedAssets] data. |
### getLSP10ArrayLengthBytes ```solidity function getLSP10ArrayLengthBytes(contract IERC725Y erc725YContract) internal view returns (bytes); ``` Get the raw bytes value stored under the `_LSP10_VAULTS_ARRAY_KEY`. #### Parameters | Name | Type | Description | | ----------------- | :-----------------: | ----------------------------------------------- | | `erc725YContract` | `contract IERC725Y` | The contract to query the ERC725Y storage from. | #### Returns | Name | Type | Description | | ---- | :-----: | ----------------------------------------------- | | `0` | `bytes` | The raw bytes value stored under this data key. |
--- # LSP17Utils :::info Standard Specifications [`LSP-17-ContractExtension`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md) ::: :::info Solidity implementation [`LSP17Utils.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp17contractextension-contracts/contracts/LSP17Extendable.sol) ::: > LSP17 Utility library to check an extension ## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### isExtension ```solidity function isExtension( uint256 parametersLengthWithOffset, uint256 msgDataLength ) internal pure returns (bool); ``` Returns whether the call is a normal call or an extension call by checking if the `parametersLengthWithOffset` with an additional of 52 bytes supposed msg.sender and msg.value appended is equal to the msgDataLength
--- # LSP1Utils :::info Standard Specifications [`LSP-1-UniversalReceiver`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md) ::: :::info Solidity implementation [`LSP1Utils.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts/ILSP1UniversalReceiver.sol) ::: > LSP1 Utility library. LSP1Utils is a library of utility functions that can be used to notify the `universalReceiver` function of a contract that implements LSP1 and retrieve information related to LSP1 `typeId`. Based on LSP1 Universal Receiver standard. ## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### notifyUniversalReceiver ```solidity function notifyUniversalReceiver( address lsp1Implementation, bytes32 typeId, bytes data ) internal nonpayable; ``` Notify a contract at `lsp1Implementation` address by calling its `universalReceiver` function if this contract supports the LSP1 interface. #### Parameters | Name | Type | Description | | -------------------- | :-------: | -------------------------------------------------------------------------------------------------- | | `lsp1Implementation` | `address` | The address of the contract to notify. | | `typeId` | `bytes32` | A `bytes32` typeId. | | `data` | `bytes` | Any optional data to send to the `universalReceiver` function to the `lsp1Implementation` address. |
### getLSP1DelegateValue ```solidity function getLSP1DelegateValue( mapping(bytes32 => bytes) erc725YStorage ) internal view returns (bytes); ``` _Retrieving the value stored under the ERC725Y data key `LSP1UniversalReceiverDelegate`._ Query internally the ERC725Y storage of a `ERC725Y` smart contract to retrieve the value set under the `LSP1UniversalReceiverDelegate` data key. #### Parameters | Name | Type | Description | | ---------------- | :-------------------------: | ----------------------------------------------------------- | | `erc725YStorage` | `mapping(bytes32 => bytes)` | A reference to the ERC725Y storage mapping of the contract. | #### Returns | Name | Type | Description | | ---- | :-----: | -------------------------------------------------------------------------- | | `0` | `bytes` | The bytes value stored under the `LSP1UniversalReceiverDelegate` data key. |
### getLSP1DelegateValueForTypeId ```solidity function getLSP1DelegateValueForTypeId( mapping(bytes32 => bytes) erc725YStorage, bytes32 typeId ) internal view returns (bytes); ``` _Retrieving the value stored under the ERC725Y data key `LSP1UniversalReceiverDelegate:` for a specific `typeId`._ Query internally the ERC725Y storage of a `ERC725Y` smart contract to retrieve the value set under the `LSP1UniversalReceiverDelegate:` data key for a specific LSP1 `typeId`. #### Parameters | Name | Type | Description | | ---------------- | :-------------------------: | ----------------------------------------------------------- | | `erc725YStorage` | `mapping(bytes32 => bytes)` | A reference to the ERC725Y storage mapping of the contract. | | `typeId` | `bytes32` | A bytes32 LSP1 `typeId`; | #### Returns | Name | Type | Description | | ---- | :-----: | ------------------------------------------------------------------------------------ | | `0` | `bytes` | The bytes value stored under the `LSP1UniversalReceiverDelegate:` data key. |
--- # LSP2Utils :::info Standard Specifications [`LSP-2-ERC725YJSONSchema`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md) ::: :::info Solidity implementation [`LSP2Utils.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp2-contracts/contracts/LSP2Utils.sol) ::: > LSP2 Utility library. LSP2Utils is a library of utility functions that can be used to encode data key of different key type defined on the LSP2 standard. Based on LSP2 ERC725Y JSON Schema standard. ## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### generateSingletonKey ```solidity function generateSingletonKey(string keyName) internal pure returns (bytes32); ``` Generates a data key of keyType Singleton by hashing the string `keyName`. As: ``` keccak256("keyName") ``` #### Parameters | Name | Type | Description | | --------- | :------: | ---------------------------------------------------- | | `keyName` | `string` | The string to hash to generate a Singleton data key. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------- | | `0` | `bytes32` | The generated `bytes32` data key of key type Singleton. |
### generateArrayKey ```solidity function generateArrayKey(string arrayKeyName) internal pure returns (bytes32); ``` Generates a data key of keyType Array by hashing `arrayKeyName`. As: ``` keccak256("arrayKeyName[]") ``` #### Parameters | Name | Type | Description | | -------------- | :------: | ---------------------------------------------------------------------- | | `arrayKeyName` | `string` | The string that will be used to generate a data key of key type Array. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------- | | `0` | `bytes32` | The generated `bytes32` data key of key type Array. |
### generateArrayElementKeyAtIndex ```solidity function generateArrayElementKeyAtIndex( bytes32 arrayKey, uint128 index ) internal pure returns (bytes32); ``` Generates an Array data key at a specific `index` by concatenating together the first 16 bytes of `arrayKey` with the 16 bytes of `index`. As: ``` arrayKey[index] ``` #### Parameters | Name | Type | Description | | ---------- | :-------: | ----------------------------------------------------------------------------------- | | `arrayKey` | `bytes32` | The Array data key from which to generate the Array data key at a specific `index`. | | `index` | `uint128` | The index number in the `arrayKey`. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------------------------- | | `0` | `bytes32` | The generated `bytes32` data key of key type Array at a specific `index`. |
### generateMappingKey ```solidity function generateMappingKey( string firstWord, string lastWord ) internal pure returns (bytes32); ``` Generates a data key of key type Mapping that map `firstWord` to `lastWord`. This is done by hashing two strings words `firstWord` and `lastWord`. As: ``` bytes10(firstWordHash):0000:bytes20(lastWordHash) ``` #### Parameters | Name | Type | Description | | ----------- | :------: | ---------------------------------------------------- | | `firstWord` | `string` | The word to retrieve the first 10 bytes of its hash. | | `lastWord` | `string` | The word to retrieve the first 10 bytes of its hash. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------------------------------------------------------- | | `0` | `bytes32` | The generated `bytes32` data key of key type Mapping that map `firstWord` to a specific `lastWord`. |
### generateMappingKey ```solidity function generateMappingKey( string firstWord, address addr ) internal pure returns (bytes32); ``` Generates a data key of key type Mapping that map `firstWord` to an address `addr`. This is done by hashing the string word `firstWord` and concatenating its first 10 bytes with `addr`. As: ``` bytes10(firstWordHash):0000:
``` #### Parameters | Name | Type | Description | | ----------- | :-------: | ---------------------------------------------------- | | `firstWord` | `string` | The word to retrieve the first 10 bytes of its hash. | | `addr` | `address` | An address to map `firstWord` to. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------------------------------------------------------- | | `0` | `bytes32` | The generated `bytes32` data key of key type Mapping that map `firstWord` to a specific address `addr`. |
### generateMappingKey ```solidity function generateMappingKey( bytes10 keyPrefix, bytes20 bytes20Value ) internal pure returns (bytes32); ``` Generate a data key of key type Mapping that map a 10 bytes `keyPrefix` to a `bytes20Value`. As: ``` keyPrefix:bytes20Value ``` #### Parameters | Name | Type | Description | | -------------- | :-------: | ---------------------------------------------------- | | `keyPrefix` | `bytes10` | The first part of the data key of key type Mapping. | | `bytes20Value` | `bytes20` | The second part of the data key of key type Mapping. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------------------------------------------------------------- | | `0` | `bytes32` | The generated `bytes32` data key of key type Mapping that map a `keyPrefix` to a specific `bytes20Value`. |
### generateMappingWithGroupingKey ```solidity function generateMappingWithGroupingKey( string firstWord, string secondWord, address addr ) internal pure returns (bytes32); ``` Generate a data key of key type MappingWithGrouping by using two strings `firstWord` mapped to a `secondWord` mapped itself to a specific address `addr`. As: ``` bytes6(keccak256("firstWord")):bytes4(keccak256("secondWord")):0000:
``` #### Parameters | Name | Type | Description | | ------------ | :-------: | ---------------------------------------------------------------- | | `firstWord` | `string` | The word to retrieve the first 6 bytes of its hash. | | `secondWord` | `string` | The word to retrieve the first 4 bytes of its hash. | | `addr` | `address` | The address that makes the last part of the MappingWithGrouping. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------------------------------------------------------------------------------------------- | | `0` | `bytes32` | The generated `bytes32` data key of key type MappingWithGrouping that map a `firstWord` to a `secondWord` to a specific address `addr`. |
### generateMappingWithGroupingKey ```solidity function generateMappingWithGroupingKey( bytes6 keyPrefix, bytes4 mapPrefix, bytes20 subMapKey ) internal pure returns (bytes32); ``` Generate a data key of key type MappingWithGrouping that map a `keyPrefix` to an other `mapPrefix` to a specific `subMapKey`. As: ``` keyPrefix:mapPrefix:0000:subMapKey ``` #### Parameters | Name | Type | Description | | ----------- | :-------: | ------------------------------------------------------------------------- | | `keyPrefix` | `bytes6` | The first part (6 bytes) of the data key of keyType MappingWithGrouping. | | `mapPrefix` | `bytes4` | The second part (4 bytes) of the data key of keyType MappingWithGrouping. | | `subMapKey` | `bytes20` | The last part (bytes20) of the data key of keyType MappingWithGrouping. | #### Returns | Name | Type | Description | | ---- | :-------: | ----------------------------------------------------------------------------------------------------------------------------------- | | `0` | `bytes32` | The generated `bytes32` data key of key type MappingWithGrouping that map a `keyPrefix` to a `mapPrefix` to a specific `subMapKey`. |
### generateMappingWithGroupingKey ```solidity function generateMappingWithGroupingKey( bytes10 keyPrefix, bytes20 bytes20Value ) internal pure returns (bytes32); ``` Generate a data key of key type MappingWithGrouping that map a 10 bytes `keyPrefix` to a specific `bytes20Value`. As: #### Parameters | Name | Type | Description | | -------------- | :-------: | -------------------------------------------------------------- | | `keyPrefix` | `bytes10` | The first part of the data key of keyType MappingWithGrouping. | | `bytes20Value` | `bytes20` | The last of the data key of keyType MappingWithGrouping. | #### Returns | Name | Type | Description | | ---- | :-------: | --------------------------------------------------------------------------------------- | | `0` | `bytes32` | The generated `bytes32` data key of key type MappingWithGrouping that map a `keyPrefix` |
### generateJSONURLValue ```solidity function generateJSONURLValue( string hashFunction, string json, string url ) internal pure returns (bytes); ``` Generate a JSONURL value content. #### Parameters | Name | Type | Description | | -------------- | :------: | ---------------------------------------- | | `hashFunction` | `string` | The function used to hash the JSON file. | | `json` | `string` | Bytes value of the JSON file. | | `url` | `string` | The URL where the JSON file is hosted. |
### generateASSETURLValue ```solidity function generateASSETURLValue( string hashFunction, string assetBytes, string url ) internal pure returns (bytes); ``` Generate a ASSETURL value content. #### Parameters | Name | Type | Description | | -------------- | :------: | ---------------------------------------- | | `hashFunction` | `string` | The function used to hash the JSON file. | | `assetBytes` | `string` | Bytes value of the JSON file. | | `url` | `string` | The URL where the JSON file is hosted. | #### Returns | Name | Type | Description | | ---- | :-----: | ----------------------------------- | | `0` | `bytes` | The encoded value as an `ASSETURL`. |
### isCompactBytesArray ```solidity function isCompactBytesArray( bytes compactBytesArray ) internal pure returns (bool); ``` Verify if `data` is a valid array of value encoded as a `CompactBytesArray` according to the LSP2 `CompactBytesArray` valueType specification. #### Parameters | Name | Type | Description | | ------------------- | :-----: | -------------------------- | | `compactBytesArray` | `bytes` | The bytes value to verify. | #### Returns | Name | Type | Description | | ---- | :----: | ------------------------------------------------------------------------------- | | `0` | `bool` | `true` if the `data` is correctly encoded CompactBytesArray, `false` otherwise. |
### isValidLSP2ArrayLengthValue ```solidity function isValidLSP2ArrayLengthValue( bytes arrayLength ) internal pure returns (bool); ``` Validates if the bytes `arrayLength` are exactly 16 bytes long, and are of the exact size of an LSP2 Array length value #### Parameters | Name | Type | Description | | ------------- | :-----: | ------------------------------------- | | `arrayLength` | `bytes` | Plain bytes that should be validated. | #### Returns | Name | Type | Description | | ---- | :----: | -------------------------------------------------------- | | `0` | `bool` | `true` if the value is 16 bytes long, `false` otherwise. |
### removeLastElementFromArrayAndMap ```solidity function removeLastElementFromArrayAndMap( bytes32 arrayKey, uint128 newArrayLength, bytes32 removedElementIndexKey, bytes32 removedElementMapKey ) internal pure returns (bytes32[] dataKeys, bytes[] dataValues); ``` Generates Data Key/Value pairs for removing the last element from an LSP2 Array and a mapping Data Key. #### Parameters | Name | Type | Description | | ------------------------ | :-------: | ------------------------------------------------------------- | | `arrayKey` | `bytes32` | The Data Key of Key Type Array. | | `newArrayLength` | `uint128` | The new Array Length for the `arrayKey`. | | `removedElementIndexKey` | `bytes32` | The Data Key of Key Type Array Index for the removed element. | | `removedElementMapKey` | `bytes32` | The Data Key of a mapping to be removed. |
### removeElementFromArrayAndMap :::info The function assumes that the Data Value stored under the mapping Data Key is of length 20 where the last 16 bytes are the index of the element in the array. ::: ```solidity function removeElementFromArrayAndMap(contract IERC725Y erc725YContract, bytes32 arrayKey, uint128 newArrayLength, bytes32 removedElementIndexKey, uint128 removedElementIndex, bytes32 removedElementMapKey) internal view returns (bytes32[] dataKeys, bytes[] dataValues); ``` Generates Data Key/Value pairs for removing an element from an LSP2 Array and a mapping Data Key. #### Parameters | Name | Type | Description | | ------------------------ | :-----------------: | ------------------------------------------------------------- | | `erc725YContract` | `contract IERC725Y` | The ERC725Y contract. | | `arrayKey` | `bytes32` | The Data Key of Key Type Array. | | `newArrayLength` | `uint128` | The new Array Length for the `arrayKey`. | | `removedElementIndexKey` | `bytes32` | The Data Key of Key Type Array Index for the removed element. | | `removedElementIndex` | `uint128` | the index of the removed element. | | `removedElementMapKey` | `bytes32` | The Data Key of a mapping to be removed. |
--- # LSP5Utils :::info Standard Specifications [`LSP-5-ReceivedAssets`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-5-ReceivedAssets.md) ::: :::info Solidity implementation [`LSP5Utils.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp5-contracts/contracts/LSP5Utils.sol) ::: > LSP5 Utility library. LSP5Utils is a library of functions that can be used to register and manage assets under an ERC725Y smart contract. Based on the LSP5 Received Assets standard. ## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### generateReceivedAssetKeys :::caution Warning Returns empty arrays when encountering errors. Otherwise the arrays must have 3 data keys and 3 data values. ::: ```solidity function generateReceivedAssetKeys( address receiver, address assetAddress, bytes4 assetInterfaceId ) internal view returns (bytes32[] lsp5DataKeys, bytes[] lsp5DataValues); ``` Generate an array of data key/value pairs to be set on the receiver address after receiving assets. #### Parameters | Name | Type | Description | | ------------------ | :-------: | ----------------------------------------------------------------------------- | | `receiver` | `address` | The address receiving the asset and where the LSP5 data keys should be added. | | `assetAddress` | `address` | The address of the asset being received (_e.g: an LSP7 or LSP8 token_). | | `assetInterfaceId` | `bytes4` | The interfaceID of the asset being received. | #### Returns | Name | Type | Description | | ---------------- | :---------: | -------------------------------------------------------------------- | | `lsp5DataKeys` | `bytes32[]` | An array Data Keys used to update the [LSP-5-ReceivedAssets] data. | | `lsp5DataValues` | `bytes[]` | An array Data Values used to update the [LSP-5-ReceivedAssets] data. |
### generateSentAssetKeys :::caution Warning Returns empty arrays when encountering errors. Otherwise the arrays must have at least 3 data keys and 3 data values. ::: ```solidity function generateSentAssetKeys( address sender, address assetAddress ) internal view returns (bytes32[] lsp5DataKeys, bytes[] lsp5DataValues); ``` Generate an array of Data Key/Value pairs to be set on the sender address after sending assets. #### Parameters | Name | Type | Description | | -------------- | :-------: | ----------------------------------------------------------------------------- | | `sender` | `address` | The address sending the asset and where the LSP5 data keys should be updated. | | `assetAddress` | `address` | The address of the asset that is being sent. | #### Returns | Name | Type | Description | | ---------------- | :---------: | -------------------------------------------------------------------- | | `lsp5DataKeys` | `bytes32[]` | An array Data Keys used to update the [LSP-5-ReceivedAssets] data. | | `lsp5DataValues` | `bytes[]` | An array Data Values used to update the [LSP-5-ReceivedAssets] data. |
### getLSP5ArrayLengthBytes ```solidity function getLSP5ArrayLengthBytes(contract IERC725Y erc725YContract) internal view returns (bytes); ``` Get the raw bytes value stored under the `_LSP5_RECEIVED_ASSETS_ARRAY_KEY`. #### Parameters | Name | Type | Description | | ----------------- | :-----------------: | ----------------------------------------------- | | `erc725YContract` | `contract IERC725Y` | The contract to query the ERC725Y storage from. | #### Returns | Name | Type | Description | | ---- | :-----: | ----------------------------------------------- | | `0` | `bytes` | The raw bytes value stored under this data key. |
--- # LSP6Utils :::info Standard Specifications [`LSP-6-KeyManager`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md) ::: :::info Solidity implementation [`LSP6Utils.sol`](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp6-contracts/contracts/LSP6KeyManager.sol) ::: > LSP6 Utility library. LSP6Utils is a library of utility functions that can be used to retrieve, check and set LSP6 permissions stored under the ERC725Y storage of a smart contract. Based on the LSP6 Key Manager standard. ## Internal Methods Any method labeled as `internal` serves as utility function within the contract. They can be used when writing solidity contracts that inherit from this contract. These methods can be extended or modified by overriding their internal behavior to suit specific needs. Internal functions cannot be called externally, whether from other smart contracts, dApp interfaces, or backend services. Their restricted accessibility ensures that they remain exclusively available within the context of the current contract, promoting controlled and encapsulated usage of these internal utilities. ### getPermissionsFor :::info If the raw value fetched from the ERC725Y storage of `target` is not 32 bytes long, this is considered like _"no permissions are set"_ and will return 32 x `0x00` bytes as `bytes32(0)`. ::: ```solidity function getPermissionsFor(contract IERC725Y target, address caller) internal view returns (bytes32); ``` Read the permissions of a `caller` on an ERC725Y `target` contract. #### Parameters | Name | Type | Description | | -------- | :-----------------: | ----------------------------------------------------- | | `target` | `contract IERC725Y` | An `IERC725Y` contract where to read the permissions. | | `caller` | `address` | The controller address to read the permissions from. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------------------------ | | `0` | `bytes32` | A `bytes32` BitArray containing the permissions of a controller address. |
### getAllowedCallsFor ```solidity function getAllowedCallsFor(contract IERC725Y target, address from) internal view returns (bytes); ```
### getAllowedERC725YDataKeysFor ```solidity function getAllowedERC725YDataKeysFor(contract IERC725Y target, address caller) internal view returns (bytes); ``` Read the Allowed ERC725Y data keys of a `caller` on an ERC725Y `target` contract. #### Parameters | Name | Type | Description | | -------- | :-----------------: | ----------------------------------------------------- | | `target` | `contract IERC725Y` | An `IERC725Y` contract where to read the permissions. | | `caller` | `address` | The controller address to read the permissions from. | #### Returns | Name | Type | Description | | ---- | :-----: | --------------------------------------------------------------------------------------------------------- | | `0` | `bytes` | An abi-encoded array of allowed ERC725 data keys that the controller address is allowed to interact with. |
### hasPermission ```solidity function hasPermission( bytes32 controllerPermissions, bytes32 permissionToCheck ) internal pure returns (bool); ``` Compare the permissions `controllerPermissions` of a controller address to check if they includes the permissions `permissionToCheck`. #### Parameters | Name | Type | Description | | ----------------------- | :-------: | --------------------------------------------------------------------------------- | | `controllerPermissions` | `bytes32` | The permissions of an address. | | `permissionToCheck` | `bytes32` | The permissions to check if the controller has under its `controllerPermissions`. | #### Returns | Name | Type | Description | | ---- | :----: | ---------------------------------------------------------------------------------- | | `0` | `bool` | `true` if `controllerPermissions` includes `permissionToCheck`, `false` otherwise. |
### isCompactBytesArrayOfAllowedCalls ```solidity function isCompactBytesArrayOfAllowedCalls( bytes allowedCallsCompacted ) internal pure returns (bool); ``` Same as `LSP2Utils.isCompactBytesArray` with the additional requirement that each element must be 32 bytes long. #### Parameters | Name | Type | Description | | ----------------------- | :-----: | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `allowedCallsCompacted` | `bytes` | A compact bytes array of tuples `(bytes4,address,bytes4,bytes4)` to check (defined as `(bytes4,address,bytes4,bytes4)[CompactBytesArray]` in LSP6). | #### Returns | Name | Type | Description | | ---- | :----: | -------------------------------------------------------------------------------------------------------------- | | `0` | `bool` | `true` if the value passed is a valid compact bytes array of bytes32 AllowedCalls elements, `false` otherwise. |
### isCompactBytesArrayOfAllowedERC725YDataKeys ```solidity function isCompactBytesArrayOfAllowedERC725YDataKeys( bytes allowedERC725YDataKeysCompacted ) internal pure returns (bool); ``` Same as `LSP2Utils.isCompactBytesArray` with the additional requirement that each element must be from 1 to 32 bytes long. #### Parameters | Name | Type | Description | | --------------------------------- | :-----: | -------------------------------------------------------------------------------------------------------------------------------------- | | `allowedERC725YDataKeysCompacted` | `bytes` | a compact bytes array of ERC725Y data Keys (full bytes32 data keys or bytesN prefix) to check (defined as `bytes[CompactBytesArray]`). | #### Returns | Name | Type | Description | | ---- | :----: | ------------------------------------------------------------------------------------------------------------------ | | `0` | `bool` | `true` if the value passed is a valid compact bytes array of bytes32 Allowed ERC725Y data keys, `false` otherwise. |
### setDataViaKeyManager ```solidity function setDataViaKeyManager( address keyManagerAddress, bytes32[] keys, bytes[] values ) internal nonpayable returns (bytes result); ``` Use the `setData(bytes32[],bytes[])` function via the KeyManager on the target contract. #### Parameters | Name | Type | Description | | ------------------- | :---------: | ----------------------------------- | | `keyManagerAddress` | `address` | The address of the KeyManager. | | `keys` | `bytes32[]` | The array of `bytes32[]` data keys. | | `values` | `bytes[]` | The array of `bytes[]` data values. |
### combinePermissions ```solidity function combinePermissions( bytes32[] permissions ) internal pure returns (bytes32); ``` Combine multiple permissions into a single `bytes32`. Make sure that the sum of the values of the input array is less than `2^256-1 to avoid overflow. #### Parameters | Name | Type | Description | | ------------- | :---------: | ------------------------------------ | | `permissions` | `bytes32[]` | The array of permissions to combine. | #### Returns | Name | Type | Description | | ---- | :-------: | ------------------------------------------------------ | | `0` | `bytes32` | A `bytes32` value containing the combined permissions. |
### generateNewPermissionsKeys ```solidity function generateNewPermissionsKeys(contract IERC725Y account, address controller, bytes32 permissions) internal view returns (bytes32[] keys, bytes[] values); ``` Generate a new set of 3 x LSP6 permission data keys to add a new `controller` on `account`. #### Parameters | Name | Type | Description | | ------------- | :-----------------: | ----------------------------------------------------------------------------------------------- | | `account` | `contract IERC725Y` | The ERC725Y contract to add the controller into (used to fetch the `LSP6Permissions[]` length). | | `controller` | `address` | The address of the controller to grant permissions to. | | `permissions` | `bytes32` | The `BitArray` of permissions to grant to the controller. | #### Returns | Name | Type | Description | | -------- | :---------: | --------------------------------------- | | `keys` | `bytes32[]` | An array of 3 x data keys containing: | | `values` | `bytes[]` | An array of 3 x data values containing: |
### getPermissionName ```solidity function getPermissionName(bytes32 permission) internal pure returns (string); ``` Returns the name of the permission as a string. #### Parameters | Name | Type | Description | | ------------ | :-------: | ----------------------------------------------------------------------------------- | | `permission` | `bytes32` | The low-level `bytes32` permission as a `BitArray` to get the permission name from. | #### Returns | Name | Type | Description | | ---- | :------: | -------------------------------------------------- | | `0` | `string` | The string name of the `bytes32` permission value. |
--- --- title: ⛽️ Execute Relay Call (Meta Transactions) sidebar_position: 7 --- # Execute Relay Call ## Sequential relay calls in the same channel When executing 3 sequential relay calls with sequential nonces in a single channel (= nonces from the KeyManager retrieved via [`getNonce`](../contracts/LSP6KeyManager/LSP6KeyManager.md#getnonce), keep in mind that **if the first transaction does revert, the next 2 will revert in turns**. That happens because a Key Manager nonce is assigned to each relay call. E.g.: - First relay call - nonce is 4 - Second relay call - nonce is 5 - Third relay call - nonce is 6 One of the requirements for executing a relay call is that **the latest nonce (for a specific signer) stored on-chain in the Key Manager contract must be the same as the one used when signing the executed relay call**. After each successful execution, the on-chain nonce is incremented. Given the example above, the on-chain nonce is 4 and we are executing the relay calls. **If the first relay call pass ✅** - First relay call: nonce was 4 -> incremented to 5 - Second relay call: nonce was 5 -> incremented to 6 - Third relay call: nonce was 6 -> incremented to 7 **If the first relay call fails ❌** - **First relay call reverts ❌** nonce was 4 -> nonce remains 4 - Second relay call: nonce on-chain is 4 -> nonce used to sign was 5 = reverts ❌ with [`InvalidRelayNonce`](../contracts//LSP6KeyManager/LSP6KeyManager.md#invalidrelaynonce) - Third relay call: nonce on-chain is 5 -> nonce used to sign was 6 = reverts ❌ with [`InvalidRelayNonce`](../contracts//LSP6KeyManager/LSP6KeyManager.md#invalidrelaynonce) --- --- sidebar_label: '🔂 Follower System' sidebar_position: 8 description: How to interact with and implement the LUKSO LSP26 Follower System in your dApps and smart contracts. --- # Follower System The LSP26 Follower System provides a standardized way to manage social connections on-chain. This guide will help you understand how to interact with the LSP26 contract. ## Interacting with the LSP26 - Follower System Contract ### Following an Address To follow an address, call the `follow` function: ```solidity function follow(address addr) external; ``` Example usage: ```javascript await followerSystemContract.follow(addressToFollow); ``` ### Unfollowing an Address To unfollow an address, use the `unfollow` function: ```solidity function unfollow(address addr) external; ``` Example usage: ```javascript await followerSystemContract.unfollow(addressToUnfollow); ``` ### Checking Follow Status To check if one address is following another: ```solidity function isFollowing(address follower, address addr) external view returns (bool); ``` Example usage: ```javascript const isFollowing = await followerSystemContract.isFollowing( followerAddress, followedAddress, ); ``` ### Retrieving Follower and Following Counts To get the number of followers or followed addresses: ```solidity function followerCount(address addr) external view returns (uint256); function followingCount(address addr) external view returns (uint256); ``` Example usage: ```javascript const followers = await followerSystemContract.followerCount(address); const following = await followerSystemContract.followingCount(address); ``` ## Best Practices 1. **Batch Operations**: For following or unfollowing multiple addresses at once, use the `followBatch` and `unfollowBatch` functions to save on gas costs. 2. **Pagination**: When retrieving large lists of followers or following, use the paginated `getFollowersByIndex` and `getFollowsByIndex` functions to avoid gas limits and improve performance. 3. **Event Listening**: Set up event listeners for the `Follow` and `Unfollow` events to keep your dApp's state in sync with on-chain changes. 4. **LSP1 Integration**: If your dApp interacts with LSP1-compatible contracts, be prepared to handle the LSP26 follow/unfollow notifications through the `universalReceiver` function. --- --- title: 🔐 Key Manager sidebar_position: 2 --- # Key Manager The Key Manager uses the concept of [permissions](/docs/standards/access-control/lsp6-key-manager.md#permissions) to _authorize_ any addresses (dApps, protocols, devices, etc…) to do certain specific actions on the contract it is linked to. But why should you give anybody access to your smart contract? What is the intention behind doing this? A Key Manager can be used with different setups by being linked to: - **a LSP0ERC725Account like a Universal Profile**: to access your UP from other devices (that hold private keys), give access to some of your UP's functionalities to some dApps, or to create a DAO. - **a Token contract**: to manage a token or NFT collection that was created in collaboration with multiple brands. ## Example of permissions usage ### For a Universal Profile When looking at your Universal Profile within the 🆙 Browser Extension, your EOA / private keys held within your device (Browser or Mobile) is _the address that holds all the permissions_. We refer to this as the **main controller**. You can then grant partial access to any address so that they can use your Universal Profile to interact on your behalf in a controlled manner. For example: | Example | Description | Permissions | | :-------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------- | | Treasury & Funds Manager | Allow certain addresses to transfer your native tokens (or any LSP7 tokens) to certain specific addresses (_e.g: allow a crypto accountant or treasury manager to manage your funds on your behalf, allow a video game dApp to transfer the game tokens, etc..._) | `SUPER_TRANSFERVALUE`
or `TRANSFERVALUE` + Allowed Calls on specific addresses
or `CALL` + Allowed Calls on certain token addresses. | | Brand Manager | Allow certain addresses representing Marketing managers to either manage the metadata (and branding) of your Universal Profile, or the metadata of any NFT collections created by your Universal Profile. | `SETDATA` + Allowed ERC725Y Data Keys to manage the UP
`CALL` + Allowed Calls on specific NFT collection contract addresses. | | Metadata Manager | Allow certain dApps to store some user settings related to the dApp under the Universal Profile's storage, and allow each specific dApp to update these specific data only. | `SETDATA` + Allowed ERC725Y Data Keys | | Universal Receiver Delegate | Allow your Universal Receiver Delegate to operate automatically when receiving tokens or NFTs (_e.g: add / remove them in your received assets, automatically transfer a certain percentage of tokens received into a saving vault, save certain valuable NFTs into a vault, etc..._) | | | Social Recovery | Plug a service to gain you back access to your 🆙 if you have a lost access to your main controller private key / address. | `ADDCONTROLLER` | | Automated Trading | Allow a defi protocol to automatically transfer certain tokens automatically on your behalf for trading purpose | `CALL` + Allowed Calls on certain token addresses. | Using the Key Manager's permissions for a Universal Profile enables to catalyze interactions on the blockchain. Instead of requiring the main profile owner to have to do _"everything by himself / herself"_ and perform any single actions, any permissioned addresses (trusted users, dapps, smart contracts behind protocols, third party services) can perform the action themselves in a restricted manner, without having to wait for the user to complete the action. ## Allowed ERC725Y Data Keys :::note If controller has `SETDATA` permission but has no `AllowedERC725YDataKeys`, controller will not be able to use the `SETDATA` permission at all. ::: Key Manager allows for restricting controller addresses to change only specific or dynamic data keys. In order to achieve such functionality: 1. encode a set of data keys as [`bytes[CompactBytesArray]`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#bytescompactbytesarray) 2. store them under the data key [`AllowedERC725YDataKeys`](/standards/access-control/lsp6-key-manager.md#allowed-erc725y-data-keys). ### Specific Data Keys A _Specific Data Key_ must have the length of 32 bytes. Setting a _Specific Data Key_ in the [Allowed ERC725Y Data Keys](/standards/access-control/lsp6-key-manager.md#allowed-erc725y-data-keys) will allow the controller to only modify the data value of that _Specific Data Key_. ### Dynamic Data Keys A _Dynamic Data Key_ can have any length between 0 and 32 (except 0 and 32). Setting a _Dynamic Data Key_ in the [Allowed ERC725Y Data Keys](/standards/access-control/lsp6-key-manager.md#allowed-erc725y-data-keys) will allow the controller to modify the data value of any data key that starts exactly with that _Dynamic Data Key_. Example: Dynamic Data Key - `0xcafe0000cafe0000beef0000beef` | Data key | Can modify data value? | | :------------------------------------------------------------------- | :--------------------- | | `0xcafe0000cafe0000beef0000beef000000000000000000000000000000000000` | ✅ | | `0xcafe0000cafe0000beef0000beef000000000000000000000000000000000123` | ✅ | | `0xcafe0000cafe0000beef0000beefcafecafecafecafecafecafecafecafecafe` | ✅ | | `0x0000000000000000000000000000cafecafecafecafecafecafecafecafecafe` | ❌ | | `0x000000000000000000000000000000000000cafe0000cafe0000beef0000beef` | ❌ | ## Allowed Calls :::note If controller has `CALL` permission but has no `AllowedCalls`, controller will not be able to use the `CALL` permission at all. ::: Key Manager allows for restricting controller addresses to be able to call specific functions on specific addresses which should be of a specific standard. In order to achieve such functionality one could encode a set of type calls, addresses, standards and functions to [`bytes[CompactBytesArray]`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#bytesncompactbytesarray), and store them under the [Allowed Calls](../../standards/access-control/lsp6-key-manager.md#allowed-calls) data key. _E.g._ Supposedly we have the following `AllowedCalls`: `0x002000000002cafecafecafecafecafecafecafecafecafecafe24871b3d7f23690c002000000003cafecafecafecafecafecafecafecafecafecafe24871b3d44c028fe` It can be decoded as: | Allowed Calls | | | | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | First allowed call | **Call Types** - `0x00000002` (Call)
**Address** - `0xcafecafecafecafecafecafecafecafecafecafe`
**Standard** - `0x24871b3d` (LSP0)
**Function** - `0x7f23690c` (`setData(bytes32,bytes)`) | - This allowed call permits the controller to use the function `setData(bytes32,bytes)` in the contract deployed at address `0xcafecafecafecafecafecafecafecafecafecafe`.
- When calling that function the operation type has to be `CALL` with no value being sent.
- The address `0xcafecafecafecafecafecafecafecafecafecafe` has to return true to `ERC165.supportsInterface(0x24871b3d)`. | | Second allowed call | **Call Types** - `0x00000003` (Transfervalue & Call)
**Address** - `0xcafecafecafecafecafecafecafecafecafecafe`
**Standard** - `0x24871b3d` (LSP0)
**Function** - `0x44c028fe` (`execute(uint256,address,uint256,bytes)`) | - This allowed call permits the controller to use the function `execute(uint256,address,uint256,bytes)` in the contract deployed at address `0xcafecafecafecafecafecafecafecafecafecafe`.
- When calling that function the operation type has to be `CALL`, you can send value as well.
- The address `0xcafecafecafecafecafecafecafecafecafecafe` has to return true to `ERC165.supportsInterface(0x24871b3d)`. | ## Implement custom permissions > **Note:** although custom permissions can be created, this might not prevent from collisions where third party applications may treat the same custom permission differently. The permission system of the Key Manager is versatile enough to allow new custom permissions to be created, for specific application use cases, aside from the default ones. Since the permissions use `bytes32` as type, the range is large enough to fit up to 256 permissions in total ([32 bytes = 256 bits](/standards/access-control/lsp6-key-manager#address-permissions)). For instance, data stored under some data keys could be very sensitive for some specific dApp (_e.g: represent the :up: user settings for this dApp._), and a developer might not necessarily want to use the **Allowed ERC725Y Data Keys** for this particular data key. The Solidity implementation of the Key Manager allows extend the verification logic to [implement custom permissions](https://github.com/lukso-network/lsp-smart-contracts/blob/8f0cfb2c573c44702d3155375b2d935b043416b3/contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol#L263-L275). This can be done by simply overriding some of the functions that check for permissions depending on the action being performed (the action being defined by the calldata sent and the function being called, like `setData(...)`, `execute(...)`, etc...). Below is a Solidity example of a custom Key Manager that can control a token contract and requires a specific permission to update the `LSP4Metadata`. ```solidity // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.5; // interfaces import {ILSP6KeyManager} from "@lukso/lsp6-contracts/contracts/ILSP6KeyManager.sol"; // modules import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {LSP6SetDataModule} from "@lukso/lsp6-contracts/contracts/LSP6SetDataModule.sol"; import {LSP6OwnershipModule} from "@lukso/lsp6-contracts/contracts/LSP6OwnershipModule.sol"; /// @title LSP6 Key Manager implementation to enable multiple owners with different permissions and roles /// to control an LSP7 or LSP8 Token (instead of having a single `owner()`). contract LSP6TokenManager is ILSP6KeyManager, ERC165, LSP6SetDataModule, LSP6OwnershipModule { using Address for *; using ECDSA for *; using LSP6Utils for *; /// @dev address of the LSP7/8 Token contract this Key Manager controls address private immutable _linkedToken; mapping(address => mapping(uint256 => uint256)) internal _nonceStore; constructor(address linkedToken_) { if (linkedToken_ == address(0)) revert InvalidLSP6Target(); _linkedToken = linkedToken_; } /// @dev permission required to update the `LSP4Metadata` data key via `setData(...)` on the token contract bytes32 constant _PERMISSION_UPDATE_TOKEN_METADATA = 0x0000000000000000000000000000000000000000000000000000000000400000; /// @dev keccak256('LSP4Metadata') --> from the LSP4 Standard /// This is defined in `LSP4Constants.sol`, but we write it here for better understanding. bytes32 constant _LSP4_METADATA_KEY = 0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e; /// @inheritdoc LSP6SetDataModule /// @dev implement a custom check to verify if the controller /// has the permission to update the token metadata function _getPermissionRequiredToSetDataKey( address controlledContract, bytes32 controllerPermissions, bytes32 inputDataKey, bytes memory inputDataValue ) internal view virtual override returns (bytes32) { if (inputDataKey == _LSP4_METADATA_KEY) { controllerPermissions.hasPermission( _PERMISSION_UPDATE_TOKEN_METADATA ); } super._getPermissionRequiredToSetDataKey( controlledContract, controllerPermissions, inputDataKey, inputDataValue ); } } ``` As you can see from the Solidity code snippet above, since the Key Manager is broken down in multiple modules for each set of permissions related to specific type of actions (`LSP6SetDataModule`, `LSP6OwnershipModule`), it is relatively easy to create a specific implementation by-reusing the same code and implement custom permissions check on top based on the examples above. ## Further Reading - [The Bytecode episode #4 (Youtube) - overview of the Solidity code of the `LSP6KeyManagerCore.sol` by Jean Cavallera](https://www.youtube.com/watch?v=2Sm9LsCPjdE) --- --- title: ⚙️ Extendable & Extension Contracts sidebar_position: 6 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Extendable & Extension Contracts Contracts that use the LSP17 standard are called **Extendable Contracts**. Meaning they can extend their functionalities by linking **Extension Contracts** to them for specific functionalities that they do not support natively. ## Extendable Contracts The list of extensions for specific functions are stored under the specific data keys under their ERC725Y storage. You can think of them as **Extension Hosts**. You can inherit the [`LSP17Extendable.sol`](../contracts/LSP17ContractExtension/LSP17Extendable.md) contract to create an extendable contract. To add an extension handler for a specific function selector, you can set the address of the extension contract under the `LSP17Extension:` data key as follow: - 10 bytes (= 20 hexadecimal characters): `LSP17Extension` Mapping data key prefix - 20 bytes (= 40 hexadecimal characters): the `bytes4` function selector right padded with 16 zero bytes. Now whenever a call is made to this function selector on the extendable contract, it will land in its `fallback` function. From there, the calldata will be forwarded to the retrieved extension contract address set above. ```solidity // SPDX-License-Identifier: MIT pragma solidity ~0.8.4; // libraries import { LSP2Utils } from "@lukso/lsp-smart-contracts/contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol"; // constants import { _LSP17_EXTENSION_PREFIX } from "@lukso/lsp-smart-contracts/contracts/LSP17ContractExtension/LSP17Constants.sol"; function generateLSP17ExtensionDataKey(bytes4 extensionSelector) pure returns (bytes32) { return LSP2Utils.generateMappingKey( _LSP17_EXTENSION_PREFIX, bytes20(extensionSelector) ); } ``` ```js import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; import { concat, zeroPadBytes } from 'ethers'; const extensionSelector = zeroPadBytes('0xcafecafe', 20); const dataKey = concat([ ERC725YDataKeys.LSP17.LSP17ExtensionPrefix, extensionSelector, ]); ``` :::warning Be aware that adding an extension that can `selfdestruct` itself can be dangerous. This can make the [`LSP17Extendable`](../contracts/LSP17ContractExtension/LSP17Extendable.md) contract vulnerable to [metamorphic contracts](https://twitter.com/samczsun/status/1660012956632104960). If this extension contract has been deployed at a pre-determined address with `CREATE2`, an attacker could `selfdestruct` it and deploy a new one with different runtime bytecode using `CREATE2` and the same salt and initialization code as on the first deployment. This can result in the new contract to have the same address but different functionality. An attacker can now use these new functionalities to perform malicious actions. ::: ### Forwarding native tokens received to extensions The [`LSP17Extendable`](../contracts/LSP17ContractExtension/LSP17Extendable.md) contract implementation does not forward by default the native tokens received by the contract to the extension contract. If you want your extension to receive native tokens, by forwarding them to the extension contract (for instance, for extensions that require native tokens as part of their logic, or to make the extendable contract to fully work as a _"proxy forwarder contract"_), you can override the [`_fallbackLSP17Extendable`](../contracts/LSP17ContractExtension/LSP17Extendable.md#_fallbacklsp17extendable) function. ## Extensions Contracts Extension contracts are contracts deployed on the network that aim to be used for extending functionalities that use the LSP17 standard. You can inherit the [`LSP17Extendable.sol`](../contracts/LSP17ContractExtension/LSP17Extendable.md) contract to create a contract extension. :::warning The extendable contract might forward the value that it received on extension call. If the extension you are creating is not intended to receive value, make sure to revert by adding a simple check: ```solidity if (msg.value == 0) revert(...) ``` **If your extension does not have a way to withdraw the native tokens, they will be stuck in the contract**. ::: ### Checking the amount of native tokens received by the extended contract You can use the function [`_extendableMsgValue()`](../contracts/LSP17ContractExtension/LSP17Extension.md#_extendablemsgvalue) function to check the amount of native tokens received by the extended contract in the first place. This function can be useful if you want to create a behaviour in your extension contract that takes into account that the `msg.value` received. For instance: - your extended contract received a specific amount of native tokens (_e.g: `_extendableMsgValue() == 1 ether`_). - your extended contract did not receive any native tokens at all (_e.g: `_extendableMsgValue() == 0`_). ## Difference between Inheriting and Extending The code of a smart contract can be either inherited or extended by an extendable smart contract. The idea of inheriting a Solidity contract is that the code or the function inherited will be included natively in the contract, so whenever someone calls the logic, it will be executed directly. ```mermaid sequenceDiagram participant User participant InheritedContract User ->> InheritedContract: Call Function InheritedContract-->>InheritedContract: Execute Logic InheritedContract -->> User: Return ``` Extending means the logic is borrowed from somewhere else. Whenever someone calls the extended smart contract, this contract calls the extension, and lets the logic execute from the extension. ```mermaid sequenceDiagram participant User participant ExtendableContract participant Extension User ->> ExtendableContract: Call Function ExtendableContract ->> Extension: Forward Call Extension -->> Extension: Execute Logic Extension -->> ExtendableContract: Return ExtendableContract -->> User: Return ``` ### Differences 1. **Flexibility:** Extensions are useful when a functionality is needed but the behavior is not certain. The extension can be changed later to a newer version that modifies the logic. With inheriting, the implementation logic is fixed permanently. 2. **Event Emission:** If event emission on the core contract is important, inheriting is the better choice. When extending functionality, the logic is triggered from the extension, and all events are emitted there. This could be problematic for dApps that require events to be on the same smart contract, not on a potentially changeable extension. 3. **Contract Size Limit:** Extensions are useful when a smart contract is expected to have many functionalities, but the smart contract cannot include all the logic due to a contract size limit. It works as a router; when called with a function, it checks its extension and calls it. 4. **Context Changing:** When the logic is implemented by inheriting, `msg.sender` will be the caller and `msg.value` will be the value sent. In the case of extending, the `msg.sender` in the function in the extension will be the extended contract. The function can still have access to the original initiator caller by using it from the extra appended calldata. But in case of the function being executed is calling another function, when inherited the caller will be the original contract, but in the case of extension, the caller will be the extension. This could be problematic or require different structural adjustments. --- --- title: 🔊 Universal Receiver sidebar_position: 3 --- # Universal Receiver Delegate There are two default implementations of the LSP1 Delegate contracts available, each for different use cases. | Contract | Description | | -------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | **[`LSP1UniversalReceiverDelegateUP.sol`](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP.md)** | Add feature to a `LSP0ERC725Account` to registered and un-register tokens (LSP7 and LSP8) and vaults (LSP9) received. | | **[`LSP1UniversalReceiverDelegateVault.sol`](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateVault.md)** | Add feature to a `LSP9Vault` to register and un-register tokens (LSP7 and LSP8). | ## Routing The Universal Profile implementation allows for attaching multiple instances of Universal Receiver Delegate to it. This is due to LSP1 Routing. You could have a single General Purpose Universal Receiver Delegate and multiple instances of Specific Universal Receiver Delegate. A General Purpose Universal Receiver Delegate has its address stored under the [LSP1UniversalReceiverDelegate Singleton](/standards/accounts/lsp1-universal-receiver-delegate.md#lsp1universalreceiverdelegate-singleton) data key. This contract will be called on any LSP1 hook, meaning that it can potentially react on any [TypeID](../type-ids.md#universal-receiver-type-ids). A Specific Universal Receiver Delegate has its address stored under the [LSP1UniversalReceiverDelegate Mapping](/standards/accounts/lsp1-universal-receiver-delegate.md#lsp1universalreceiverdelegate-mapping) data key. This contract will be called on specific LSP1 hook, depending on the [TypeID](../type-ids.md#universal-receiver-type-ids) that was passed as a parameter in the hook, meaning that it only reacts on a single specific [TypeID](../type-ids.md#universal-receiver-type-ids). --- --- title: Create a Non Fungible Token sidebar_position: 1 --- # Create a Non Fungible Token ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.4; // modules import { LSP8IdentifiableDigitalAsset } from "@lukso/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol"; // constants import { _LSP8_TOKENID_FORMAT_NUMBER } from "@lukso/lsp8-contracts/contracts/LSP8Constants.sol"; import { _LSP4_TOKEN_TYPE_COLLECTION } from "@lukso/lsp4-contracts/contracts/LSP4Constants.sol"; contract BasicNFTCollection is LSP8IdentifiableDigitalAsset { constructor( string memory nftCollectionName, string memory nftCollectionSymbol, address contractOwner ) LSP8IdentifiableDigitalAsset( nftCollectionName, nftCollectionSymbol, contractOwner, _LSP4_TOKEN_TYPE_COLLECTION, _LSP8_TOKENID_FORMAT_NUMBER ) { // contract logic goes here... } } ``` ## LSP8 NFT extensions The `@lukso/lsp8-contracts` package includes token extensions (similarly to OpenZeppelin contracts) that can be added through inheritance. This enables to include specific functionalities for building your token. | Extension contract | Description | | :---------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | [`LSP8Burnable.sol`](../../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md) | exposes a public `burn(...)` function that allows any NFT holder or operator to burn a specific NFT tokenId. | | [`LSP8CappedSupply.sol`](../../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.md) | enable to specify a maximum supply on deployment / initialization, which caps the maximum amount of NFT that can be minted in the collection. | | [`LSP8Enumerable.sol`](../../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md) | functionality to enumerate the list of NFTs in a collection. | --- --- title: Customize transfer behaviour sidebar_position: 2 --- # Customize transfer behaviour The `LSP8IdenfitiableDigitalAsset` contract implementation includes the `_beforeTokenTransfer` and `_afterTokenTransfer` functions that offer the ability to specify custom logic that can run before or after the token transfer has happen (= before or after the balances in the contract state have been updated). --- --- title: 🖼️ Identifiable Digital Asset (NFT) sidebar_position: 5 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # LSP8 Identifiable Digital Asset :::danger Deprecation of `LSP8CompatibleERC721` The `LSP8CompatibleERC721` contracts have been deprecated and deleted from the [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts) package since version `0.15.0`, because of their unsafe nature and [security considerations (See PR #845 for more details)](https://github.com/lukso-network/lsp-smart-contracts/pull/845#issuecomment-1888671461). They are not recommended to be used. However, if you want to still use them, they remain available in the version [`0.14.0`](https://github.com/lukso-network/lsp-smart-contracts/releases/tag/lsp-smart-contracts-v0.14.0). ::: The **LSP8 Identifiable Digital Asset** contract is the newest advanced version of the existing ERC NFT standards, such as ERC721. LSP8 identifiable digital assets represent **N**on **F**ungible **T**okens (NFTs) that can be uniquely traded. Each NFT is identified with a tokenId, based on **[ERC721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol)** and can also have its own metadata set using the **[`setDataForTokenId(...)`](../../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatafortokenid)** function. A **bytes32** value is used for tokenId to allow many uses of token identification, including numbers, contract addresses, and hashed values (i.e., serial numbers). ## Installation & Usage The LSP8 smart contracts and their ABIs are available are available in their own individual package. To use them, install `@lukso/lsp8-contracts` as a dependency in your project. ``` npm install @lukso/lsp8-contracts ``` ``` yarn add @lukso/lsp8-contracts ``` ``` pnpm add @lukso/lsp8-contracts ``` `LSP8IdentifiableDigitalAsset.sol` is an `abstract` contract that is not deployable as is, because it does not contain any public functions by default to manage token supply (_e.g: no public `mint(...)` or `burn(...)` functions_). You can either: - use the `LSP8Mintable` preset contract that contains a public `mint(...)` function callable only by the contract's owner. - or extend the `LSP8IdentifiableDigitalAsset` contract (_see below_) and create your own supply mechanism by defining public methods that use the internal `_mint(...)` and `_burn(...)` functions. ## Comparisons with ERC721
Description ERC721 LSP8
Transferring tokens as an owner. transferFrom(address,address,uint256)
safeTransferFrom(address,address,uint256)
safeTransferFrom(address,address,uint256,bytes)
transfer(address,address,bytes32,bool,bytes)
Transferring tokens as an operator.
Approving an operator to spend tokens on behalf of the owner. approve(address,uint256) authorizeOperator(address,bytes32)
In comparison ERC721 has: - `safeTransferFrom(address,address,uint256,bytes)` - `safeTransferFrom(address,address,uint256)` - `transferFrom(address,address,uint256)` All of the above functions can be used by both the owner of the token id or by the operator of the token id in order to transfer the ERC721 token. To be mentioned, both functions `safeTransferFrom(...)` have a hook that calls the recipient contract. Looking at LSP7 & LSP8 we have unified `transfer(...)` & `transferBatch(...)` functions in both contracts. Those functions contain a hook which is executed conditionally and can be used in any of the above cases. --- --- title: Set NFT Metadata sidebar_position: 3 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Set NFT Metadata The function [`setDataBatchForTokenIds(...)`](../../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatabatchfortokenids) can be used to set multiple [data key-value](/standards/erc725.md#erc725y-generic-data-keyvalue-store) pairs at once for one or multiple tokenIds. ## Examples ### Set multiple metadata at once on the same tokenId To set for instance 3 x data key-value pairs for the same `tokenId`, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` can be used as follow: ```solidity // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.12; import { ILSP8IdentifiableDigitalAsset as ILSP8 } from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol"; import { _LSP4_METADATA_KEY } from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; bytes32 constant _NFT_ICON_DATA_KEY = keccak256("NFTIcon"); bytes32 constant _NFT_MARKET_PLACE_URLS__DATA_KEY = keccak256("NFTMarketplaceURLs"); bytes32 constant _TOKEN_ID_TO_SET = 0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe; function setMultipleDataForSingleTokenId( ILSP8 lsp8Contract, bytes memory lsp4MetadataValue, bytes memory nftIconValue, bytes memory nftMarketPlaceURLsValue ) { bytes32[] memory tokenIdsToUpdate = new bytes32[](3); bytes32[] memory dataKeysToSet = new bytes32[](3); bytes[] memory dataValuesToSet = new bytes[](3); // we are setting 3 x data key-value pairs for the same tokenid tokenIdsToUpdate[0] = _TOKEN_ID_TO_SET; tokenIdsToUpdate[1] = _TOKEN_ID_TO_SET; tokenIdsToUpdate[2] = _TOKEN_ID_TO_SET; dataKeysToSet[0] = _LSP4_METADATA_KEY; dataKeysToSet[1] = _NFT_ICON_DATA_KEY; dataKeysToSet[2] = _NFT_MARKET_PLACE_URLS__DATA_KEY; dataValuesToSet[0] = lsp4MetadataValue; dataValuesToSet[1] = nftIconValue; dataValuesToSet[2] = nftMarketPlaceURLsValue; lsp8Contract.setDataBatchForTokenIds( tokenIdsToUpdate, dataKeysToSet, dataValuesToSet ); } ``` ```js import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; const _NFT_ICON_DATA_KEY = keccak256('NFTIcon'); const _NFT_MARKET_PLACE_URLS__DATA_KEY = keccak256('NFTMarketplaceURLs'); const _TOKEN_ID_TO_SET = '0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe'; async function setMultipleDataForSingleTokenId( lsp8Contract, lsp4MetadataValue, nftIconValue, nftMarketPlaceURLsValue, ) { const tokenIdsToUpdate = [ _TOKEN_ID_TO_SET, _TOKEN_ID_TO_SET, _TOKEN_ID_TO_SET, ]; const dataKeysToSet = [ ERC725YDataKeys.LSP4.LSP4Metadata, _NFT_ICON_DATA_KEY, _NFT_MARKET_PLACE_URLS__DATA_KEY, ]; const dataValuesToSet = [ lsp4MetadataValue, nftIconValue, nftMarketPlaceURLsValue, ]; await lsp8Contract.setDataBatchForTokenIds( tokenIdsToUpdate, dataKeysToSet, dataValuesToSet, ); } ``` ### Set metadata on different tokenIds To set for instance the same data key-value pair (_e.g: `LSP4Metadata`_) for 3 x different `tokenId`s, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` can be used as follow: ```solidity // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.12; import { ILSP8IdentifiableDigitalAsset as ILSP8 } from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol"; import { _LSP4_METADATA_KEY } from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; bytes32 constant _FIRST_TOKEN_ID_TO_SET = 0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe; bytes32 constant _SECOND_TOKEN_ID_TO_SET = 0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef; bytes32 constant _THIRD_TOKEN_ID_TO_SET = 0xf00df00df00df00df00df00df00df00df00df00df00df00df00df00df00df00d; function setMultipleDataForSingleTokenId( ILSP8 lsp8Contract, bytes memory firstTokenIdLsp4MetadataValue, bytes memory secondTokenIdLsp4MetadataValue, bytes memory thirdTokenIdLsp4MetadataValue ) { bytes32[] memory tokenIdsToUpdate = new bytes32[](3); bytes32[] memory dataKeysToSet = new bytes32[](3); bytes[] memory dataValuesToSet = new bytes[](3); tokenIdsToUpdate[0] = _FIRST_TOKEN_ID_TO_SET; tokenIdsToUpdate[1] = _SECOND_TOKEN_ID_TO_SET; tokenIdsToUpdate[2] = _THIRD_TOKEN_ID_TO_SET; // we are setting the metadata for 3 x different tokenIds dataKeysToSet[0] = _LSP4_METADATA_KEY; dataKeysToSet[1] = _LSP4_METADATA_KEY; dataKeysToSet[2] = _LSP4_METADATA_KEY; dataValuesToSet[0] = firstTokenIdLsp4MetadataValue; dataValuesToSet[1] = secondTokenIdLsp4MetadataValue; dataValuesToSet[2] = thirdTokenIdLsp4MetadataValue; lsp8Contract.setDataBatchForTokenIds( tokenIdsToUpdate, dataKeysToSet, dataValuesToSet ); } ``` ```js import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; const _FIRST_TOKEN_ID_TO_SET = '0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe'; const _SECOND_TOKEN_ID_TO_SET = '0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef'; const _THIRD_TOKEN_ID_TO_SET = '0xf00df00df00df00df00df00df00df00df00df00df00df00df00df00df00df00d'; async function setMultipleDataForSingleTokenId( lsp8Contract, firstTokenIdLsp4MetadataValue, secondTokenIdLsp4MetadataValue, thirdTokenIdLsp4MetadataValue, ) { const tokenIdsToUpdate = [ _FIRST_TOKEN_ID_TO_SET, _SECOND_TOKEN_ID_TO_SET, _THIRD_TOKEN_ID_TO_SET, ]; const dataKeysToSet = [ ERC725YDataKeys.LSP4.LSP4Metadata, ERC725YDataKeys.LSP4.LSP4Metadata, ERC725YDataKeys.LSP4.LSP4Metadata, ]; const dataValuesToSet = [ firstTokenIdLsp4MetadataValue, secondTokenIdLsp4MetadataValue, thirdTokenIdLsp4MetadataValue, ]; await lsp8Contract.setDataBatchForTokenIds( tokenIdsToUpdate, dataKeysToSet, dataValuesToSet, ); } ``` ## Check if the metadata of a specific NFT (tokenId) has changed Since LSP8 uses [ERC725Y](/standards/erc725#erc725y-generic-data-keyvalue-store) under the hood, the URI pointing to the metadata of a specific tokenId can be changed inside the ERC725Y storage of the LSP8 contract. We have seen in the previous section [**how to set metadata for one or multiple tokenIds**](#setting-metadata-for-one-or-multiple-tokenids). The two functions `setDataForTokenId(...)` and `setDataBatchForTokenIds(...)` emit a [`TokenIdDataChanged`](../../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#tokeniddatachanged) event. You can listen for this event in the LSP8 contract from your dApp, filtering for the `LSP4Metadata` data key to check if the metadata of a tokenId has been changed. You can do so by filtering the first parameter with the `tokenId` and the second parameter with the [bytes32 value of the `LSP4Metadata` data key](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata). --- --- title: Create a Fungible Token sidebar_position: 1 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Create a Fungible Token ```solidity title="MyToken.sol" {8-14} showLineNumbers // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import {_LSP4_TOKEN_TYPE_TOKEN} from "@lukso/lsp4-contracts/contracts/LSP4Constants.sol"; import {LSP7DigitalAsset} from "@lukso/lsp7-contracts/contracts/LSP7DigitalAsset.sol"; contract MyToken is LSP7DigitalAsset( "MyToken", // token name "MTKN", // token symbol msg.sender, // contract owner _LSP4_TOKEN_TYPE_TOKEN, // token type as uint256 (0 for Token, 1 for NFT, 2 for Collection) false // make the token non divisible (true = 0 decimals, false = 18 decimals) ) { // Custom logic for your token... } ``` ```solidity title="MyToken.sol" {18-24} showLineNumbers // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import {_LSP4_TOKEN_TYPE_TOKEN} from "@lukso/lsp4-contracts/contracts/LSP4Constants.sol"; import {LSP7DigitalAsset} from "@lukso/lsp7-contracts/contracts/LSP7DigitalAsset.sol"; contract MyToken is LSP7DigitalAsset { /// @dev Available options for 4th parameter token type (uint256) /// - 0 for Token /// - 1 for NFT /// - 2 for Collection constructor( string memory name_, string memory symbol_, address contractOwner_, bool isNonDivisible_ ) LSP7DigitalAsset( name_, symbol_, contractOwner_, _LSP4_TOKEN_TYPE_TOKEN, isNonDivisible_ ) { // constructor logic ... } // Custom logic for your token... } ``` ## LSP7 Tokens extensions The `@lukso/lsp7-contracts` package includes token extensions (similarly to OpenZeppelin contracts) that can be added through inheritance. This enables to include specific functionalities for building your token. | Extension contract | Description | | :---------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- | | [`LSP7Burnable.sol`](../../contracts/LSP7DigitalAsset/extensions/LSP7Burnable.md) | Exposes a public `burn(...)` function that allows any token holder or operator to burn any amount of tokens. | | [`LSP7CappedSupply.sol`](../../contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.md) | Enable to specify a maximum supply on deployment / initialization, which caps the maximum amount of tokens that can be minted. | If your token contract uses the proxy pattern with initialize functions, use the `InitAbstract` version of these extension contracts (_e.g: `LSP7Burnable` -> `LSP7BurnableInitAbstract`_). ```solidity title="MyToken.sol" {19-20} showLineNumbers // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import { _LSP4_TOKEN_TYPE_TOKEN } from "@lukso/lsp4-contracts/contracts/LSP4Constants.sol"; import { LSP7DigitalAsset } from "@lukso/lsp7-contracts/contracts/LSP7DigitalAsset.sol"; // extensions import { LSP7Burnable } from "@lukso/lsp7-contracts/contracts/extensions/LSP7Burnable.sol"; import { LSP7CappedSupply } from "@lukso/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol"; contract MyToken is LSP7DigitalAsset( "MyToken", // token name "MTKN", // token symbol msg.sender, // contract owner _LSP4_TOKEN_TYPE_TOKEN, // token type as uint256 (0 for Token, 1 for NFT, 2 for Collection) false // make the token non divisible (true = 0 decimals, false = 18 decimals) ), LSP7Burnable, LSP7CappedSupply(42_000_000 * 10 ** super.decimals()) { function _mint( address to, uint256 amount, bool force, bytes memory data ) internal virtual override(LSP7CappedSupply, LSP7DigitalAsset) { LSP7CappedSupply._mint(to, amount, force, data); } // Custom logic for your token... } ``` ```solidity title="MyToken.sol" {23-25} showLineNumbers // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import { _LSP4_TOKEN_TYPE_TOKEN } from "@lukso/lsp4-contracts/contracts/LSP4Constants.sol"; import { LSP7DigitalAsset } from "@lukso/lsp7-contracts/contracts/LSP7DigitalAsset.sol"; // extensions import { LSP7Burnable } from "@lukso/lsp7-contracts/contracts/extensions/LSP7Burnable.sol"; import { LSP7CappedSupply } from "@lukso/lsp7-contracts/contracts/extensions/LSP7CappedSupply.sol"; contract MyToken is LSP7DigitalAsset, LSP7Burnable, LSP7CappedSupply { /// @dev Available options for 4th parameter token type (uint256) /// - 0 for Token /// - 1 for NFT /// - 2 for Collection constructor( string memory name_, string memory symbol_, address contractOwner_, bool isNonDivisible_, uint256 maxSupply_ ) LSP7DigitalAsset(name_, symbol_, contractOwner_, _LSP4_TOKEN_TYPE_TOKEN, isNonDivisible_) LSP7Burnable() LSP7CappedSupply(maxSupply_) { // constructor logic ... } function _mint( address to, uint256 amount, bool force, bytes memory data ) internal virtual override(LSP7CappedSupply, LSP7DigitalAsset) { LSP7CappedSupply._mint(to, amount, force, data); } // Custom logic for your token... } ``` --- --- title: Customize transfer behaviour sidebar_position: 2 --- # Customize transfer behaviour ## `_beforeTokenTransfer` and `_afterTokenTransfer` hooks `The LSP7DigitalAsset contract` implementation includes two hooks to add custom behaviour to run logic before or after the total supply of tokens has been updated in the contract's storage. This can be done via the [`_beforeTokenTransfer(...)`](../../contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_beforetokentransfer) and [`_afterTokenTransfer(...)`](../../contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_aftertokentransfer) functions. ### Solidity example Below is a simple pseudo-code example in Solidity where the `_afterTokenTransfer(...)` internal hook **registers the number of token transactions sent and received by any address**. Since a LSP7 token uses ERC725Y as storage under the hood, it provides a flexible way to add metadata. This example leverages this feature and provides a way to get a simple count of token transactions performed by each user in terms of tokens sent and received. It uses the following functions and libraries: - `_afterTokenTransfer(...)` hook to register the token transfer after it occurred. - The [ERC725Y](../../../standards/erc725.md#erc725y-data-representation) storage of the token contract where the transfer count will be stored (reading via [`_getData(...)`](../../contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_getdata), updating it via [`_setData(...)`](../../contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_setdata)). - We defined a specific data key where to store this info and used the [`LSP2Utils`](../../contracts/../libraries/LSP2Utils.md#generatemappingkey-2) library to encode this as a [`Mapping`](../../../standards/metadata/lsp2-json-schema.md#mapping) data key easily. ```solidity // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; // tokens import { _LSP4_TOKEN_TYPE_TOKEN } from "@lukso/lsp4-contracts/contracts/LSP4Constants.sol"; import { LSP7DigitalAsset } from "@lukso/lsp7-contracts/contracts/LSP7DigitalAsset.sol"; // libraries import { LSP2Utils } from "@lukso/lsp2-contracts/contracts/LSP2Utils.sol"; contract MyToken is LSP7DigitalAsset { /// @dev Available options for 4th parameter token type (uint256) /// - 0 for Token /// - 1 for NFT /// - 2 for Collection constructor( string memory name_, string memory symbol_, address contractOwner_, bool isNonDivisible_ ) LSP7DigitalAsset(name_, symbol_, contractOwner_, _LSP4_TOKEN_TYPE_TOKEN, isNonDivisible_) { // constructor logic ... } function _afterTokenTransfer( address from, address to, uint256, /* amount */ bytes memory /* data */ ) internal virtual override { // TokensSentTx:
bytes32 tokensSentTxDataKey = LSP2Utils.generateMappingKey({ keyPrefix: bytes10(keccak256("TokensSentTx")), bytes20Value: bytes20(from) }); // TokensReceivedTx:
bytes32 tokensReceivedTxDataKey = LSP2Utils.generateMappingKey({ keyPrefix: bytes10(keccak256("TokensReceivedTx")), bytes20Value: bytes20(to) }); bytes memory tokensSentTxValue = _getData(tokensSentTxDataKey); bytes memory tokensReceivedTxValue = _getData(tokensReceivedTxDataKey); // sanity check to ensure we can abi-decode correctly require(tokensSentTxValue.length == 32, "Invalid uint256 encoded value under `TokensSentTx:
` data key"); require( tokensReceivedTxValue.length == 32, "Invalid uint256 encoded value under `TokensReceivedTx:
data key" ); uint256 tokensSentTxCount = abi.decode(tokensSentTxValue, (uint256)); uint256 tokensReceivedTxCount = abi.decode(tokensReceivedTxValue, (uint256)); // increment the counter + set data in the storage tokensSentTxCount++; tokensReceivedTxCount++; _setData(tokensSentTxDataKey, abi.encode(tokensSentTxCount)); _setData(tokensReceivedTxDataKey, abi.encode(tokensReceivedTxCount)); } } ``` This example is minimalist and only stores a counter as a number. Still, any info related to the token transfer could be stored during the transfer (_e.g: the amount, the data passed, the gas price, the balance before and after, etc..._). This way, the storage of the token contract can act, for instance, as: - A _"mini explorer"_ for the token contract (without relying on a block explorer and reviewing the complete list of transactions). - To query the transactions for a user and provide an analytical view of their balance changes, demonstrating its data analysis capabilities. - Showcase which user, smart contract address or protocol are the most active users and traders for this token (being the ones with the higher count under the `TokensSentTx:
` data key). --- --- title: 🪙 Digital Asset (Token) sidebar_position: 4 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # LSP7 Digital Asset :::danger Deprecation of `LSP7CompatibleERC20` The `LSP7CompatibleERC20` contracts have been deprecated and deleted from the [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts) package since version `0.15.0`, because of their [unsafe nature and security considerations](https://github.com/lukso-network/lsp-smart-contracts/pull/845#issuecomment-1888671461). They are not recommended to be used. However, if you want to still use them, they remain available up to the version [`0.14.0`](https://github.com/lukso-network/lsp-smart-contracts/releases/tag/lsp-smart-contracts-v0.14.0). ::: The **LSP7 Digital Asset** contract is the newest advanced version of the existing ERC token standards, such as ERC20 and ERC1155. It comes with many features that enhance the security and the overall user experience and compatibility with [ERC725Accounts](/standards/accounts/lsp0-erc725account.md) and [Universal Receivers](/standards/accounts/lsp1-universal-receiver.md). The **LSP7DigitalAsset** contract represents digital assets for fungible tokens where minting and transferring are specified with an amount of tokens. Their functions were inspired from **[ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)** and **[ERC1155](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC1155/ERC1155.sol)** with more upgraded features. ## Installation & Usage The LSP7 smart contracts and their ABIs are available are available in their own individual package. To use them, install `@lukso/lsp7-contracts` as a dependency in your project. ``` npm install @lukso/lsp7-contracts ``` ``` yarn add @lukso/lsp7-contracts ``` ``` pnpm add @lukso/lsp7-contracts ``` `LSP7DigitalAsset.sol` is an `abstract` contract that is not deployable as is, because it does not contain any public functions by default to manage token supply (_e.g: no public `mint(...)` or `burn(...)` functions_). You can either: - the `LSP7Mintable` preset contract that contains a public `mint(...)` function callable only by the contract's owner. - or extend the `LSP7DigitalAsset` contract (_see below_) and create your own supply mechanism by defining public methods that use the internal `_mint(...)` and `_burn(...)` functions. ## Token Metadata LSP7 uses the **LSP4DigitalAssetMetadata** standard under the hood. Since LSP4 uses an **[ERC725Y General Data Key/Value Store](https://eips.ethereum.org/EIPS/eip-725)**, it allows any form of metadata to be defined and set. This could include things such as **list of creators, JSON files, exchanges where the token is listed, etc...** It is within this contract that the **Token-Metadata** (name and symbol) is set for the **LSP7DigitalAsset** on deployment / initialization. ## Example use cases An LSP7 can serves as: - a **Divisible Token Contract** when `isNonDivisible` bool is set to `false` in the [`constructor(...)`](#constructor) - otherwise serves as a **Non-Divisible Token Contract**. This can be useful to set `isNonDivisible` to `true`, rather than deploying a LSP8 contract to achieve the same goal. ## Comparisons with ERC20
Description ERC20 LSP7
Transferring tokens as an owner. transfer(address,uint256) transfer(address,address,uint256,bool,bytes)
Transferring tokens as an operator. transferFrom(address,address,uint256)
Approving an operator to spend tokens on behalf of the owner. approve(address,uint256) authorizeOperator(address,uint256)
In ERC20 the following functions can be used to transfer tokens from the token holder: - `transfer(address,uint256)` can only be used by the token holder. Therefore, the caller must be token holder. - `transferFrom(address,address,uint256)` can be used by operator to transfer tokens on behalf of a token holder (as long as this token holder has been approved and given an allowance). In comparison in LSP7, a single function `transfer(address,address,uint256,bool,bytes)` can be used by both operator and token owner. - if a token holder want to transfer its own token, it can call directly the function (be the caller) and specify its address for the first parameter `from`. - if an operator want to transfer tokens for a token holder that it has been approved for (via the `authorizeOperator(...)` function), it can call the function and specify the address of the token holder as the `from` address as well. Therefore as you can see from the table above, the only thing that changes when transferring token as a token owner or an operator is **the caller** of the function. **The parameters remain the same**. --- --- title: 🆙 Universal Profile sidebar_position: 1 --- # Universal Profile The `UniversalProfile.sol` smart contract is a combination of two LSP standards: - **[LSP0-ERC725Account Standard](/standards/accounts/lsp0-erc725account)** that also contains some LSP3Profile metadata, giving a "face and uniqueness" to the smart contract based account. - **[LSP3-UniversalProfile-Metadata Standard](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md)** The LSP3 Profile Metadata enables to give a "face" to the smart contract based account, making it distinguishable and unique from others Universal Profiles. A `UniversalProfile` as a smart contract can be used as a _blockchain-based account_ by humans, machines, organizations, or even other smart contracts. ## Functionalities & Behaviour A `UniversalProfile` has all the basic functionalities of an _Externally Owned Account_ (EOA), as well as the following functions that give the contract additional features: - [`execute(...)`](#execute) : enables to execute functions on other contracts, transfer value, or deploy new contracts. - [`isValidSignature(...)`](#isvalidsignature): delivers verification of signatures and signed messages from EOAs. - [`universalReceiver(...)`](#universalreceiver): brings notification of incoming calls and assets. - [`setData(...)`](#setdata): offers to set information in the account storage. All ownable functions such as [`execute(..)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#execute), [`executeBatch(..)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#executebatch), [`setData(..)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#setdata), [`setDataBatch(..)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#setdatabatch), [`transferOwnership(..)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#transferownership), and [`renounceOwnership(..)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#renounceownership) can be called by the owner The contract also includes the [LSP20-CallVerification](/standards/accounts/lsp0-erc725account.md#lsp20---call-verification) at its core. Meaning if the contract is owned by another contract, LSP20 enables to interact with the contract directly without having to resolve through its owner first. This allows seamless integrations with other contracts, protocols and dApps, as the contract can be called directly, making the developer experience easier. To illustrate, if another address than the owner calls the [`execute(..)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#execute) function, the account contract will: 1. Forward the call to the owner. 2. The execution of the function will only continue if the owner returns the `LSP20 MAGIC VALUE`, indicating that the caller is allowed to execute the function. The magic value can also determine if there should be any post-execution check on the owner. This same behavior applies to other ownable functions as well. The structure allows the account to have a more dynamic and adaptable approach for managing function execution logic, using the **LSP20-CallVerification** standard. ## Extensions An [`LSP0ERC725Account`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md) has the functionalities of [`LSP17Extendable`](/contracts/contracts/LSP17ContractExtension/LSP17Extendable.md) built-in. This allows extending its behavior with functions it does not support natively in its interface. However, calls to the `fallback` function will revert if no extension is registered for the function selector that was called. :::tip The only exception is the `0x00000000` function selector, which returns in order to allow the Universal Profile to act similarly to an EOA, and receive _"graffiti"_ data (when receiving native tokens or not) without executing anything else. ::: :::caution If your Universal Profile calls an extension to perform some security check, verification or validation, you should not rely on the extension to revert to ensure the validation failed, but check the `bytes` returned by the extension through [`_fallbackLSP17Extendable`](/contracts/contracts/LSP17ContractExtension/LSP17Extendable.md#_fallbacklsp17extendable). ::: :::caution Be aware of [phantom functions](https://dedaub.com/blog/phantom-functions-and-the-billion-dollar-no-op/) for functions in extensions with the `0x00000000` selector. For example, a contract might perform some kind of validation in an extension (_e.g: checking for permissions_), and expect the function to revert if the user is not authorized. However, since the function's selector is `0x00000000` and the LSP0 account doesn't have this extension registered, the `fallback` function will `return` instead of reverting, giving the contract the impression that the user is authorized. > See [`_fallbackLSP17Extendable`](/contracts/contracts/LSP17ContractExtension/LSP17Extendable.md#_fallbacklsp17extendable) for more details. In such case, make sure to double that an extension is registered first for the `0x00000000` selector via [`_getExtension`](/contracts/contracts/LSP17ContractExtension/LSP17Extendable.md#_getextension). ::: ## Adding metadata Unlike private keys and EOAs that cannot hold any metadata, a UniversalProfile is a blockchain based account that can have any info attached to it. You can do so using the [`setData(bytes32,bytes)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#setdata) and [`setDataBatch(bytes32[],bytes[])`](/contracts/contracts/UniversalProfile/UniversalProfile.md#setdatabatch) functions to add, update or delete any metadata in your Universal Profile. ### Updating your `LSP3Profile` metadata. The [`LSP3Profile`](/standards/metadata/lsp3-profile-metadata.md#lsp3profile) data key has a special meaning. It enables you to edit your profile details --- --- title: Universal Receiver Type IDs --- # Universal Receiver Type IDs The **LSP1 type Ids** listed below correspond to unique identifiers used across the LSP standards. They are used by various smart contracts to notify sender and recipients contracts implementing LSP1 about various incoming or outgoing information. For instance, notify a sender that some LSP7 tokens are being transferred from its balance, or a recipient about receiving some LSP7 tokens. The type Ids listed below can be exported and accessed from the `@lukso/lsp-smart-contracts` package as follow: ```js import { LSP1_TYPE_IDS } from "@lukso/lsp-smart-contracts"; // access the typeId related to being notified when receiving LYX (= native tokens) LSP1_TYPE_IDS. // access the typeId related to being notified when receiving LSP7 tokens LSP1_TYPE_IDS. ``` ## LSP0 - ERC725 Account ### `LSP0ValueReceived` | | | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `"LSP0ValueReceived"` | | **Hash** | `0x9c4705229491d365fb5434052e12a386d6771d976bea61070a8c694e8affea3d` | | **Used in:** | [`constructor(address)`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#constructor), [`receive()`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#receive), [`fallback(bytes)`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#fallback), [`execute(uint256,address,uint256,bytes)`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#execute), [`executeBatch(uint256[],address[],uint256[],bytes[])`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#executebatch), [`setData(bytes32,bytes)`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#setdata), [`setDataBatch(bytes32[],bytes[])`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#setdatabatch) | | **Solidity constant:** | `_TYPEID_LSP0_VALUE_RECEIVED` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP0ValueReceived` | ### `LSP0OwnershipTransferStarted` | | | | ------------------------ | ---------------------------------------------------------------------------------------------------- | | **Name** | `"LSP0OwnershipTransferStarted"` | | **Hash** | `0xe17117c9d2665d1dbeb479ed8058bbebde3c50ac50e2e65619f60006caac6926` | | **Used in:** | [`transferOwnership(address)`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#transferownership) | | **Solidity constant:** | `_TYPEID_LSP0_OwnershipTransferStarted` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP0OwnershipTransferStarted` | ### `LSP0OwnershipTransferred_SenderNotification` | | | | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `"LSP0OwnershipTransferred_SenderNotification"` | | **Hash** | `0xa4e59c931d14f7c8a7a35027f92ee40b5f2886b9fdcdb78f30bc5ecce5a2f814` | | **Used in:** | [`acceptOwnership()`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#acceptownership)
[`renounceOwnership()`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#renounceownership) | | **Solidity constant:** | `_TYPEID_LSP0_OwnershipTransferred_SenderNotification` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP0OwnershipTransferred_SenderNotification` | ### `LSP0OwnershipTransferred_RecipientNotification` | | | | ------------------------ | ----------------------------------------------------------------------------------------- | | **Name** | `"LSP0OwnershipTransferred_RecipientNotification"` | | **Hash** | `0xceca317f109c43507871523e82dc2a3cc64dfa18f12da0b6db14f6e23f995538` | | **Used in:** | [`acceptOwnership()`](./contracts/LSP0ERC725Account/LSP0ERC725Account.md#acceptownership) | | **Solidity constant:** | `_TYPEID_LSP0_OwnershipTransferred_RecipientNotification` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP0OwnershipTransferred_RecipientNotification` | ## LSP7 - Digital Asset ### `LSP7Tokens_SenderNotification` | | | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `"LSP7Tokens_SenderNotification"` | | **Hash** | `0x429ac7a06903dbc9c13dfcb3c9d11df8194581fa047c96d7a4171fc7402958ea` | | **Used in:** | [`_burn(address,uint256,bytes)`](./contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_burn),
[`_transfer(address,address,uint256,bool,bytes)`](./contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_transfer) | | **Solidity constant:** | `_TYPEID_LSP7_TOKENSSENDER` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP7Tokens_SenderNotification` | ### `LSP7Tokens_RecipientNotification` | | | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Name** | `"LSP7Tokens_RecipientNotification"` | | **Hash** | `0x20804611b3e2ea21c480dc465142210acf4a2485947541770ec1fb87dee4a55c` | | **Used in:** | [`_mint(address,uint256,bool,bytes)`](./contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_mint),
[`_transfer(address,address,uint256,bool,bytes)`](./contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_transfer) | | **Solidity constant:** | `_TYPEID_LSP7_TOKENSRECIPIENT` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP7Tokens_RecipientNotification` | ### `LSP7Tokens_OperatorNotification` | | | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `"LSP7Tokens_OperatorNotification"` | | **Hash** | `0x386072cc5a58e61263b434c722725f21031cd06e7c552cfaa06db5de8a320dbc` | | **Used in:** | [`authorizeOperator(address,uint256,bytes)`](./contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#authorizeoperator), [`revokeOperator(address,bool,bytes)`](./contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#revokeoperator), [`increaseAllowance(address,uint256,bytes)`](./contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#increaseallowance), [`decreaseAllowance(address,uint256,bytes)`](./contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#decreaseallowance) | | **Solidity constant:** | `_TYPEID_LSP7_TOKENOPERATOR` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP7Tokens_OperatorNotification` | ## LSP8 - Identifiable Digital Asset ### `LSP8Tokens_SenderNotification` | | | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `"LSP8Tokens_SenderNotification"` | | **Hash** | `0xb23eae7e6d1564b295b4c3e3be402d9a2f0776c57bdf365903496f6fa481ab00` | | **Used in:** | [`_burn(bytes32,bytes)`](./contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#_burn),
[`_transfer(address,address,bytes32,bool,bytes)`](./contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#_transfer) | | **Solidity constant:** | `_TYPEID_LSP8_TOKENSSENDER` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP8Tokens_SenderNotification` | ### `LSP8Tokens_RecipientNotification` | | | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Name** | `"LSP8Tokens_RecipientNotification"` | | **Hash** | `0x0b084a55ebf70fd3c06fd755269dac2212c4d3f0f4d09079780bfa50c1b2984d` | | **Used in:** | [`_mint(address,bytes32,bool,bytes)`](./contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#_mint),
[`_transfer(address,address,bytes32,bool,bytes)`](./contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#_transfer) | | **Solidity constant:** | `_TYPEID_LSP8_TOKENSRECIPIENT` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP8Tokens_RecipientNotification` | ### `LSP8Tokens_OperatorNotification` | | | | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `"LSP8Tokens_OperatorNotification"` | | **Hash** | `0x468cd1581d7bc001c3b685513d2b929b55437be34700410383d58f3aa1ea0abc` | | **Used in:** | [`authorizeOperator(address,bytes32,bytes)`](./contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#authorizeoperator), [`revokeOperator(address,bytes32,bool,bytes)`](./contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#revokeoperator) | | **Solidity constant:** | `_TYPEID_LSP8_TOKENOPERATOR` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP8Tokens_OperatorNotification` | ## LSP9 - Vault ### `LSP9ValueReceived` | | | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `"LSP9ValueReceived"` | | **Hash** | `0x468cd1581d7bc001c3b685513d2b929b55437be34700410383d58f3aa1ea0abc` | | **Used in:** | [`constructor(address)`](./contracts/LSP9Vault/LSP9Vault.md#constructor), [`receive()`](./contracts/LSP9Vault/LSP9Vault.md#receive), [`fallback(bytes)`](./contracts/LSP9Vault/LSP9Vault.md#fallback), [`execute(uint256,address,uint256,bytes)`](./contracts/LSP9Vault/LSP9Vault.md#execute), [`executeBatch(uint256[],address[],uint256[],bytes[])`](./contracts/LSP9Vault/LSP9Vault.md#executebatch) | | **Solidity constant:** | `_TYPEID_LSP9_VALUE_RECEIVED` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP9ValueReceived` | ### `LSP9OwnershipTransferStarted` | | | | ------------------------ | ------------------------------------------------------------------------------------ | | **Name** | `"LSP9OwnershipTransferStarted"` | | **Hash** | `0xaefd43f45fed1bcd8992f23c803b6f4ec45cf6b62b0d404d565f290a471e763f` | | **Used in:** | [`transferOwnership(address)`](./contracts/LSP9Vault/LSP9Vault.md#transferownership) | | **Solidity constant:** | `_TYPEID_LSP9_OwnershipTransferStarted` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP9OwnershipTransferStarted` | ### `LSP9OwnershipTransferred_SenderNotification` | | | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `"LSP9OwnershipTransferred_SenderNotification"` | | **Hash** | `0x0c622e58e6b7089ae35f1af1c86d997be92fcdd8c9509652022d41aa65169471` | | **Used in:** | [`acceptOwnership()`](./contracts/LSP9Vault/LSP9Vault.md#acceptownership)
[`renounceOwnership()`](./contracts/LSP9Vault/LSP9Vault.md#renounceownership) | | **Solidity constant:** | `_TYPEID_LSP9_OwnershipTransferred_SenderNotification` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP9OwnershipTransferred_SenderNotification` | ### `LSP9OwnershipTransferred_RecipientNotification` | | | | ------------------------ | ------------------------------------------------------------------------- | | **Name** | `"LSP9OwnershipTransferred_RecipientNotification"` | | **Hash** | `0x79855c97dbc259ce395421d933d7bc0699b0f1561f988f09a9e8633fd542fe5c` | | **Used in:** | [`acceptOwnership()`](./contracts/LSP9Vault/LSP9Vault.md#acceptownership) | | **Solidity constant:** | `_TYPEID_LSP9_OwnershipTransferred_RecipientNotification` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP9OwnershipTransferred_RecipientNotification` | ## LSP14 - Ownable 2-Step ### `LSP14OwnershipTransferStarted` | | | | ------------------------ | ---------------------------------------------------------------------------------------------------- | | **Name** | `"LSP14OwnershipTransferStarted"` | | **Hash** | `0xee9a7c0924f740a2ca33d59b7f0c2929821ea9837ce043ce91c1823e9c4e52c0` | | **Used in:** | [`transferOwnership(address)`](./contracts/LSP14Ownable2Step/LSP14Ownable2Step.md#transferownership) | | **Solidity constant:** | `_TYPEID_LSP14_OwnershipTransferStarted` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP14OwnershipTransferStarted` | #### `LSP14OwnershipTransferred_SenderNotification` | | | | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `"LSP14OwnershipTransferred_SenderNotification"` | | **Hash** | `0xa124442e1cc7b52d8e2ede2787d43527dc1f3ae0de87f50dd03e27a71834f74c` | | **Used in:** | [`acceptOwnership()`](./contracts/LSP14Ownable2Step/LSP14Ownable2Step.md#acceptownership)
[`renounceOwnership()`](./contracts/LSP14Ownable2Step/LSP14Ownable2Step.md#renounceownership) | | **Solidity constant:** | `_TYPEID_LSP14_OwnershipTransferred_SenderNotification` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP14OwnershipTransferred_SenderNotification` | #### `LSP14OwnershipTransferred_RecipientNotification` | | | | ------------------------ | ----------------------------------------------------------------------------------------- | | **Name** | `"LSP14OwnershipTransferred_RecipientNotification"` | | **Hash** | `0xe32c7debcb817925ba4883fdbfc52797187f28f73f860641dab1a68d9b32902c` | | **Used in:** | [`acceptOwnership()`](./contracts/LSP14Ownable2Step/LSP14Ownable2Step.md#acceptownership) | | **Solidity constant:** | `_TYPEID_LSP14_OwnershipTransferred_RecipientNotification` | | **Javascript constant:** | `LSP1_TYPE_IDS.LSP14OwnershipTransferred_RecipientNotification` | --- --- sidebar_label: '🌟 Benefits of LUKSO Standards' description: 'Overview of the benefits of using LUKSO Standard Proposals (LSPs)' --- # Benefits of the LUKSO Standards Discover the features and benefits of the LUKSO Standards (LSPs) compared to over standards and existing solutions. ## Universal Profiles vs. Smart Wallets Universal Profiles (known as 🆙) are smart accounts that come with many benefits because of their features. The [🆙 Browser Extension](/install-up-browser-extension) offers a better user experience to interact with dApps compared to traditional web3 wallets. | | Gnosis SAFE | Base Smart Contract Account | EIP 6900 Modular Smart Contract account | Universal Profiles | | ------------------------------ | -------------------------- | --------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------- | | Profile like information | ❌ | ❌ | ❌ | ✅ Through [LSP3](/standards/metadata/lsp3-profile-metadata) | | Generic Information Storage | ❌ | ❌ | ❌ | ✅ Through [ERC725Y](../standards/accounts/lsp0-erc725account.md#erc725y---generic-key-value-store) | | Notifications and Reactability | ❌ | ❌ | ❌ | ✅ Through [LSP1](../standards/accounts/lsp1-universal-receiver.md) | | Permission System | ❌ | ❌ | ❌ | ✅ Through [LSP6](../standards/access-control/lsp6-key-manager.md) | | Multisig | ✅ | ❌ | ❌ | 🔶 Can be controlled by a multisig | | Multi purpose | 🔶 (With future extension) | 🔶 (With future extension) | 🔶 (With future extension) | ✅ Can be a DAO, Organisation, Brand, AI, Robot, etc through and permissions [LSP6] | | Gasless Experience | ✅ | ✅ | ✅ | ✅ via the [Transaction Relayer](../standards/accounts/lsp15-transaction-relayer-api.md) | | Extensible | ✅ | ✅ | ✅ | ✅ Through [LSP17](../standards/accounts/lsp17-contract-extension.md) | | Upgradeable Security | ✅ | ✅ | ✅ | ✅ Through [LSP14](../standards/access-control/lsp14-ownable-2-step.md) | | Pre and Post Execution Hooks | ✅ | ✅ | ✅ | ✅ Through [LSP20](../standards/accounts/lsp20-call-verification.md) | | Feature | Benefits | | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [**🗄️ Metadata in one place**](#️-metadata-in-one-place) | Removes the requirement to refill the same information again and again on each new app you register to!
Your information is stored and fetched from the same place (your 🆙 storage) and displayed the same across all the dApps ecosystem! | | [**🎨 Customizable metadata**](#-customizable-metadata) | Make your Universal Profile stand out from others! Give it a profile and cover image, and add as many amount of information with its unlimited storage. | | [**⛽️ Gas-Less transactions**](#️-gas-less-transactions) | No more need to buy and hold native tokens to pay for the gas. Use the transaction relayer from [_universalprofile.cloud_](https://my.universalprofile.cloud/dashboard) plugged to the Universal Profile from the start to get started. | | [**🔑 Multi-Control with permissions**](#-multi-control-with-permissions) | Universal Profiles can be controlled by multiple addresses (EOAs and contracts) with various permission levels, held across different devices or representing dApps. Each can have specific access rights (token transfers, playlist management, account recovery, etc). | | **📢 Notification and customized reactivity** | The 🆙 can be customized to react differently based on different events it receives. For instance, the default implementation automatically register new received assets. | | **⚙️ Extendability with pluggable Extensions** | New features (like new function selectors not present by default in the smart contract code) can be added to a Universal Profile, using a system of extensions.

See our guide [**Extending Universal Profile functionalities**](./universal-profile/advanced-guides/extend-profile-functionalities.md) for more details. | ### 🗄️ Metadata in one place With traditional web3 wallets, a user has to fill the same infos every time it registers on a new dApp (_e.g: username, biography, social media accounts_). A Universal Profile stores user's data in one single place: the contract's storage. Any dApp can then retrieve the same information from the same place, making dApp onboarding easier and faster.

3 x different dApps (UniversalProfile.cloud, Universal.Page and UniversalSwaps.io) using the same Universal Profile data.

### 🎨 Customizable Metadata A Universal Profile can represent many personas or forms of identities: - a user profile (personal or professional) - a brand - a DAO or an organisation - an AI living on the internet - a service like a wallet recovery - a character in a video game (represented as an NFT with its own metadata)

4 x different Universal Profiles used for different purposes (a brand, a DAO, a user's profile, a wallet recovery service).

### ⛽️ Gas-Less transactions :::info Opting out of the relayer **Using the relayer and always gas less transactions is not mandatory!** Users can also choose not to rely on the [Transaction Relay Service](../standards/accounts/lsp15-transaction-relayer-api.md) and the pay the gas fees of the transaction themselves by funding the [controller](./concepts.md#controller) of their Universal Profile with native currency (_e.g: LYX_). ::: Universal Profiles enable gas-less transactions. The **relayer pays the gas fees and does not require the user to hold native tokens** to pay the transaction fees. Users do not need to go through the whole cumbersome process of: 1. downloading a wallet 2. creating a new address 3. registering to a crypto exchange or a service to buy crypto 4. performing KYC 5. buying native crypto by card or bank transfer 6. _in some cases,_ requesting the bank to authorize the transaction to buy crypto (some user banks restrict from buying crypto online) 7. finally start using dApps! This improves onboarding experiences in the following ways: - most of the new web3 users do not get their heads around the concept of "gas" and having to pay fees every time they interact with a dApp (compared to interacting with other applications on the internet). - native and experienced web3 users need to acquire more native currency from various chains just to _"play around with dApps"_ and explore, increasing the costs even more for users present across many chains. - users can also bridge native currency from one chain to another (_e.g: having to bridge ethers from Ethereum to Base to use dApps on Base_), but this requires giving up some funds on one chain as a result. - developers looking to build dApps on new chains need to acquire test LYX from testnet faucets, but most of them now require to hold a minimum amount of native currency on the mainnet to avoid spam and over-usage of the faucet. As Universal Profile supports gas-less transactions, it is possible to add multiple relayers and switch between them before the confirmation of the transaction. ### 🔑 Multi-Control with permissions Universal Profiles can be controlled through multiple EOAs (and their associated private keys), where each private key can be allowed or restricted to specific actions via permissions. These [**controllers**](./universal-profile/key-manager/get-controller-permissions.md) can be on multiple devices (laptop, desktop, mobile, hardware wallet like ledger) and represent: - EOAs or other 🆙 - dapps protocols (defi trading app, gaming app), granted specific access to the Universal Profile. Some real-life examples for a user's Universal Profile could be: - A defi app can transfer only a specific token to a particular pool for trading. - A music dApp can only update a list of music playlists in the Universal Profile's storage. - A family member can be granted recovery access for trusted third-party recovery. ## LSP7/8 Token standards vs. ERC20/721 :::success Useful guides Interested to migrate your token or NFT collection? See our hands-on developer guides: - [Migrate from ERC20 to LSP7](./migrate/migrate-erc20-to-lsp7.md) - [Migrate from ERC721 to LSP8](./migrate/migrate-erc721-to-lsp8.md) ::: ### ⚖️ ERC20 vs. LSP7 Transfer Authorization | Feature | ERC20 | LSP7 | | ------------------------ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | **Basic Approval** | ✅ Simple approve/allowance | ✅ Enhanced [authorizeOperator](/contracts/contracts/LSP7DigitalAsset/#authorizeoperator) with explicit operator notification callback | | **Recipient Validation** | ❌ No validation | ✅ [Force parameter](/contracts/contracts/LSP7DigitalAsset/#parameters-13) + recipient callbacks | | **Transfer Context** | ❌ None | ✅ [Optional data parameter](/contracts/contracts/LSP7DigitalAsset/#parameters-13) to add context to transfers | | **Transfer Hooks** | ❌ None | ✅ [LSP1](/standards/accounts/lsp1-universal-receiver.md) notifications for sender/receiver | | **Transfer Rejection** | ❌ Not possible | ✅ Recipients can reject transfers via custom [LSP1](/standards/accounts/lsp1-universal-receiver.md) Universal Receiver | | **Contextual Data** | ❌ None | ✅ Rich data with transfers | Below are the benefits offered by the LUKSO Token standards [**LSP7 Digital Asset**](../standards/tokens/LSP7-Digital-Asset.md) and [**LSP8 Identifiable Digital Asset**](../standards/tokens/LSP8-Identifiable-Digital-Asset.md). | Feature | Benefits | | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [**🔘 Easier functions for developers**](#-easier-functions-for-developers) | You are a developer? Stop learning different functions for each new ERC token standard! (ERC20, ERC721, ERC1155, etc...).
LSP7 and LSP8 use the **same function names** for transfer and operator approvals, whether it is a token or NFT transfer. | | [**🗄️ Unlimited & Dynamic Metadata for Tokens & NFTs**](#️-unlimited--dynamic-metadata) | Your NFT is not only an image. It can now hold as many information as can be imagined (custom traits, attributes, ...). This information can evolve overtime. | | **䷓ Flexible Batching functionalities** | Distribute multiple tokens or NFTs easily to users with [`transferBatch(...)`](../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#transferbatch) or perform multiple actions in a single transaction with [`batchCalls(...)`](../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#batchcalls).
_(e.g: authorize multiple operators, transfer an NFT and update its metadata)_. | | [**📢 Notify sender & recipient(s) on transfer and new operators**](#-notify-on-transfers) | Sender is notified _"I have sent tokens"_, recipient is notified _"I have received tokens"_ and both can have custom logic to react on these notifications.

**Finished the old _"`approve(...)` then `transferFrom(...)`"_ flow!**. Using the Universal Receiver and automatic reactions on notifications is the new way! | | **⚙️ Extendability with pluggable Extensions** | New features (like new function selectors not present by default in the smart contract code) can be added to a Digital Asset, using a system of extensions. | | [**✋🏻 Safety parameter (by default!) to prevent accidental transfers**](#-safety-to-prevent-accidental-transfers) | Prevent bad web3 user stories and reduce the number of Google searches for:
_"Transferred tokens to the wrong wallet address. How can I recover them?"_. | ### 🔘 Easier functions for developers Both [LSP7](../standards/tokens/LSP7-Digital-Asset.md) and [LSP8](../standards/tokens/LSP8-Identifiable-Digital-Asset.md) use the same function to transfer tokens, with only one different parameter type. - LSP7 [`transfer(address,address,uint256,bool,bytes)`](../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#transfer) function uses a **`uint256`** to transfer an **amount**. - LSP8 [`transfer(address,address,bytes32,bool,bytes)`](../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#transfer) function uses a **`bytes32`** to transfer a [**token ID**](../standards/tokens/LSP8-Identifiable-Digital-Asset.md#format-of-tokenids). Similarly, they both use the same function `authorizeOperator(address,[uint256/bytes32],bytes)` to approve new operators for a token allowance or specific token Ids. ### 🗄️ Unlimited & Dynamic Metadata

3 x different NFT collections with their unique traits and characteristics.

Like Universal Profile, digital assets based on the LSP7 and LSP8 standards can hold an **unlimited quantity of metadata** for any type of information considered relevant to the token or NFT collection. This can include: - Icons and image. - The creators of the tokens / NFT collection. - The list of exchanges where this token can be found. LSP8 also allows to create more complex and rich NFT collections where **each NFT can have its own custom metadata**. Setting metadata specific to each NFT is done using the standardized functions [`setDataForTokenId(...)` and `setDataBatchForTokenIds(...)`](../contracts/overview/NFT/set-nft-metadata.md). This is useful for instance for: - NFTs that need to hold specific items like digital clothing items for avatars, or weapons / body armors in a video game. - dynamic NFTs, where any information, traits or attributes of an NFT could be programmed to change or evolve overtime according to certain conditions, logics or triggers. ### 📢 Notify on transfers On each token transfers, bother sender & recipient are notified that a token transfer happened. This notification includes a specific notification ID (_e.g: "I have sent / received some tokens / NFTs"_. See typeIds for more infos). In addition, it is possible to program and _"plug-in"_ custom logic contracts called [**Universal Receiver Delegate**](../standards/accounts/lsp1-universal-receiver-delegate.md) to the sender and recipient, so that they can automatically react based on these different types of notifications. For example: - Registering / Removing tokens from your list of received assets. - Block incoming spam tokens that can contain malicious logic to steal user's funds if interacting with such token contracts, by filtering them against a spam or blacklist registry. - Forward automatically a certain percentage of the tokens received to a specific address (_e.g: a Vault to implement "save the change" schemes, a wallet for savings, a family member)_. - Implement automated mechanisms to re-distribute equally and proportionally the tokens received in a trustless manner (_e.g: distribute dividends to shareholders, or bonuses to employees._) In the web3 ecosystem, many contracts can hold, send and receive assets (_e.g: 🆙, Vaults, Marketplaces, Liquidity pools, etc..._). The [LSP1 Universal Receiver standard](../standards/accounts/lsp1-universal-receiver-delegate.md#how-delegation-works) offers many ways to build innovative automation systems on top of those, so that users can enjoy a better and safer experience interacting with digital assets on the blockchain. ### ✋🏻 Safety to prevent accidental transfers The `transfer(...)` function of [LSP7](../standards/tokens/LSP7-Digital-Asset.md) and [LSP8](../standards/tokens/LSP8-Identifiable-Digital-Asset.md) contains a [`bool force`](/standards/tokens/LSP7-Digital-Asset#force-mint-and-transfer) parameter to prevent accidental transfers like: - when an incorrect address was pasted in an input field on a dApp or blockchain explorer. - when an incorrect `address` parameter was passed within an internal transaction of a complex interaction. - when a smart contract does not have any functionality to transfer tokens, preventing the tokens from being stuck. - when transferring tokens to an EOA address, which should be for advanced users who use private keys / seed phrases and could loose access to funds in the future. The `bool force` parameter ensures that users and smart contracts are not transferring tokens to addresses that could potentially not hold or re-transfer the token. --- --- sidebar_label: '📘 Glossary' description: 'Most frequently used terminology related to the LUKSO Ecosystem: Universal Profiles, Controllers, Transaction Relay Service.' --- # Glossary :::info At LUKSO docs, use [ChefGPT](https://www.cookbook.dev/) for quick term explanations. Highlight any word and click `Ask Cookbook` in the Navbar for its definition. ::: ## Commonly Searched Terms | Topic | TL;DR | | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Controllers | Controllers are like little programs that are given specific permissions to do things to and with your Universal Profile. | | [Key Manager](/standards/access-control/lsp6-key-manager.md) | The Key Manager is essentially a place where you can manage permissions that other _things_ have on your Universal Profile. _Things_ could be other people's profiles, dapps, extensions....anything. | | [ERC725X](/standards/metadata/lsp2-json-schema.md) | ERC725X is a standard that defines how your Universal Profile works and how it can be used to manage your online identity and assets. It's like a set of rules that everyone agrees on, making it easier for different applications and platforms to understand and interact with your profile. | | [ERC725Y](/standards/erc725#erc725x) | ERC725Y is the basic tool that lets you store information, while LSP2 is the set of rules that makes sure everyone stores and retrieves this information in an organized and understandable way. | | [LYXt](../../docs/faq/lukso/general-information.md#whats-the-difference-between-lyxt-lyxe-and-lyx) | LYXt is the token for developers to use on our testnet. It can always be acquired by anyone for free. | | [LYXe](../../docs/faq/lukso/general-information.md#whats-the-difference-between-lyxt-lyxe-and-lyx) | LYXe is the token that was deployed on Ethereum before LUKSO Mainnet was launched. It allowed people to invest in LUKSO pre-launch. | | [Metadata](/standards/metadata/lsp3-profile-metadata.md) | This typically refers to the additional data that is stored against a token or NFT. The difference on LUKSO is it can be extended.

For example, imagine you've bought a house and have the deed as an NFT on LUKSO. Well now, as rennovations are carried out, they can be continually added to the NFT for history. | | Account Abstraction | Account abstraction is abstracting away smart contract execution from storing funds. With a smart contract account, you can program it to do all sorts of things. You can set up automatic payments, create multi-signature wallets that require multiple people to approve transactions, or even add security features like daily spending limits. It's like having a customizable, programmable bank account on the blockchain. | --- --- sidebar_label: '📃 Working with assets' sidebar_position: 4 description: Learn how to prepare and use assets for LUKSO Universal Profiles and digital assets (LSP7 / LSP8). --- # 📃 Working with assets When creating/editing Universal Profiles or Digital Assets, you will need to upload assets (such as images, icons, videos, etc.) and [metadata JSON files](../../standards/tokens/LSP4-Digital-Asset-Metadata.md). This can be tricky, but this guide will help you get through this process. ## Asset upload flow The asset upload flow works like this: 1. Upload each media file (icon, pictures, images, videos...) and get their URLs or IPFS CID (more info below). 2. With the file hashes and URLs, generate the final [LSP4 Metadata JSON file](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md) and upload this file to get its URL or IPFS CID. 3. Encode the LSP4 Metadata JSON file URL as a `VerifiableURI`. 4. Write the reference to the JSON file on the contract. ### Where to upload the files? **LSPs do not restrict you to a specific storage solution.** To upload the files (assets and metadata JSON file), you have mainly two options: - Centralised storage such as [AWS S3](https://aws.amazon.com/s3/), [Google Cloud](https://cloud.google.com/storage?hl=en), Dropbox... - Decentralised storage such as [IPFS](https://ipfs.tech/), [Arweave](https://www.arweave.org/), [Filecoin](https://filecoin.io/)... Centralized storage solutions are user-friendly and can be a good starting point for those new to the ecosystem or participating in hackathons. However, they rely on a single point of control, which may not align with the decentralized ethos of blockchain technology. Decentralized storage solutions align with the decentralized nature of blockchain and offer benefits like _redundancy_, _censorship resistance_, and _permanent storage_. However, they might be more complex to interact with. ## Generate the JSON File After uploading the media files, you can attach their links to a JSON file in the below structure. The JSON content is then used as input for encoding the metadata according to [LSP4](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4---digital-asset-metadata). :::tip Data Verification To ensure the authenticity of the images, please generate the hash of the uploaded files and attach the hash function and the actual hash in hex format within the `"verification"` field including a `"method"` and `"data"` entry. :::
LSP4 Example JSON File ```js { "LSP4Metadata": { "name": "My Token Name", "description": "Sample Description", "links": [{ "title": "My Website", "url": "https://my.website.com" }], "icon": [ { "width": 60, "height": 60, "url": "https://mycentralised-storage.com/filename.png" } ], "images": [ [ { "width": 1000, "height": 1000, "url": "https://centralised-cloud-storage.com/image.jpg", "verification": { "method": "keccak256(bytes)", "data": "0x" } } { "width": 500, "height": 500, "url": "ipfs://[IPFS-CID]", "verification": { "method": "keccak256(bytes)", "data": "0x" } } ] ], "assets": [], "attributes": [ { "key": "Standard type", "value": "LSP", "type": "string" }, { "key": "Standard number", "value": 4, "type": "number" } ] } } ```
Such JSON can be generated manually or using tools, such as [`@lukso/lsp-utils`](https://github.com/lukso-network/lsp-utils). To generate the JSON from predefined fields: 1. Install the `@lukso/lsp-utils` library ```bash npm i @lukso/lsp-utils ``` 2. Import the `generateLSP4JSON` to generate the JSON ```js import { generateLSP4JSON } from '@lukso/lsp-utils'; ``` Example: ```js const name = 'Test NFT'; const description = 'This is a test NFT collection'; const links = [ { title: 'Website', url: 'https://example.com' }, { title: 'Twitter', url: 'https://twitter.com/example' }, ]; const attributes = [ { key: 'trait', value: 'rare', type: 'string' }, { key: 'level', value: '5', type: 'number' }, ]; const hashVerification = { method: 'keccak256(bytes)', data: '0x6216ef2b4777755faa239eaf3c37c6e5bdf073b20d8b86a2bb5d214ff70194c2', }; const icons = { icons: [ { width: 200, height: 200, url: 'ipfs://QmWE3VGALUgQk1unq765vNbCf3zEYfBwtq1eAtQXLoi3vh', verification: hashVerification, }, { width: 400, height: 400, url: 'ipfs://QmWE3VGALUgQk1unq765vNbCf3zEYfBwtq1eAtQXLoi3vh', verification: hashVerification, }, ], lsp7images: [], lsp8images: [], }; const images = { imageFields: [ { images: [ { width: 1200, height: 1200, url: 'ipfs://QmWE3VGALUgQk1unq765vNbCf3zEYfBwtq1eAtQXLoi3vh', verification: hashVerification, }, { width: 800, height: 600, url: 'ipfs://QmWE3VGALUgQk1unq765vNbCf3zEYfBwtq1eAtQXLoi3vh', verification: hashVerification, }, ], lsp7images: [], lsp8images: [], }, ], }; const assets = { assets: [ { url: 'ipfs://QmWE3VGALUgQk1unq765vNbCf3zEYfBwtq1eAtQXLoi3vh', fileType: 'image/png', verification: hashVerification, }, ], lsp7assets: [], lsp8assets: [], }; const json = generateLSP4JSON( name, description, links, attributes, icons, images, assets, ); // // { // links: ... // description:... // } // ``` Now the JSON can be uploaded to IPFS. Other utility functions can be used to prepare the JSON to be converted to [VerifiableURI](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4metadata), such as creating the hash and encoding it as VerifiableURI. Check all functions related to metadata generating in [lsp-utils docs](../../tools/lsp-utils/LSP4DigitalAssetMetadata.md). ```js import { generateLSP4JSONWithHash } from '@lukso/lsp-utils'; import { generateLSP4JSONVerifiableURI } from '@lukso/lsp-utils'; const { json, hash } = generateLSP4JSONWithHash( name, description, links, attributes, icons, images, assets, ); const verifiableURI = generateLSP4JSONVerifiableURI( name, description, links, attributes, icons, images, assets, ); ``` The `generateLSP4JSONVerifiableURI` will return you directly what needs to be set in the smart contract, but it is slightly more expensive than uploading the JSON to IPFS and encoding the link, as the function encode the JSON as a base64 link. ## Encode the LSP4 Metadata To encode the LSP4 Metadata with ease, you can use the 🛠️ [`erc725.js`](../../tools/dapps/erc725js/getting-started.md) library. The tool provides all necessary LSP Schemas and the `encodeData()` function. ```js import { ERC725 } from '@erc725/erc725.js'; import LSP4DigitalAssetSchema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; const LSP4JSON = { /* Your JSON */ }; const encodedLSP4Metadata = ERC725.encodeData( { keyName: 'LSP4Metadata', value: { json: LSP4JSON, url: 'https://my-file-provider.com/my-file-link.json', // It can also be: ipfs://[CID] }, }, LSP4DigitalAssetSchema, ); ``` The encoded content will then look like the following:
LSP4 Encoded Contract Metadata ```js { keys: [ '0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e' ], values: [ '0x00006f357c6a0020610be5a5ebf25a8323ed5a9d8735f78aaf97c7e3529da7249f17e1b4129636f3697066733a2f2f516d5154716865424c5a466e5155787535524473387441394a746b78665a714d42636d47643973756b587877526d' ] } ```
## Write the value to the contract Now that you have they key to update and the value to write, you can use the [`setData()`](../../contracts/contracts/ERC725/ERC725.md#setdata) to update the contract. --- --- sidebar_label: '❓ Choose between LSP7 or LSP8' sidebar_position: 2 description: Discover which standard is best suited for your token or NFT project between LSP7 or LSP8. --- # Choose between LSP7 or LSP8 This page provides guidance on which standard and combination to choose for your project. Both LSP7 and LSP8 coupled with the `LSP4TokenType` data key allow to create NFT collections on LUKSO. From simple to more complex! ## Available Options There are 4 x main popular combination of LSP7 / LSP8 + the `LSP4TokenType`.
Description Standard LSP4 Token Type
LSP7 LSP8 (0) Token (1) NFT (2) Collection
Fungible Token
_"NFT-like"_ digital item with multiple ownable quantities
A collection of unique items
An _"umbrella"_ collection containing multiple sub-collections
```mermaid flowchart TD Start{"LSP4TokenType"} LSP7Token("LSP7 Token (e.g., **Dollar**, Euro)") LSP8Decision{"LSP7 or LSP8 NFT"} LSP8NFT("LSP8 NFT (e.g., mixed collection)") NFT("Unique NFT (e.g., unique watch collection, each watch is a one of a kind)") XYZ("NFT with multiple ownable quantities (e.g., t-shirt collection, same design in multiple quantities)") supportsInterface("supportsInterface") Start -->|"0"| LSP7Token Start -->|"1"| LSP8Decision Start -->|"2"| LSP8NFT LSP8Decision --> supportsInterface supportsInterface -->|"LSP7"| XYZ supportsInterface -->|"LSP8"| NFT ``` ## Fungible Token ### Characteristics - divisible (unless `decimals()` overwritten to `0`). - 18 decimals by default (unless overwritten to have less decimals, like USDT for example which has 6 decimals). - The `LSP4Metadata` represents the metadata of the fungible token. ### Example Use Cases - a digital currency - a meme coin - a share in a com - a voting token. - a reward token. - a utility token. --- ## Multiple Ownable Digital Items ### Characteristics - Non divisible (decimals is `0`). - Each items can't be uniquely identified by an ID in the collection. They are all the same. - All items share the same metadata. There is no metadata specific per item. - The `LSP4Metadata` represents the metadata of each item (they are all the same). ### Example Use Cases - a contract with 500 x digital t-shirts. - a contract with 1000 x digital tickets. --- ## Standard NFT Collection ### Characteristics - The `LSP4Metadata` represents the metadata of the whole NFT Collection. - All the NFTs live in the same smart contract. - Each NFT can be uniquely identified by a `tokenId` in the collection. - Each NFT can have its own custom metadata. This can be set via: - `setDataForTokenId(...)` for each NFT. - by setting the `LSP8MetadataBaseURI` and appending the `tokenId` to the base URI. ### Example Use Cases - a collection of unique watches with their serial number. - a collection of unique digital art pieces. --- ## Collection of Sub-Collections ### Characteristics - Each tokenId is a of `LSP8TokenIdFormat` of `Address`. - Each sub-collection is a smart contract that can be either an LSP7 or LSP8 --- --- sidebar_label: '👋🏻 Getting Started' sidebar_position: 1 description: Create a Hardhat project and start building your smart contracts for LUKSO. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Getting started building Tokens & NFTs The LUKSO ecosystem offers smart contract developers a lot of [new standards](../../standards/introduction.md) and [tools](/tools) to build **powerful, modular, and standardized** blockchain applications. This page will guide you in setting up your development environment to build and deploy tokens and NFTs on LUKSO. :::info For more low level information about the Tokens Contracts (LSP7 and LSP8), see the dedicated [contracts](../../contracts/introduction.md) section. ::: ### Playground Repository In the following guides, we will use the [`lukso-playground`](https://github.com/lukso-network/lukso-playground) repository with a full Hardhat setup, including ready-to-go network configurations, sample contracts, and scripts to deploy and verify LSP-based contracts on LUKSO.
:::info **This repository uses the [bun](https://bun.sh) toolkit to manage packages and run scripts. Make sure to [install it](https://bun.sh/docs/installation) first.** ::: ## Clone the Playground Repository First, clone the playground repository and navigate into the smart-contracts-hardhat folder: ```bash git clone https://github.com/lukso-network/lukso-playground.git cd lukso-playground/smart-contracts ``` To install all the dependencies, run the below command: ```bash bun install ``` You can then go ahead to create a `.env` file within the root folder of the Hardhat repository and the following contents: ```text title=".env" PRIVATE_KEY=0x... ``` The private key will be used to deploy the smart contracts to the network and can either be a **standalone Externally Owned Account** or a **controller of a Universal Profile**. If you want to deploy the smart contracts as a Universal Profile, you also have to provide the related address of the Universal Profile. :::danger Never share your private key that you will put into the `.env` file! ::: :::success To pay for the gas deployment fees, you will need LYXt. You can request LYXt from the [LUKSO Testnet faucet](https://faucet.testnet.lukso.network/). ::: We now have a base Hardhat setup that we can use to develop and deploy our smart contracts. ## Run locally Run the TypeScript code of one file within the terminal using `bun`. ```bash bun file-path/script.ts ``` --- --- sidebar_label: 'Cascade and Sense Support' sidebar_position: 6 description: 'Introduction to implementation Cascade and Sense Protocols of NFTs at LUKSO network' --- # Cascade and Sense Support for NFT Metadata :::success Useful Tip This guide will walk you through uploading images and metadata to Cascade and Sense Protocol on [LUKSO Testnet](../../../networks/testnet/parameters.md). ::: ## Introduction [Cascade](https://cascade.pastel.network) is a protocol that allows users to store data permanently in a highly redundant, distributed fashion with a single upfront fee. [Sense](https://sense.pastel.network) is a lightweight protocol on the Pastel Network, built to assess the relative rareness of a given NFT against near-duplicate metadata. ## Uploading files to Cascade and Sense Protocol To upload files to Cascade and Sense Protocol, you need gateway api key. ### Upload files to Cascade Protocol You can use CascadeUploader of `@lukso/data-provider-cascade` library to upload files to Cascade Protocol and retrieve result id and IPFS link. ```javascript import { createReadStream } from 'node:fs'; import { CascadeUploader } from '@lukso/data-provider-cascade'; import { config } from 'dotenv'; config({ path: './.env.test' }); const provider = new CascadeUploader(process.env.CASCADE_API_KEY || ''); const file = createReadStream('./examples/test-image.png'); const result = await provider.uploadToCascade(file); if (result) { console.log(result.ipfs_url); } // upload folder const results = await provider.uploadFolderToCascade('./examples'); if (results.length > 0) { for (const result of results) { if (result) { console.log('File Name:', result.file_name); console.log('IPFS Url:', result.ipfs_url); console.log('Result Id:', result.result_id); } } } ``` ### Upload files to Sense Protocol You can use SenseUploader of `@lukso/data-provider-sense` library to upload files to Sense Protocol and retrieve result id and ipfs link. ```javascript import { createReadStream } from 'node:fs'; import { SenseUploader } from '@lukso/data-provider-sense'; import { config } from 'dotenv'; config({ path: './.env.test' }); const provider = new SenseUploader(process.env.SENSE_API_KEY || ''); const file = createReadStream('./examples/test-image.png'); const result = await provider.uploadToSense(file); if (result) { console.log(result.ipfs_url); } // upload folder const results = await provider.uploadFolderToSense('./examples'); if (results.length > 0) { for (const result of results) { if (result) { console.log('File Name:', result.file_name); console.log('IPFS Url:', result.ipfs_url); console.log('Result Id:', result.result_id); } } } ``` ### Retrieve activation ticket transaction id To get activation ticket transaction status and id, you can use `retrieveTxId` function of provider. ```javascript const { result_id } = await provider.uploadToCascade(file); const { status, tx_id } = await provider.retrieveTxId(result_id); console.log(tx_id); ``` ## Add Cascade and Sense's result id and activation ticket id to metadata After you upload files to Cascade and Sense Protocol, you need to save those information at metadata of nft. ```json { ... other properties cascadeId: "fc67a80d-0d4a-4065-868f-8c9bd1d0efb6", // Cascade upload result id cascadeTxId: "4482769c-7256-4339-97ad-f563c11e38ad", // Cascade Activation Ticket TxId senseId: "3959c860-ccbd-402c-8617-6cdac8cfef7f" // Sense upload result id senseTxId: "b1641fd0-328a-4c62-913b-3e7414c3b154" // Sense Activation Ticket TxId } ``` ## References - [Cascade Overview](https://docs.pastel.network/cascade-protocol/cascade-overview) - [Sense Overview](https://docs.pastel.network/sense-protocol/master) --- --- sidebar_label: 'Set LSP7 Token Metadata' sidebar_position: 3 description: Learn how to update LSP4 Metadata of digital assets on LUKSO using ethers.js, web3.js, or Hardhat. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Set LSP7 Token Metadata > 👇🏻 Hands on 📽️ _ethers.js_ workshop video for the [**Oxford Blockchain Society**](https://x.com/oxfordblocksoc) from March 2024.
In this guide, you will learn how to edit the [`LSP4Metadata`](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md) of an [LSP7 Digital Asset](../../../standards/tokens/LSP7-Digital-Asset.md). You will need to: 1. get your assets ready (images, videos, etc.) and create a metadata JSON file 2. upload these files using a preferred storage provider 3. generate an encoded value based on the URL to the metadata JSON file 4. write that value in the smart contract key-value store For steps 1 to 3, there is a dedicated [Asset Preparation Guide](metadata-preparation.md). Once your assets are uploaded and the URL to your metadata JSON file is ready and encoded, come back here.
Show encoded LSP4 Object ```js const encodedLSP4Metadata = { keys: ['0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e'], values: [ '0x00006f357c6a0020610be5a5ebf25a8323ed5a9d8735f78aaf97c7e3529da7249f17e1b4129636f3697066733a2f2f516d5154716865424c5a466e5155787535524473387441394a746b78665a714d42636d47643973756b587877526d', ], }; ```
:::tip Code repository You can find all the contracts, sample metadata, and scripts of the guide within our [`lukso-playground`](https://github.com/lukso-network/lukso-playground/tree/main/smart-contracts) repository. ::: :::info Contract Deployment If you want to learn more about the contract deployment itself, please have a look at the [Create LSP7 Token](../../digital-assets/token/create-lsp7-token.md) guides before you continue. ::: ## Setup First, prepare the encoded metadata and connect to your token contract. ```js title="set-token-metadata-ethers.js" import { ethers } from 'ethers'; import LSP7Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; // As generated in the Asset Preparation guide const encodedLSP4Metadata = { keys: ['0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e'], values: [ '0x00006f357c6a0020610be5a5ebf25a8323ed5a9d8735f78aaf97c7e3529da7249f17e1b4129636f3697066733a2f2f516d5154716865424c5a466e5155787535524473387441394a746b78665a714d42636d47643973756b587877526d', ], }; // Connect via the UP Browser Extension const provider = new ethers.BrowserProvider(window.lukso); await provider.send('eth_requestAccounts', []); const signer = await provider.getSigner(); const myAssetAddress = '0x...'; // Instantiate the token contract const token = new ethers.Contract(myAssetAddress, LSP7Artifact.abi, signer); ``` ```js title="set-token-metadata-web3.js" import Web3 from 'web3'; import LSP7Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; // As generated in the Asset Preparation guide const encodedLSP4Metadata = { keys: ['0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e'], values: [ '0x00006f357c6a0020610be5a5ebf25a8323ed5a9d8735f78aaf97c7e3529da7249f17e1b4129636f3697066733a2f2f516d5154716865424c5a466e5155787535524473387441394a746b78665a714d42636d47643973756b587877526d', ], }; // Connect via the UP Browser Extension const web3 = new Web3(window.lukso); await web3.eth.requestAccounts(); const accounts = await web3.eth.getAccounts(); const myAssetAddress = '0x...'; // Instantiate the token contract const token = new web3.eth.Contract(LSP7Artifact.abi, myAssetAddress); ``` ```ts title="scripts/attachAssetMetadataAsEOA.ts" import { ethers } from 'hardhat'; import LSP7Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; import * as dotenv from 'dotenv'; // Load the environment variables dotenv.config(); // As generated in the Asset Preparation guide const encodedLSP4Metadata = { keys: ['0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e'], values: [ '0x00006f357c6a0020610be5a5ebf25a8323ed5a9d8735f78aaf97c7e3529da7249f17e1b4129636f3697066733a2f2f516d5154716865424c5a466e5155787535524473387441394a746b78665a714d42636d47643973756b587877526d', ], }; const [signer] = await ethers.getSigners(); const myAssetAddress = '0x...'; // Instantiate the token contract const token = new ethers.Contract(myAssetAddress, LSP7Artifact.abi, signer); ``` ## Set data on token Once you have the data key and value (with the encoded VerifiableURI in it), call the [`setData(bytes32,bytes)`](/contracts/contracts/UniversalProfile/#setdata) function on the Token contract. ```js title="set-token-metadata-ethers.js" // Update the ERC725Y storage of the LSP4 metadata const tx = await token.setData( encodedLSP4Metadata.keys[0], encodedLSP4Metadata.values[0], ); // Wait for the transaction to be included in a block const receipt = await tx.wait(); console.log('✅ Token metadata updated:', receipt.hash); ``` ```js title="set-token-metadata-web3.js" // Update the ERC725Y storage of the LSP4 metadata const receipt = await token.methods .setData(encodedLSP4Metadata.keys[0], encodedLSP4Metadata.values[0]) .send({ from: accounts[0] }); console.log('✅ Token metadata updated:', receipt.transactionHash); ``` ```ts title="scripts/attachAssetMetadataAsEOA.ts" // Update the ERC725Y storage of the LSP4 metadata const tx = await token.setData( encodedLSP4Metadata.keys[0], encodedLSP4Metadata.values[0], ); // Wait for the transaction to be included in a block const receipt = await tx.wait(); console.log('✅ Token metadata updated:', receipt); ``` Run the script: ```bash npx hardhat --network luksoTestnet run scripts/attachAssetMetadataAsEOA.ts ``` ### Setting multiple data keys at once If you need to update multiple metadata keys simultaneously, use [`setDataBatch(bytes32[],bytes[])`](/contracts/contracts/UniversalProfile/#setdatabatch): ```js const tx = await token.setDataBatch( encodedLSP4Metadata.keys, encodedLSP4Metadata.values, ); await tx.wait(); ``` ```js await token.methods .setDataBatch(encodedLSP4Metadata.keys, encodedLSP4Metadata.values) .send({ from: accounts[0] }); ``` ```ts const tx = await token.setDataBatch( encodedLSP4Metadata.keys, encodedLSP4Metadata.values, ); await tx.wait(); ``` --- --- sidebar_label: 'Metadata Preparation' sidebar_position: 2 description: Learn how to prepare and use assets for LUKSO Universal Profiles and digital assets (LSP7 / LSP8). --- # Metadata Preparation :::info LSP4 Metadata When creating or editing Universal Profiles or Digital Assets, you will first need to upload assets such as images, icons, videos, etc. These assets can then be linked within the [Metadata JSON File](/standards/tokens/LSP4-Digital-Asset-Metadata.md) that will be attached to the smart contract. ::: This guide will walk you through all necessary steps to prepare the asset data. ## Metadata Preparation Flow To set the metadata of a digital asset, you have to follow these steps: 1. Upload each media file (icon, picture, image, video, etc) and get it's `URLs` or `IPFS CID`. 2. Inside the [LSP4 Metadata JSON file](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4metadata) , set the following values under each `"images"`: - under `verification.data`, set the hash of the media file. - under `url`, set the value `ipfs://` (obtained from Step 1) 3. Upload the [LSP4 Metadata JSON file](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md) to get its `URL` or `IPFS CID`. 4. Encode the LSP4 Metadata JSON file URL as a `VerifiableURI`. 5. Write the **reference to the JSON file** to your token contract. ```mermaid %%{init: {'themeVariables': { 'actorBkg': '#E0F7FA', 'actorBorder': '#006064', 'sequenceNumberColor': '#00695C', 'mainBkg': '#F1F8E9'}}}%% sequenceDiagram participant U as Developer participant S as Storage (e.g. IPFS) participant G as Metadata JSON participant C as Smart Contract U->>S: Upload Media Files (icon, image, video, etc.) S-->>U: Return File URLs or IPFS CIDs U->>G: Provide File Hashes and URLs G-->>U: Build-up the LSP4 Metadata JSON U->>S: Upload LSP4 Metadata JSON S-->>U: Return URL or IPFS CID U-->>U: Encode URL as VerifiableURI U->>C: Write VerifiableURI to Contract ``` ## 1 - File Uploads :::tip Storage Solution LSPs do not restrict you to a specific storage solution. ::: To upload the files (assets and metadata JSON file), you have mainly two options: | Solution | Description | Examples | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | Centralized Storage | Centralized storage solutions are user-friendly and can be a good starting point for those new to the ecosystem or participating in hackathons. However, they rely on a single point of control, which may not align with the decentralized ethos of blockchain technology. | [AWS S3](https://aws.amazon.com/s3/), [Google Cloud](https://cloud.google.com/storage?hl=en), [Dropbox](https://www.dropbox.com/), etc. | | Decentralized Storage | Decentralized storage solutions align with the decentralized nature of blockchain and offer benefits like _redundancy_, _censorship resistance_, and _permanent storage_. However, they might be more complex to interact with. | [IPFS](https://ipfs.tech/), [Arweave](https://www.arweave.org/), [Filecoin](https://filecoin.io/), etc. | :::info Uploading files to IPFS See our guide [**"Use IPFS Storage"**](../../other-guides/utilize-ipfs-storage.md) to learn how to upload your files to IPFS using the LUKSO [`tools-data-providers`](https://github.com/lukso-network/tools-data-providers) library. ::: ## 2 - Generate the JSON File The JSON content is used as input for encoding the metadata according to the [LSP4](/standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4---digital-asset-metadata) standard. After you filled your metadata file with content, upload it to a preferred storage solution. To ensure the authenticity of the images, please **generate the hash** of the uploaded files and set them within the `"verification"` field of the JSON Metadata: - Define **the used hash function** within the `"method"` element - Add the **hash digest** (_e.g: 32 bytes long for keccak256_) within the `"data"` element After uploading the media files, you can attach their links to a JSON File in the following structure:
LSP4 Example JSON File ```js { "LSP4Metadata": { "name": "My Token Name", "description": "Sample Description", "links": [{ "title": "My Website", "url": "https://my.website.com" }], "icon": [ { "width": 60, "height": 60, "url": "https://mycentralised-storage.com/filename.png", "verification": { "method": "keccak256(bytes)", "data": "0x" } } ], "images": [ [ { "width": 1000, "height": 1000, "url": "https://centralised-cloud-storage.com/image.jpg", "verification": { "method": "keccak256(bytes)", "data": "0x" } }, { "width": 500, "height": 500, "url": "ipfs://[IPFS-CID]", "verification": { "method": "keccak256(bytes)", "data": "0x" } } ] ], "assets": [], "attributes": [ { "key": "Standard type", "value": "LSP", "type": "string" }, { "key": "Standard number", "value": 4, "type": "number" } ] } } ```
:::warning Prettified JSON While the example above is formatted for readability, minifying the JSON file (removing whitespace and formatting) is recommended as it makes hash verification more consistent. ::: ## 3 - Encode the LSP4 Metadata :::tip Convenience Tool You can use the 🛠️ [`erc725.js`](../../../tools/dapps/erc725js/getting-started.md) library to encode the LSP4 Metadata. The tool provides all necessary LSP schemas as well as the `encodeData()` function. ::: ```js import { ERC725 } from '@erc725/erc725.js'; import LSP4DigitalAssetSchema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; const LSP4JSON = { /* Your JSON */ }; const encodedLSP4Metadata = ERC725.encodeData( [ { keyName: 'LSP4Metadata', value: { json: LSP4JSON, url: 'https://my-file-provider.com/my-file-link.json', // It can also be: ipfs://[CID] }, }, ], LSP4DigitalAssetSchema, ); ``` The encoded content will then look like the following: ```js title="LSP4 Encoded Contract Metadata" wordWrap=inherit { keys: [ '0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e' ], values: [ '0x00006f357c6a0020610be5a5ebf25a8323ed5a9d8735f78aaf97c7e3529da7249f17e1b4129636f3697066733a2f2f516d5154716865424c5a466e5155787535524473387441394a746b78665a714d42636d47643973756b587877526d' ] } ``` ## 4 - Adding the Metadata After you retrieved the key and value of your [ERC725Y](/standards/erc725#erc725y-generic-data-keyvalue-store) data key, you can call the [`setData()`](../../../contracts/contracts/ERC725/ERC725.md#setdata) function of the asset to update it's metadata on the contract. :::tip Sample Implementation You can follow our [Deploy Token With Metadata](../../universal-profile/interactions/batch-transactions.md#deploy-a-token--set-metadata) and [Set NFT Metadata](../nft/set-nft-metadata.md) Guides to set or update contract metadata. ::: --- --- sidebar_label: 'Fetch Asset Metadata' sidebar_position: 1 description: Learn how to read Digital Asset (LSP7) and Identifiable Digital Assets (NFT/LSP8) data from their smart contracts. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeSandbox from "@site/src/components/CodeSandbox"; # 📑 Read Digital Asset Data :::info Code Examples The full code of this example can be found in the 👾 [lukso-playground](https://github.com/lukso-network/lukso-playground/tree/main/dapps/digital-assets) repository. ::: On LUKSO, [Digital Assets](/standards/tokens/introduction.md) are created using the [LSP7 - Digital Asset](/standards/tokens/LSP7-Digital-Asset.md) and [LSP8 - Identifiable Digital Asset](/standards/tokens/LSP8-Identifiable-Digital-Asset.md) standards. The data of each digital asset lives in its own [ERC725Y](/standards/erc725.md#erc725y-generic-data-keyvalue-store) storage. This tutorial teaches you how to fetch and read this data.

A LSP7 Token as seen on UniversalEverything

:::info Preparation Before following this guide, it is recommended to be a bit familiar with the token standards: - [LSP4 - Digital Asset Metadata](/standards/tokens/LSP4-Digital-Asset-Metadata.md). - [LSP7 - Digital Asset](/standards/tokens/LSP7-Digital-Asset.md). - [LSP8 - Digital Identifiable Asset](/standards/tokens/LSP8-Identifiable-Digital-Asset.md). - [How digital assets differ based on their LSP4 Token Type](/standards/tokens/LSP4-Digital-Asset-Metadata.md#types-of-digital-assets). ::: :::success Check Assets Online You can use the 🔎 [ERC725 Inspect](https://erc725-inspect.lukso.tech/inspector?network=lukso+mainnet) tool for inspecting assets within the browser. ::: ## Setup You will need the following to follow this tutorial: - Address of a digital asset (_Example asset address on testnet: [`0x0514A829C832639Afcc02D257154A9DaAD8fa21B`](https://wallet.universalprofile.cloud/asset/0x0514A829C832639Afcc02D257154A9DaAD8fa21B?network=testnet)_). - `@lukso/lsp-smart-contracts` package - `erc725.js` ```bash npm i @lukso/lsp-smart-contracts @erc725/erc725.js ``` ## Check if the contract is a Digital Asset :::info If you are using the 📃 [lsp-smart-contracts](/tools/lsp-smart-contracts/getting-started) library, you can fetch the list of `interfaceId` directly from the package's [constants](/tools/lsp-smart-contracts/constants) called `INTERFACE_IDS`. Optionally, you can also find a full list of interface IDs on the [Contracts > Interface ID](/contracts/interface-ids/) page and input them manually. ::: First, we need to check if the contract is a digital asset, as either an LSP7 or an LSP8 smart contract. To do so, we will do the same way as shown in the [**Interface Detection**](../../standard-detection.md#interface-detection) guide: call the `supportsInterface(bytes4)` function in the smart contract, checking for various interface IDs. ```ts import { ethers } from 'ethers'; import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts'; const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const myAsset = new ethers.Contract('', [ { inputs: [ { internalType: 'bytes4', name: '_interfaceId', type: 'bytes4', }, ], name: 'supportsInterface', outputs: [ { internalType: 'bool', name: '', type: 'bool', }, ], stateMutability: 'view', type: 'function', }, provider, ]); const isLSP7 = await myAsset.supportsInterface(INTERFACE_IDS.LSP7DigitalAsset); const isLSP8 = await myAsset.supportsInterface( INTERFACE_IDS.LSP8IdentifiableDigitalAsset, ); console.log(isLSP7, isLSP8); // each, true or false ``` ```ts import Web3 from 'web3'; import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const myAsset = new web3.eth.Contract( [ { inputs: [ { internalType: 'bytes4', name: '_interfaceId', type: 'bytes4', }, ], name: 'supportsInterface', outputs: [ { internalType: 'bool', name: '', type: 'bool', }, ], stateMutability: 'view', type: 'function', }, ], '', ); const isLSP7 = await myAsset.methods .supportsInterface(INTERFACE_IDS.LSP7DigitalAsset) .call(); const isLSP8 = await myAsset.methods .supportsInterface(INTERFACE_IDS.LSP8IdentifiableDigitalAsset) .call(); console.log(isLSP7, isLSP8); // each, true or false ``` ## Fetch the Asset Metadata [LSP4 - Digital Asset Metadata](/standards/tokens/LSP4-Digital-Asset-Metadata.md) describes the data within [LSP7](/standards/tokens/LSP7-Digital-Asset.md) and [LSP8](/standards/tokens/LSP8-Identifiable-Digital-Asset.md) asset's [ERC725Y data storage](/standards/erc725#erc725y-generic-data-keyvalue-store). The following data keys can be fetched 👇 | 🗄️ Data Key | Value contained inside this data key | | :------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `SupportedStandards:LSP4DigitalAsset` | A hex literal value confirming the ERC725Y contract contains metadata keys for the [LSP4DigitalAsset](/standards/tokens/LSP4-Digital-Asset-Metadata.md) standard. | | `LSP4Metadata` | The JSON file with asset descriptions and images. | | `LSP4Creators[]` | An array of all creators of the asset. | | `LSP4CreatorsMap:
` | A mapping of creator-specific information. | | `LSP4TokenType` | The asset's token type (encoded as a `uint256` number). | | `LSP4TokenSymbol` | The utf8 hex characters of the string representing the asset's symbol. | | `LSP4TokenName` | The utf8 hex characters of the string representing the asset's name. | To retrieve and decode the value stored under this data keys, we will use [erc725.js](../../../tools/dapps/erc725js/getting-started.md) and instantiate the class with: 1. the LSP4 Schema that defines the data keys above and how to decode them 2. the address of your digital asset 3. an RPC URL 4. an IPFS gateway to fetch any off-chain data linked to the contract storage ```ts title="Instantiate erc725.js" import { ERC725 } from '@erc725/erc725.js'; import lsp4Schema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts'; const erc725js = new ERC725( lsp4Schema, '0x0514A829C832639Afcc02D257154A9DaAD8fa21B', // address of the digital asset contract 'https://4201.rpc.thirdweb.com', { ipfsGateway: 'https://api.universalprofile.cloud/ipfs', }, ); ``` We can fetch the digital asset data in three ways: 1. using [`getData()`](/tools/dapps/erc725js/methods#getdata) without parameters. This will fetch the value of all data keys at once. 2. using `getData("DataKeyName")` to fetch the value of a specific data key. For instance `getData("LSP4Metadata")`. 3. using [`fetchData('LSP4Metadata')`](/tools/dapps/erc725js/methods.md#fetchdata) which decodes the `VerifiableURI` to extract the JSON metadata file link and fetch its content from IPFS (or another storage service). ### Asset Name and Symbol ```ts // Fetch the asset's name const tokenName = await erc725js.fetchData('LSP4TokenName'); console.log(tokenName); /** { key: '0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1', name: 'LSP4TokenName', value: 'upturn: MINT PASS [UPT0001]', } */ // Fetch the asset's symbol const tokenSymbol = await erc725js.fetchData('LSP4TokenSymbol'); console.log(tokenSymbol); /** { key: '0x2f0a68ab07768e01943a599e73362a0e17a63a72e94dd2e384d2c1d4db932756', name: 'LSP4TokenSymbol', value: 'UPT', } */ ``` import ERC725 from '@site/static/img/tools/erc725-tools.png'; ### Global Token Information To fetch the whole JSON file of the asset's metadata, you can use the following 2 functions of the [`erc725js`](/tools/dapps/erc725js/getting-started.md) library: - [`fetchData('LSP4Metadata')`](/tools/dapps/erc725js/methods.md#fetchdata): This will download and decode the content of `VerifiableURI` as JSON. - [`getData(LSP4Metadata)`](/tools/dapps/erc725js/methods#getdata): This will retrieve the raw data value from the smart contract. You will then need to decode the `VerifiableURI` maunually using [`decodeData(...)`](/tools/dapps/erc725js/methods.md#decodedata). ```ts // Download and verify the asset metadata JSON file const assetMetadata = await erc725js.fetchData('LSP4Metadata'); console.log(assetMetadata); ```
Show result ```js { "key": "0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e", "name": "LSP4Metadata", "value": { "LSP4Metadata": { "description": "A MINT PASS enables 1x Token Deployment using the upturn protocol", "links": [ { "title": "upturnOS", "url": "https://upturn.live" } ], "icon": [ { "width": 1600, "height": 1584, "url": "ipfs://bafybeieyp4gvgprefvd6exm4sdbehkzlu2rmh57ferp3tmfb2oihfg6tp4", "verification": { "method": "keccak256(bytes)", "data": "0x996302e00ef0226f12d44c029fb2c82290f31e2209013cd5c0502840f8e57d0e" } } ], "backgroundImage": [ { "width": 1920, "height": 1080, "url": "ipfs://bafybeiediqal3fvzlmu5c4kc2kei2irq5rggi5hkmqecvefcdiaeg2bgbu", "verification": { "method": "keccak256(bytes)", "data": "0xf80f3cfd9f905186fb30bcbd77c4111e4afe5fba75c678928e7fc2452f74cbc1" } } ], "assets": [ { "url": "ipfs://bafkreibxq4lrx5s4q5lag5wsw7pivugcfkb4ync4y23wjgy4brbusi7tsy", "fileType": "image/png", "verification": { "method": "keccak256(bytes)", "data": "0x4ec65a52385593b134770e5612cfcb54c0a77aba2121964e0b27ba037cf4eea6" } } ], "images": [ [ { "width": 1440, "height": 1440, "url": "ipfs://bafkreibxq4lrx5s4q5lag5wsw7pivugcfkb4ync4y23wjgy4brbusi7tsy", "verification": { "method": "keccak256(bytes)", "data": "0x4ec65a52385593b134770e5612cfcb54c0a77aba2121964e0b27ba037cf4eea6" } } ] ] } } } ```
### List of Creators ```ts // Fetch all creators of the asset const assetCreatorsList = await erc725js.fetchData('LSP4Creators[]'); console.log(assetCreatorsList); /** // Creator List (empty, no creators set) { key: '0x114bd03b3a46d48759680d81ebb2b414fda7d030a7105a851867accf1c2352e7', name: 'LSP4Creators[]', value: [] } */ ``` ### Get Creator basic infos :::success Advice If one of the creator contains the `LSP0ERC725Account` interface ID (`0x...`), it is likely to be a Universal Profile! 🆙 Follow the guide [**Read Profile Data**](../../universal-profile/metadata/read-profile-data.md) to retrieve the profile infos! ::: The `LSP4CreatorsMap:
` is a Mapping data key that requires a dynamic input. To fetch its info, use the function below, providing the creator address as input to the `dynamicKeyParts` property of the object parameter. ```js // Fetch creator-specific information const creatorInformation = await erc725js.fetchData([ { keyName: 'LSP4CreatorsMap:
', // Sample creator address dynamicKeyParts: '0x9139def55c73c12bcda9c44f12326686e3948634', }, ]); console.log(creatorInformation); // Dynamic Creator Map Retrieval /* * Creator Map for 0x9..8634 (empty, no data set) * Key Format: '0x6de85eaf5d982b4e5da00000' * Name Format: 'LSP4CreatorsMap:' [ { key: '0x6de85eaf5d982b4e5da000009139def55c73c12bcda9c44f12326686e3948634', name: 'LSP4CreatorsMap:9139def55c73c12bcda9c44f12326686e3948634', value: [], }, ]; */ ``` ## Interpret Data based on Token Type If both, contract and metadata standard are aligned, Finally we need to determine the [LSP4 Token Type](/standards/tokens/LSP4-Digital-Asset-Metadata.md#types-of-digital-assets) in order to interpret the metadata correctly. At this point, you should be able to identify if the digital asset is a: - LSP7 - Token - LSP7 - NFT - LSP8 - NFT - LSP8 - Collection Based on the [token type](#detect-the-token-type), the information of the [LSP4 Digital Metadata](/standards/tokens/LSP4-Digital-Asset-Metadata.md#types-of-digital-assets) can be interpreted differently: - As [**global token information**](#global-token-information) of the contract (Token or LSP7 NFT) - To each [**individual token ID**](#token-id-metadata) (LSP8 NFT or Collection) :::tip Token ID Entries - If your asset is a Token (`tokenType = 0`), individual metadata **can't be set**, due to the lack of token IDs. - If your asset is an NFT (`tokenType = 1`), individual metadata **may be set in addition** to the global token information. - If your asset is a Collection (`tokenType = 2`), the token ID-specific medatada is **mandatory**. --- --- sidebar_label: '👾 Collection with LSP7' sidebar_position: 2 description: Learn how to create an NFT Collection on LUKSO using LSP7 Digital Asset standard. --- # Create an NFT Collection Using LSP7 This tutorial explores how to create a collection of [digital assets](/standards/tokens/LSP7-Digital-Asset.md), where each digital asset is the same. This method is useful for minting large quantities of NFTs at once efficiently (eg: tickets for an event). :::note This guide builds on top of a Hardhat project using TypeScript as described in the [Getting Started](../getting-started.md) section. ::: :::tip The full code of this example can be found in the smart contract section of the 👾 [`lukso-playground`](https://github.com/lukso-network/lukso-playground) repository. :::
When creating smart contracts representing digital assets on LUKSO, you will need to specify the token type and data keys for the 📄 [LSP4 Digital Asset Metadata](/standards/tokens/LSP4-Digital-Asset-Metadata) that will be stored in the 🗂️ [ERC725Y](/standards/erc725.md#erc725y-generic-data-keyvalue-store) storage of the Digital Asset. There are three different [token types](/standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokentype): - `0` = Token - `1` = NFT - `2` = Collection For this example we will use the `Token` token type. You can create a custom 🌄 [LSP7 Digital Asset Token](/standards/tokens/LSP7-Digital-Asset.md) that extends [LSP7Mintable](../../../contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md) so that new assets can be minted by the [`owner`](../../../contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md#owner) of the smart contract. ```solidity title="contracts/Example1/EventTicketsNFT.sol" // SPDX-License-Identifier: MIT pragma solidity ^0.8.4; // modules import { LSP7Mintable } from "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.sol"; import { _LSP4_TOKEN_TYPE_TOKEN } from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; contract EventTicketsNFT is LSP7Mintable { constructor( string memory eventName, string memory tokenSymbol, address contractOwner ) LSP7Mintable( eventName, tokenSymbol, contractOwner, _LSP4_TOKEN_TYPE_TOKEN, // set the token type as Token true // make the token non divisible ) {} } ``` Next define the deployment script. ```ts title="scripts/deployAndMintTickets.ts" import { ethers } from 'ethers'; import EventTicketsNFTArtifacts from './artifacts/EventTickets.json'; const accounts = await ethers.getSigners(); const deployer = accounts[0]; const contractFactory = new ethers.ContractFactory( EventTicketsNFTArtifacts.abi, EventTicketsNFTArtifacts.bytecode, deployer, ); const luksoMeetupTickets = await contractFactory.deploy( 'LUKSO Meetup #2', 'MUP2', deployer.address, ); // create 100 entry tickets. // Give them to the deployer initially, who will distribute them afterwards. await luksoMeetupTickets.mint( deployer.address, // recipient 100, // amount true, // force sending to an EOA '0x', // data ); const luksoMeetupTicketsAddress = await luksoMeetupTickets.getAddress(); console.log('NFT Collection deployed to:', luksoMeetupTicketsAddress); console.log('Check the block explorer to see the deployed contract'); ``` Finally, run the deploy script: ```sh npx hardhat run --network luksoTestnet scripts/deployAndMintTickets.ts ``` You can now check out the NFT collection contract on the [execution block explorer](https://explorer.execution.testnet.lukso.network/) by pasting the address logged on the console to the search field of the block explorer. ## References - [BuildUP #2 | Create an NFT Collection using LSP7 or LSP8 (YouTube)](https://www.youtube.com/watch?v=DMpeMswK12w) --- --- sidebar_label: '🗃 Collection with LSP8' sidebar_position: 1 description: Learn how to create an NFT Collection on LUKSO using LSP8 Identifiable Digital Asset standard. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Create an NFT Collection Using LSP8 This tutorial explains how to create a collection of unique Digital Assets based on the [LSP8-Identifiable-Digital-Asset](/standards/tokens/LSP8-Identifiable-Digital-Asset.md) standard. :::note This guide builds on top of a Hardhat project using TypeScript as described in the [Getting Started](../getting-started.md) section. ::: :::tip The full code of this example can be found in the smart contract section of the 👾 [`lukso-playground`](https://github.com/lukso-network/lukso-playground) repository. :::
When creating smart contracts representing digital assets on LUKSO, you need to specify the type of token you are deploying. This is done by setting the `LSP4TokenType` data key stored in the 🗂️ [ERC725Y](../../../standards/erc725.md#erc725y-generic-data-keyvalue-store) storage of the Digital Asset. There are three different [token types](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokentype): - `0` = Token - `1` = NFT - `2` = Collection For this example we will use the `Collection` token type. You can create a custom 🌄 [LSP8 Identfiable Digital Asset Collection](../../../standards/tokens/LSP8-Identifiable-Digital-Asset.md) that extends [LSP8Mintable](../../../contracts/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md) so that new assets can be created within the smart contract. ```solidity title="contracts/BasicNFTCollection.sol" // SPDX-License-Identifier: MIT pragma solidity ^0.8.4; // modules import { LSP8Mintable } from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.sol"; // constants import { _LSP8_TOKENID_FORMAT_NUMBER } from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol"; import { _LSP4_TOKEN_TYPE_COLLECTION } from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; contract BasicNFTCollection is LSP8Mintable { constructor( string memory nftCollectionName, string memory nftCollectionSymbol, address contractOwner ) LSP8Mintable( nftCollectionName, // NFT collection name nftCollectionSymbol, // NFT collection symbol contractOwner, // owner of the NFT contract (the address that controls it, sets metadata, can transfer the ownership of the contract) _LSP4_TOKEN_TYPE_COLLECTION, // type of the token is collection _LSP8_TOKENID_FORMAT_NUMBER // format of each `tokenId`s is number (represented as bytes32) ) {} } ``` The contract is ready, it's time to deploy it. You can easily do it with hardhat deployment script. ```js title="scripts/deploy.ts" import { ethers } from 'ethers'; import BasicNFTCollectionArtifacts from './artifacts/BasicNFTCollection.json'; const accounts = await ethers.getSigners(); const deployer = accounts[0]; const contractFactory = await new ethers.ContractFactory( BasicNFTCollectionArtifacts.abi, BasicNFTCollectionArtifacts.bytecode, deployer, ); const nftCollection = contractFactory.deploy( 'NFT Collection Name', // collection name 'NFT', // collection symbol deployer.address, ); const nftCollectionAddress = await nftCollection.getAddress(); console.log('NFT Collection deployed to:', nftCollectionAddress); console.log('Check the block explorer to see the deployed contract'); ``` Finally, run the deploy script: ```sh npx hardhat run --network luksoTestnet scripts/deploy.ts ``` You can now check out the NFT collection contract on the [execution block explorer](https://explorer.execution.testnet.lukso.network/) by pasting the address logged on the console to the search field of the block explorer. ## References - [BuildUP #2 | Create an NFT Collection using LSP7 or LSP8 (YouTube)](https://www.youtube.com/watch?v=DMpeMswK12w) --- --- sidebar_label: '🃏 Collection of Subcollections' description: 'Learn how to create a NFT collection where each NFT is a contract' sidebar_position: 3 --- # Create NFT Collection with a contract address as tokenId :::note This guide builds on top of a Hardhat project using TypeScript as described in the [Getting Started](../getting-started.md) section. ::: :::tip The full code of this example can be found in the smart contract section of the 👾 [`lukso-playground`](https://github.com/lukso-network/lukso-playground) repository. ::: ## Introduction If you have been looking at the [LSP8 token standard](../../../standards/tokens/LSP8-Identifiable-Digital-Asset.md), you probably noticed that addresses could be used as `tokenIds`. In this guide, we will replicate a real-world example where this could be useful to represent an NFT / `tokenId` as a smart contract with its own metadata. ## Use Case Let's take the example of [The Dematerialised](https://x.com/dematerialised), and more precisely their KLxENDLESS PHYGITAL COLLECTION. As you can see in the picture below, we have three medalions of different colours.s Each medaillon has a supply limit and each medaillon collection has its own metadata with different attributes. What we will do is create an [LSP8 collection](../../../standards/tokens//LSP8-Identifiable-Digital-Asset.md) that will represent the whole KLxENDLESS PHYSITAL collection and each medaillon will be a sub-collection (purple, blue or gold) will with a limited supply of NFTs [(Non-divisible LSP7 token)](../../../standards/tokens//LSP7-Digital-Asset.md). ## Create the LSP7 Sub-Collection Even though it seems a little bit counter-intuitive, we will start by creating a sub-collection using an LSP7 token. The reason is that the LSP8 collection will be in charge of deploying the LSP7 sub-collection tokens. ### Specify what needs to be set at deployment To create the LSP7 Sub-Collection contract, we will need to know the parameters to be set at deployment. In our case, we want to set the following: - the name of the sub-collection - the symbol of the sub-collection - the address of the [`owner()`](../../../../docs/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md) that will control the sub-collection contract (in our case this will the LSP8 collection contract) - the initial receiver of the tokens that will be minted at deployment (could be the token creator) - the number of tokens that will be minted at deployment - whether the token is divisible or not - the total supply of the token - the [Token Type](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md#types-of-digital-assets) - the [LSP4 Metadata](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4metadata) This is just an example. You can adjust these parameters according to your needs or define other deployment parameters such as the [LSP4 Creators array](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4creators). ### Imports Let's start creating an `LSP7SubCollection.sol` file in the `contracts/` folder and import: - the [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp7-contracts/contracts/LSP7DigitalAsset.sol) contract - the [`LSP4DigitalAssetMetadata.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp4-contracts/contracts/LSP4DigitalAssetMetadata.sol) contract - the [`_LSP4_SUPPORTED_STANDARDS_KEY`](../../../standards//tokens/LSP4-Digital-Asset-Metadata.md#supportedstandardslsp4digitalasset) constant - the [`_LSP4_SUPPORTED_STANDARDS_VALUE`](../../../standards//tokens/LSP4-Digital-Asset-Metadata.md#supportedstandardslsp4digitalasset) constant - the [`_LSP4_METADATA_KEY`](../../../standards//tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata) constant - the [`_LSP8_REFERENCE_CONTRACT`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8referencecontract) constant ```typescript title="contracts/LSP7SubCollection.sol" import { LSP7DigitalAsset } from '@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol'; import { LSP4DigitalAssetMetadata } from '@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol'; import { _LSP4_SUPPORTED_STANDARDS_KEY, _LSP4_SUPPORTED_STANDARDS_VALUE, _LSP4_METADATA_KEY } from '@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol'; import { _LSP8_REFERENCE_CONTRACT } from '@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol'; ``` ### Contract At deployment, we will need to set the following parameters: - `name_`: the name of the token - `symbol_`: the symbol of the token - `owner_`: the address that will be able to update the contract metadata (except the symbol, name and the LSP4TokenType) - `receiverOfInitialTokens_`: the address that will receive the minted tokens at deployment - [`lsp4TokenType_`](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokentype): the token type of the token - [`isNonDivisible_`](../../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#decimals): whether the token is divisible or not - `totalSupply_`: the total supply of the token - `lsp4MetadataURI_`: the [LSP4 Metadata](../../../standards//tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata) ```sol title="contracts/LSP7SubCollection.sol" contract LSP7SubCollection is LSP7DigitalAsset { constructor( string memory name_, string memory symbol_, address newOwner_, address receiverOfInitialTokens_, uint256 lsp4TokenType_, bool isNonDivisible_, uint256 totalSupply_, bytes memory lsp4MetadataURI_ ) LSP7DigitalAsset( name_, symbol_, newOwner_, lsp4TokenType_, isNonDivisible_ ) { // set LSP8ReferenceContract LSP4DigitalAssetMetadata._setData( _LSP8_REFERENCE_CONTRACT, abi.encodePacked( msg.sender, bytes32(uint256(uint160(address(this)))) ) ); // set the lsp4MetadataURI _setData(_LSP4_METADATA_KEY, lsp4MetadataURI_); // mint all tokens to the receiver of the initial tokens _mint(receiverOfInitialTokens_, totalSupply_, true, ""); } } ``` ### Override the `_setData` function As per the [`LSP8IdentifiableDigitalAsset`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8referencecontract) standard, the `LSP8ReferenceContract` data key should only be set once and not be modifiable. For this reason, we will need to override the `_setData(...)`function. ```sol title="contracts/LSP7SubCollection.sol" contract LSP7SubCollection is LSP7DigitalAssetCore, LSP4DigitalAssetMetadata { // previous code // override the _setData function so that the LSP8ReferenceContract is not editable function _setData( bytes32 dataKey, bytes memory dataValue ) internal override { require( dataKey != _LSP8_REFERENCE_CONTRACT, "LSP8ReferenceContractNotEditable" ); LSP4DigitalAssetMetadata._setData(dataKey, dataValue); } } ``` ### Final LSP7 Sub-collection contract
Click to expand/collapse the script. ```sol title="contracts/LSP7SubCollection.sol" // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {LSP7DigitalAsset} from "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol"; import {LSP4DigitalAssetMetadata} from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol"; import {_LSP4_SUPPORTED_STANDARDS_KEY, _LSP4_SUPPORTED_STANDARDS_VALUE, _LSP4_METADATA_KEY} from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; import {_LSP8_REFERENCE_CONTRACT} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol"; contract LSP7SubCollection is LSP7DigitalAsset { constructor( string memory name_, string memory symbol_, address newOwner_, address receiverOfInitialTokens_, uint256 lsp4TokenType_, bool isNonDivisible_, uint256 totalSupply_, bytes memory lsp4MetadataURI_ ) LSP7DigitalAsset( name_, symbol_, newOwner_, lsp4TokenType_, isNonDivisible_ ) { // set LSP8ReferenceContract LSP4DigitalAssetMetadata._setData( _LSP8_REFERENCE_CONTRACT, abi.encodePacked( msg.sender, bytes32(uint256(uint160(address(this)))) ) ); // set the lsp4MetadataURI _setData(_LSP4_METADATA_KEY, lsp4MetadataURI_); // mint all tokens to the receiver of the initial tokens _mint(receiverOfInitialTokens_, totalSupply_, true, ""); } // override the _setData function so that the LSP8ReferenceContract is not editable function _setData( bytes32 dataKey, bytes memory dataValue ) internal override { require( dataKey != _LSP8_REFERENCE_CONTRACT, "LSP8ReferenceContractNotEditable" ); LSP4DigitalAssetMetadata._setData(dataKey, dataValue); } } ```
## Create the LSP8 Collection Now that we have the LSP7 Sub-Collection, we can create the [LSP8 Collection](../../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#lsp8-collection-vs-tokenid-metadata). ### Specify what the LSP8 Collection will need to do The LSP8 Collection will be in charge of creating new Sub-Collections. It will do this by deploying a new LSP7 Sub-Collection and mint the initial supply of NFTs for the sub-collection. When minting the NFTs (as LSP7 tokens), the address of the deployed LSP7 sub-collection will be set as a `tokenId` within the LSP8 Collection. For this reason, when minting a new token on the LSP8 contract (a new LSP7 Sub-collection contract), we will need to set the following: - the `name` of the LSP7 Sub-Collection - the `symbol` of the LSP7 Sub-Collection - the [`lsp4TokenType`](../../../standards/tokens/LSP7-Digital-Asset.md##lsp4tokentype) of the LSP7 Sub-Collection - the `isNonDivisible` of the LSP7 Sub-Collection - the `totalSupply` of the LSP7 Sub-Collection - the `receiver` of the initial tokens of the LSP7 Sub-Collection ### Imports Let's start creating an `LSP8Collection.sol` file in the `contracts/` folder and import: : - the [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts.git) from which we will inherit the main functionalities of the LSP8 - the `_LSP8_TOKENID_FORMAT_ADDRESS` which is the format of the tokenId of the LSP8 Collection - the [`_LSP4_METADATA_KEY`](../../../standards//tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata) constant - the `LSP7SubCollection` contract we just created so that we can use it in our `mint(...)` function ```typescript title="contracts/LSP8Collection.sol" import { LSP8IdentifiableDigitalAsset } from '@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.sol'; import { _LSP8_TOKENID_FORMAT_ADDRESS } from '@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol'; import { _LSP4_METADATA_KEY } from '@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol'; import { LSP7SubCollection } from './LSP7SubCollection.sol'; ``` ### Contract #### Constructor The constructor will be in charge of setting the following parameters: - `name_`: the name of the LSP8 Collection - `symbol_`: the symbol of the LSP8 Collection - `newOwner_`: the owner of the LSP8 Collection that will be able change the contract metadata and mint new LSP7 tokens - [`lsp4TokenType_`](../../../standards/tokens/LSP7-Digital-Asset.md##lsp4tokentype) of the LSP7 Sub-Collection - `lsp8CollectionIdFormat`: the [format of the tokenId](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8Collectionidformat) of the LSP8 Collection - `lsp4MetadataURI_`: the [LSP4 Metadata](../../../standards//tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata) ```sol title="contracts/LSP8Collection.sol" contract LSP8Collection is LSP8IdentifiableDigitalAsset { constructor( string memory name_, string memory symbol_, address newOwner_, uint256 lsp4TokenType_, bytes memory lsp4MetadataURI_ ) LSP8IdentifiableDigitalAsset( name_, symbol_, newOwner_, lsp4TokenType_, _LSP8_TOKENID_FORMAT_ADDRESS ) { // set the lsp4MetadataURI _setData(_LSP4_METADATA_KEY, lsp4MetadataURI_); } } ``` #### Mint function Now let's implement the `mint(...)` function. This function will only be callable by the owner of the contract and will be in charge of deploying the LSP7 Sub-Collections as well as minting the LSP8 tokenId that will represent the LSP7 Sub-Collection. ```sol title="contracts/LSP8Collection.sol" contract LSP8Collection is LSP8IdentifiableDigitalAsset { // previous code function mint( string memory nameOfLSP7_, string memory symbolOfLSP7_, uint256 lsp4TokenType_, bool isNonDivisible_, uint256 totalSupplyOfLSP7_, address receiverOfInitialTokens_, bytes memory lsp4MetadataURIOfLSP7_ ) public onlyOwner returns (address lsp7SubCollectionAddress) { // deploy the LSP7SubCollection and set the address as tokenId LSP7SubCollection lsp7SubCollection = new LSP7SubCollection( nameOfLSP7_, symbolOfLSP7_, address(this), // owner of the LSP7SubCollection is this contract (LSP8Collection contract) receiverOfInitialTokens_, lsp4TokenType_, isNonDivisible_, totalSupplyOfLSP7_, lsp4MetadataURIOfLSP7_ ); lsp7SubCollectionAddress = address(lsp7SubCollection); // convert the address of the LSP7SubCollection to bytes32 to use it as tokenId bytes32 tokenId = bytes32(uint256(uint160(lsp7SubCollectionAddress))); /* owner of the tokenId is this contract tokenId is the address of the newly deployed LSP7SubCollection force is true since here the owner of the tokenId is this contract data is empty */ _mint(address(this), tokenId, true, ""); } } ``` ### Override the `_setDataForTokenId` & `_getDataForTokenId` functions Since we are inheriting from the `LSP8IdentifiableDigitalAsset.sol` contract, we will need to override the [`setDataForTokenId`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#setdatafortokenid) & [`getDataForTokenId`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatafortokenid) functions (same for the batch functions). These functions will be in charge of setting and getting the metadata of the deployed LSP7 Sub-Collection. In this particular case, it will make more sense to directly call on the [`setData(...)`](../../../contracts/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.md#setData) and [`getData(...)`](../../../contracts/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.md#getData) functions of the LSP7 Sub-Collection contract. ```sol title="contracts/LSP8Collection.sol" contract LSP8Collection is LSP8IdentifiableDigitalAsset { // previous code // override the _setDataForTokenId function to set the data on the LSP7SubCollection itself function _setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes memory dataValue ) internal override { // setData on the LSP7SubCollection LSP7SubCollection(payable(address(uint160(uint256(tokenId))))).setData( dataKey, dataValue ); emit TokenIdDataChanged(tokenId, dataKey, dataValue); } // override the _getDataForTokenId function to get the data from the LSP7SubCollection itself function _getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) internal view override returns (bytes memory dataValues) { return LSP7SubCollection(payable(address(uint160(uint256(tokenId))))).getData( dataKey ); } } ``` ### Final LSP8 Collection contract
Click to expand/collapse the script. ```sol title="contracts/LSP8Collection.sol" // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {LSP8IdentifiableDigitalAsset} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.sol"; import { _LSP8_TOKENID_FORMAT_ADDRESS } from '@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol'; import {_LSP4_METADATA_KEY} from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; import {LSP7SubCollection} from "./LSP7SubCollection.sol"; contract LSP8Collection is LSP8IdentifiableDigitalAsset { constructor( string memory name_, string memory symbol_, address newOwner_, uint256 lsp4TokenType_, bytes memory lsp4MetadataURI_ ) LSP8IdentifiableDigitalAsset( name_, symbol_, newOwner_, lsp4TokenType_, _LSP8_TOKENID_FORMAT_ADDRESS ) { // set the lsp4MetadataURI _setData(_LSP4_METADATA_KEY, lsp4MetadataURI_); } function mint( string memory nameOfLSP7_, string memory symbolOfLSP7_, uint256 lsp4TokenType_, bool isNonDivisible_, uint256 totalSupplyOfLSP7_, address receiverOfInitialTokens_, bytes memory lsp4MetadataURIOfLSP7_ ) public onlyOwner returns (address lsp7SubCollectionAddress) { // deploy the LSP7SubCollection and set the address as tokenId LSP7SubCollection lsp7SubCollection = new LSP7SubCollection( nameOfLSP7_, symbolOfLSP7_, address(this), // owner of the LSP7SubCollection is this contract (LSP8Collection contract) receiverOfInitialTokens_, lsp4TokenType_, isNonDivisible_, totalSupplyOfLSP7_, lsp4MetadataURIOfLSP7_ ); lsp7SubCollectionAddress = address(lsp7SubCollection); // convert the address of the LSP7SubCollection to bytes32 to use it as tokenId bytes32 tokenId = bytes32(uint256(uint160(lsp7SubCollectionAddress))); /* owner of the tokenId is this contract tokenId is the address of the newly deployed LSP7SubCollection force is true since here the owner of the tokenId is this contract data is empty */ _mint(address(this), tokenId, true, ""); } // override the _setDataForTokenId function to set the data on the LSP7SubCollection itself function _setDataForTokenId( bytes32 tokenId, bytes32 dataKey, bytes memory dataValue ) internal override { // setData on the LSP7SubCollection LSP7SubCollection(payable(address(uint160(uint256(tokenId))))).setData( dataKey, dataValue ); emit TokenIdDataChanged(tokenId, dataKey, dataValue); } // override the _getDataForTokenId function to get the data from the LSP7SubCollection itself function _getDataForTokenId( bytes32 tokenId, bytes32 dataKey ) internal view override returns (bytes memory dataValues) { return LSP7SubCollection(payable(address(uint160(uint256(tokenId))))).getData( dataKey ); } } ```
## Scripts Now that we have the contracts ready to be deployed, let's create a script that will deploy the LSP8 Collection and one script that will mint the LSP7 Sub-Collections. :::note Please make sure you compile your newly created contracts before creating the scripts with `npx hardhat compile`. Since the contracts are quite big, you may run into a compilation error. If this is the case, update your compiler settings in `hardhat.config.ts` with different optimizer settings. We used the following value to compile the contracts: ```typescript title="hardhat.config.ts" solidity: { version: "0.8.20", settings: { optimizer: { enabled: true, runs: 200, }, }, } ``` ::: ### Create the metadata JSONs files :::note In this part we will not cover the part where you first need to upload your JSONs files on IPFS and retrieve their CIDs. We have done it and will add them directly in the following scripts files. ::: Let's start by creating a `lsp8CollectionMetadata.json` file in the `metadata/` folder and set the following metadata:
Click to see the lsp8CollectionMetadata.json file ```json title="./metadata/lsp8CollectionMetadata.json" { "LSP4Metadata": { "name": "The Dematerialised", "description": "The Experiential Marketspace For Digital Goods", "links": [ { "title": "Website" } ], "icons": [], "images": [ { "width": 1024, "height": 974, "url": "ipfs://QmS3jF9jsoG6gnyJ7wCeJ4bej2aJEnPSv527UV8KxjBDAA", "verification": { "method": "keccak256(bytes)", "data": "0xdd6b5fb6dc984fda0222fb6f6e96b471c0667b12f03b1e804f7b5e6ab62acdb0" } } ], "assets": [], "attributes": [] } } ```
We will do the same with the LSP7 Sub-Collection metadata. Let's create a `lsp7SubCollectionMetadata.json` file in the `metadata` folder and set the following metadata:
Click to see the lsp7SubCollectionMetadata.json file ```json title="./metadata/lsp7SubCollectionMetadata.json" { "LSP4Metadata": { "name": "KLxENDLESS MEDALLION Purple", "description": "Collaboration with Karl Largerfeld", "links": [ { "title": "Get yours now" } ], "icons": [ { "width": 256, "height": 256, "url": "ipfs://QmS3jF9jsoG6gnyJ7wCeJ4bej2aJEnPSv527UV8KxjBDAA", "verification": { "method": "keccak256(bytes)", "data": "0xdd6b5fb6dc984fda0222fb6f6e96b471c0667b12f03b1e804f7b5e6ab62acdb0" } } ], "images": [ [ { "width": 1024, "height": 974, "url": "ipfs://QmUGmycxrwFec15UC41v9bvnRStK3zxR7mth72mGRcUSPD", "verification": { "method": "keccak256(bytes)", "data": "0x951bf983a4b7bcebc5c0b00a5e783630dcb788e95ee9e44b0b7d4bde4a0b4d81" } } ] ], "assets": [ { "verification": { "method": "keccak256(bytes)", "data": "0x88f3d704f3d534267c564019ce2b70a5733d070e71bf2c1f85b5fc487f47a46f" }, "url": "ifps://QmTDQGR26dSd3c4qJpmFwTh7gNRPnNbBf2Fg3gULypUag3", "fileType": "mp4" } ], "attributes": [] } } ```
### Deploy the LSP8 Collection script Let's create a `deployLSP8Collection.ts` file in the `scripts` folder. #### Imports For this script we will jut need to import: - the `ethers` library to interact with the blockchain - the [`@erc725/erc725.js`](../getting-started.md) library to convert the metadata to [VerifiableURI](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#verifiableuri) - the LSP8 Collection metadata json file we just created - the LSP4 metadata schema ```typescript title="scripts/deployLSP8Collection.ts" import { ethers } from 'hardhat'; import { ERC725, ERC725JSONSchema } from '@erc725/erc725.js'; import LSP4DigitalAsset from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; import lsp8CollectionMetadata from './metadata/lsp8CollectionMetadata.json'; ``` #### Constants We will need to set: - the `lsp8CollectionMetadataCID` constant that is the IPFS CID of the LSP8 Collection metadata file we just created ```typescript const lsp8CollectionMetadataCID = 'ipfs://QmcwYFhGP7KBo1a4EvbBxuvDf3jQ2bw1dfMEovATRJZetX'; ``` #### Deploy the LSP8 Collection Let's create a `main()` function that will be in charge of deploying the LSP8 Collection. ```typescript async function main() { // get LSP8Collection contract factory const LSP8Collection = await ethers.getContractFactory('LSP8Collection'); // get the deployer address so we can assign ownership to it const [deployer] = await ethers.getSigners(); // convert the lsp8CollectionMetadata to a verifiable uri const erc725 = new ERC725(LSP4DigitalAsset as ERC725JSONSchema); const encodeMetadata = erc725.encodeData([ { keyName: 'LSP4Metadata', value: { json: lsp8CollectionMetadata, url: lsp8CollectionMetadataCID, }, }, ]); // deploy LSP8Collection contract const lsp8Collection = await LSP8Collection.deploy( 'MyToken0', 'MT0', // will be the owner of the LSP8Collection contract deployer.address, // lsp4TokenType is address - see https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4tokentype 2, // encoded metadata encodeMetadata.values[0], ); // wait until the contract is mined await lsp8Collection.waitForDeployment(); // print contract address console.log('LSP8Collection deployed to:', await lsp8Collection.getAddress()); } ``` #### Final script
Click to expand/collapse the script. ```typescript import { ethers } from 'hardhat'; import { ERC725 } from '@erc725/erc725.js'; import LSP4DigitalAsset from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; import lsp8CollectionMetadata from './metadata/lsp8CollectionMetadata.json'; const lsp8CollectionMetadataCID = 'ipfs://QmcwYFhGP7KBo1a4EvbBxuvDf3jQ2bw1dfMEovATRJZetX'; async function main() { // get LSP8Collection contract factory const LSP8Collection = await ethers.getContractFactory('LSP8Collection'); // get the deployer address so we can assign ownership to it const [deployer] = await ethers.getSigners(); // convert the lsp8CollectionMetadata to a verifiable uri const erc725 = new ERC725(LSP4DigitalAsset, '', '', {}); const encodeMetadata = erc725.encodeData([ { keyName: 'LSP4Metadata', value: { json: lsp8CollectionMetadata, url: lsp8CollectionMetadataCID, }, }, ]); // deploy LSP8Collection contract const lsp8Collection = await LSP8Collection.deploy( 'MyToken0', 'MT0', // will be the owner of the LSP8Collection contract deployer.address, // lsp4TokenType is address - see https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4tokentype 2, // tokenId format is address - see https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8Collectionidformat 2, // encoded metadata encodeMetadata.values[0], ); // wait until the contract is mined await lsp8Collection.waitForDeployment(); // print contract address console.log('LSP8Collection deployed to:', await lsp8Collection.getAddress()); } main().catch((error) => { console.error(error); process.exitCode = 1; }); ```
#### Run the script Let's run the script using `npx hardhat run scripts/deployLSP8Collection.ts --network `. :::note The deployed contract address should be printed in the console. Make sure to copy it as we will need it for the next script. ::: #### Check the deployed contract If you happen to have deployed the contract on one of our network (Testnet or Mainnet), you can check the contract on our [ERC725 Inspect tool](https://erc725-inspect.lukso.tech/inspector?network=lukso+mainnet). By pasting the address of the contract, you should see that it supports: - [ERC725Y](/standards/metadata/lsp2-json-schema.md) - [LSP8IdentifiableDigitalAsset](/standards/tokens/LSP8-Identifiable-Digital-Asset.md) ### Mint the LSP7 Sub-Collections script Let's create a `mintLSP7SubCollections.ts` file in the `scripts`. #### Imports For this script we will just need to import: - the `ethers` library to interact with the blockchain - the ERC725 library to convert the metadata - the LSP7 Sub-Collection metadata json file - the LSP4 metadata schema ```typescript import { ethers } from 'hardhat'; import { ERC725, ERC725JSONSchema } from '@erc725/erc725.js'; import lsp7SubCollectionMetadata from './metadata/lsp7SubCollectionMetadata.json'; import LSP4DigitalAsset from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; ``` #### Constants For this script, we will need to set the following constants: - `lsp8CollectionContractAddress`: the address of the LSP8 Collection contract we just deployed - `lsp7SubCollectionName`: the name of the LSP7 Sub-Collection we want to mint - `lsp7SubCollectionSymbol`: the symbol of the LSP7 Sub-Collection we want to mint - `lsp7SubCollectionType`: the token type of the LSP7 Sub-Collection we want to mint - `lsp7SubCollectionIsNonDivisible`: whether the LSP7 Sub-Collection we want to mint is divisible or not - `lsp7SubcollectionTotalSupply`: the total supply of the LSP7 tokens we want to mint - `lsp7SubCollectionMetadataCID`: the IPFS CID of the LSP7 Sub-Collection metadata file we just created ```typescript const lsp8CollectionContractAddress = '0x567B9322500069725db0169C362dc4e939934c8b'; const lsp7SubCollectionName = 'KLxENDLESS MEDALLION Purple'; const lsp7SubCollectionSymbol = 'KLxENDLESS MEDALLION'; const lsp7SubCollectionType = 2; const lsp7SubCollectionIsNonDivisible = true; // decimals will be 0 const lsp7SubCollectionSupply = 50; // Create 50 NFTs in the sub-collection const lsp7SubCollectionMetadataCID = 'ipfs://QmXrrkZwfKWK4yqaagoKPHhH148oXLgWoncFuh5d8ugsQL;'; ``` ### Mint the LSP7 Sub-Collections Let's create a `main()` function that will be in charge of minting the LSP7 Sub-Collection. ```typescript async function main() { // get LSP8Collection contract const lsp8CollectionContract = await ethers.getContractAt( 'LSP8Collection', lsp8CollectionContractAddress, ); // convert the lsp4TokenMetadata to a verifiable uri const erc725 = new ERC725(LSP4DigitalAsset); const encodedMetadata = erc725.encodeData( [ { keyName: 'LSP4Metadata', value: { json: lsp7SubCollectionMetadata, url: lsp7SubCollectionMetadataCID, }, }, ], [], ); // get deployer to set it as original receiver of the minted tokens const [deployer] = await ethers.getSigners(); // get LSP7SubCollection contract address const lsp7ContractAddress = await lsp8CollectionContract.mint.staticCall( lsp7SubCollectionName, lsp7SubCollectionSymbol, lsp7SubCollectionType, lsp7SubCollectionIsNonDivisible, lsp7SubCollectionSupply, deployer.address, encodedMetadata.values[0], ); // mint LSP7SubCollection const tx = await lsp8CollectionContract.mint( lsp7SubCollectionName, lsp7SubCollectionSymbol, lsp7SubCollectionType, lsp7SubCollectionIsNonDivisible, lsp7SubCollectionSupply, deployer.address, encodedMetadata.values[0], ); await tx.wait(); console.log('LSP7SubCollection deployed to:', lsp7ContractAddress); } ``` #### Final script
Click to expand/collapse the script. ```typescript import { ethers } from 'hardhat'; import { ERC725 } from '@erc725/erc725.js'; import lsp7SubCollectionMetadata from './metadata/lsp7SubCollectionMetadata.json'; import LSP4DigitalAsset from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; const lsp8CollectionContractAddress = '0xA962b72095F7ec4b46fF195392B014E45Fd4a4dC'; const lsp7SubCollectionName = 'KLxENDLESS MEDALLION Purple'; const lsp7SubCollectionSymbol = 'KLxENDLESS MEDALLION'; const lsp7SubCollectionType = 2; const lsp7SubCollectionIsNonDivisible = true; // decimals will be 0 const lsp7SubCollectionSupply = 50; const lsp7SubCollectionMetadataCID = 'ipfs://QmXrrkZwfKWK4yqaagoKPHhH148oXLgWoncFuh5d8ugsQL'; async function main() { // get LSP8Collection contract const lsp8CollectionContract = await ethers.getContractAt( 'LSP8Collection', lsp8CollectionContractAddress, ); // convert the lsp4TokenMetadata to a verifiable uri const erc725 = new ERC725(LSP4DigitalAsset, '', '', {}); const encodedMetadata = erc725.encodeData( [ { keyName: 'LSP4Metadata', value: { json: lsp7SubCollectionMetadata, url: lsp7SubCollectionMetadataCID, }, }, ], [], ); // get deployer to set it as original receiver of the minted tokens const [deployer] = await ethers.getSigners(); // get LSP7SubCollection contract address const lsp7ContractAddress = await lsp8CollectionContract.mint.staticCall( lsp7SubCollectionName, lsp7SubCollectionSymbol, lsp7SubCollectionType, lsp7SubCollectionIsNonDivisible, lsp7SubCollectionSupply, deployer.address, encodedMetadata.values[0], ); // mint LSP7SubCollection const tx = await lsp8CollectionContract.mint( lsp7SubCollectionName, lsp7SubCollectionSymbol, lsp7SubCollectionType, lsp7SubCollectionIsNonDivisible, lsp7SubCollectionSupply, deployer.address, encodedMetadata.values[0], ); await tx.wait(); console.log('LSP7SubCollection deployed to:', lsp7ContractAddress); } // We recommend this pattern to be able to use async/await everywhere // and properly handle errors. main().catch((error) => { console.error(error); process.exitCode = 1; }); ```
#### Run the script Let's run the script using `npx hardhat run scripts/mintLSP7SubCollections.ts --network `. #### Check the deployed contract If you happen to have deployed the contract on one of our network (Testnet or Mainnet), you can check the contract on our [ERC725 Inspect tool](https://erc725-inspect.lukso.tech/inspector?network=lukso+mainnet). By pasting the address of the contract, you should see that it supports: - [ERC725Y](../../../standards/metadata/lsp2-json-schema.md) - [LSP7DigitalAsset](../../../standards/tokens/LSP7-Digital-Asset.md) ## Conclusion In this guide, we have seen how to create an LSP8 Collection that will be in charge of deploying LSP7 Sub-Collections and minting the initial supply. This is one way of doing it and can be adapted to your needs. --- --- sidebar_label: 'Read LSP8 NFT Metadata' sidebar_position: 4 description: Learn how to read the metadata specific to a LSP8 NFT. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Read LSP8 NFT Metadata If your digital asset contract is an [LSP8](/standards/tokens/LSP8-Identifiable-Digital-Asset.md) NFT or Collection, you can fetch the metadata of specific token IDs. There are two different ways to retrieve the metadata of a `tokenId` based on the configuration of the contract. | Method 1 - Call [`getDataForTokenId(...)`](../../../contracts/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md#getdatafortokenid) **(recommended)** | Method 2 - Read [`LSP8TokenMetadataBaseURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenmetadatabaseuri) | | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | This method retrieves individual metadata directly from the contract. Suitable for any token ID formats, including non-sequential token IDs, token IDs created after contract deployment, or if the metadata was updated for a certain subset. | With this method, you can dynamically generate the URL to individual metadata files. This is usually done when the token IDs of an NFT or Collection can be pre-determined by a sequence, are set up in advance, or if metadata is uploaded or updated in bulk. | :::info Order of Data Fetches Due to different versions of setting and fetching token IDs based on the asset conditions, returned values might be empty. Therefore, it's **recommended to first call** the [`getDataForTokenId(...)`](../../../contracts/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md#getdatafortokenid) to check for specific metadata. If the metadata is not set on the token ID, **continue to retrieve** the [`LSP8TokenMetadataBaseURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenmetadatabaseuri) of the [LSP8](../../../standards/tokens/LSP8-Identifiable-Digital-Asset.md) contract. If neither _Token ID Metadata_ nor _Base URI_ are set, you should fall back and fetch the [Global Token Information](#global-token-information), potentially including a Base URI to [retrieve the JSON content](#get-the-json-content). ::: ## Setup We will need the following dependencies to follow this guide: - [`lsp-smart-contracts`](../../../tools/lsp-smart-contracts/getting-started.md) to import the LSP8 contract ABI. - [`erc725.js`](../../../tools/dapps/erc725js/getting-started.md) to easily get [ERC725Y](/standards/erc725.md) data keys and decode their values. ```bash npm i ethers @erc725/erc725.js @lukso/lsp-smart-contracts ``` ```bash npm i web3 @erc725/erc725.js @lukso/lsp-smart-contracts ``` ## Create instance of the LSP8 Contract Create an instance of the LSP8 NFT contract, replacing the `` with the actual contract address. You can give it a try using a sample LSP8 asset on the LUKSO Testnet: [`0x8734600968c7e7193BB9B1b005677B4edBaDcD18`](https://wallet.universalprofile.cloud/asset/0x8734600968c7e7193BB9B1b005677B4edBaDcD18?network=testnet). ```js // Add the necessary imports to your JS file import { ethers } from 'ethers'; import lsp8Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; const provider = new ethers.JsonRpcProvider('https://4201.rpc.thirdweb.com'); // Create contract instance const myAssetContract = new ethers.Contract( '', lsp8Artifact.abi, provider, ); ``` ```bash npm install web3 @erc725/erc725.js @lukso/lsp-smart-contracts ``` ```js // Add the necessary imports to your JS file import Web3 from 'web3'; import lsp8Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; const web3 = new Web3( new Web3.providers.HttpProvider('https://4201.rpc.thirdweb.com'), ); // Create contract instance const myAssetContract = new web3.eth.Contract( lsp8Artifact.abi, '', ); ``` ## Preparing the Token IDs Format The [LSP8](../../../standards/tokens/LSP8-Identifiable-Digital-Asset.md) allows for different [Token ID Formats](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformat), meaning developers can specify their token IDs as `Number`, `String`, `Smart Contract Address`, `Byte Identifier` or `Hash Digest`. To call the contract, you **must first prepare your token IDs** to match the standardized **Byte32 Hex Strings** based on the [`LSP8TokenIdFormat`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformat) standardization. The **global token ID format** can be fetched from the [ERC725Y](/standards/erc725.md#erc725y-generic-data-keyvalue-store) data storage using the [`getData()`](../../../contracts/contracts/ERC725/ERC725.md#getdata) function: ```js // ... // Get the global token ID format let tokenIdFormat = parseInt( await myAssetContract.getData(ERC725YDataKeys.LSP8['LSP8TokenIdFormat']), 16, ); console.log(tokenIdFormat); // 0 ``` ```js // ... // Get the global token ID format let tokenIdFormat = parseInt( await myAssetContract.methods .getData(ERC725YDataKeys.LSP8['LSP8TokenIdFormat']) .call(), 16, ); console.log(tokenIdFormat); // 0 ``` Its value can indicate whether the token ID format is [equal or mixed across all token IDs](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformat) If your token ID is not yet compatible to [`LSP8TokenIdFormat`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformat), you have to convert it to the correct format first. Otherwise, you will be able to directly continue with fetching the metadata.
How to convert a tokenID to a Byte32 Hex String according to LSP8TokenIdFormat ```js // ... // Sample Token ID of the contract // Could be 1, my-token-id, 0x123, etc. const myTokenId = '1'; // Convert a token ID according to LSP8TokenIdFormat const convertTokenId = (tokenID: string, tokenIdFormat: number) => { switch (tokenIdFormat) { case 0: case 100: // uint256 - Number (Left padded) return ethers.zeroPadValue('0x0' + BigInt(tokenID).toString(16), 32); case 1: case 101: // string - String (Right padded) return ethers.encodeBytes32String(tokenID).padEnd(32, '0'); case 2: case 102: // address - Smart Contract (Left padded) return ethers.zeroPadValue(tokenID, 32); case 3: case 103: // bytes32 - Unique Bytes (Right padded) return ethers .hexlify(ethers.getBytes(tokenID).slice(0, 32)) .padEnd(66, '0'); case 4: case 104: // bytes32 - Hash Digest (No padding) return tokenID; } }; let byte32TokenId = convertTokenId(myTokenId, tokenIdFormat); console.log(byte32TokenId); // 0x0000000000000000000000000000000000000000000000000000000000000001 // If token ID format is mixed, retrieve it for the individual token ID if (tokenIdFormat >= 100) { tokenIdFormat = parseInt( await myAssetContract.getDataForTokenId( byte32TokenId, ERC725YDataKeys.LSP8['LSP8TokenIdFormat'], ), 16, ); byte32TokenId = convertTokenId(myTokenId, tokenIdFormat); console.log(tokenIdFormat); // 0x0000000000000000000000000000000000000000000000000000000000000001 } ``` ```js // ... // Sample Token ID of the contract // Could be 1, my-token-id, 0x123, etc. const myTokenId = '1'; // Convert a token ID according to LSP8TokenIdFormat const convertTokenId = (tokenID: string, tokenIdFormat: number) => { switch (tokenIdFormat) { case 0: case 100: // uint256 - Number (Left padded) return Web3.utils.padLeft(Web3.utils.toHex(myTokenId), 64); case 1: case 101: // string - String (Right padded) return Web3.utils.utf8ToHex(myTokenId).padEnd(66, '0'); case 2: case 102: // address - Smart Contract (Left padded) return Web3.utils.padLeft(myTokenId, 64); case 3: case 103: // bytes32 - Unique Bytes (Right padded) return Web3.utils.toHex(myTokenId).padEnd(66, '0'); case 4: case 104: // bytes32 - Hash Digest (No padding) return myTokenId; } }; let byte32TokenId = convertTokenId(myTokenId, tokenIdFormat); console.log(byte32TokenId); // 0x0000000000000000000000000000000000000000000000000000000000000001 // If token ID format is mixed, retrieve it for the individual token ID if (tokenIdFormat >= 100) { tokenIdFormat = parseInt( await myAssetContract.getDataForTokenId( byte32TokenId, ERC725YDataKeys.LSP8['LSP8TokenIdFormat'], ), 16, ); byte32TokenId = convertTokenId(myTokenId, tokenIdFormat); console.log(tokenIdFormat); // 0x0000000000000000000000000000000000000000000000000000000000000001 } ```
## Get Data from Token ID After preparing the token ID, you can start to fetch the ID-specific metadata. To get token ID metadata, you will have to make a direct contract call by calling [`getDataForTokenId()`](../../../contracts/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md#getdatafortokenid): ```js // ... // Sample token ID (1) parsed according to LSP8TokenIDFormat const byte32TokenId = ''; async function fetchTokenIdMetadata(tokenID: string) { // Get the encoded asset metadata const tokenIdMetadata = await myAssetContract.getDataForTokenId( tokenID, ERC725YDataKeys.LSP4['LSP4Metadata'], ); const erc725js = new ERC725(lsp4Schema); // Decode the metadata const decodedMetadata = erc725js.decodeData([ { keyName: 'LSP4Metadata', value: tokenIdMetadata, }, ]); console.log(decodedMetadata); } fetchTokenIdMetadata(byte32TokenId); ``` ```js // ... // Sample token ID (1) parsed according to LSP8TokenIDFormat const byte32TokenId = ''; async function fetchTokenIdMetadata(tokenID: string) { const isLSP8 = await myAssetContract.methods.supportsInterface( INTERFACE_IDS.LSP8IdentifiableDigitalAsset, ); if (!isLSP8) { console.log('Asset is not an LSP8.'); return; } // Get the encoded asset metadata const tokenIdMetadata = await myAssetContract.methods.getDataForTokenId( tokenID, ERC725YDataKeys.LSP4['LSP4Metadata'], ); const erc725js = new ERC725(lsp4Schema); // Decode the metadata const decodedMetadata = erc725js.decodeData([ { keyName: 'LSP4Metadata', value: tokenIdMetadata, }, ]); console.log(decodedMetadata); } fetchTokenIdMetadata(byte32TokenId); ``` :::info Make sure to adjust `` with the actual token ID as Byte32 Hex String according to [LSP8TokenFormat](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformat). You can give it a try using a sample token ID: `0x0000000000000000000000000000000000000000000000000000000000000001` representing token ID `1` of the `Number` format. :::
Show result ```js { "key": "0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e", "name": "LSP4Metadata", "value": { "verification": { "method": "keccak256(utf8)", "data": "0x9eefcdac3d60500619b075273c0371a6633d8f531179c882facd4f991281c658" }, "url": "ipfs://QmeKNiTr4xfdHDUinGmYC4osu1ZHoFHDDj87WBSX5z4k7x" } } ```
After retrieving the metadata from the contract, you can continue to [retrieve the actual JSON content](#get-the-json-content). If the token ID data is empty, continue fetching the Base URI and retrieving the JSON using a file link. ## Get Data from Base URI :::caution Version Support Assets created with LSP versions below 🛠️ [`@lukso/lsp-smart-contracts`](/tools/lsp-smart-contracts/getting-started.md) of `v0.14.0` lack support for retrieving token ID metadata from a Base URI. For previous LSP8 assets, the Base URI may be retrievable by calling the [`fetchData`](../../../tools/dapps/erc725js/methods.md#fetchdata) function as described in the [Global Token Information](#global-token-information) section. ::: You can fetch the [`LSP8TokenMetadataBaseURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenmetadatabaseuri) and build the correct metadata link by concatenating the [formatted](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformat) token ID. Based on the [`LSP8TokenIDFormat`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformat), the Base URI can either be: - **equal across all token IDs**: To fetch the global Base URI, use the [`getData(...)`](../../../contracts/contracts/ERC725/ERC725.md#getdata) function of the asset to receive the [ERC725Y data storage](/standards/erc725.md#erc725y-generic-data-keyvalue-store). This applies if the [`LSP8TokenIDFormat`](#preparing-the-token-ids) is `0, 1, 2, or 4`. - **mixed across all token IDs**: To fetch the individual Base URI, use the [`getDataFromTokenID(...)`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatafortokenid) function using a specific token ID. This has to be done if the [`LSP8TokenIDFormat`](#preparing-the-token-ids) is `100, 101, 102, or 104`. ```js // ... async function fetchBaseURI(tokenID: string, tokenIdFormat: number) { // Retrieve the global Base URI let tokenBaseURI = await myAssetContract.getData( ERC725YDataKeys.LSP8['LSP8TokenMetadataBaseURI'], ); if (tokenBaseURI == '0x') { console.log('BaseURI not set.'); return; } if (tokenIdFormat >= 100) { tokenBaseURI = await myAssetContract.getDataForTokenId( byte32TokenId, ERC725YDataKeys.LSP8['LSP8TokenIdFormat'], ); } // Decode the baseURI const decodedBaseURI = erc725js.decodeData([ { keyName: 'LSP8TokenMetadataBaseURI', value: tokenBaseURI, }, ]); // Return Base URI return decodedBaseURI; } const baseURI = fetchBaseURI(byte32TokenId, tokenIdFormat); console.log(baseURI); // https://my.metadata-link.xyz/asset ``` ```js /// ... async function fetchBaseURI(tokenID: string, tokenIdFormat: number) { // Retrieve the global Base URI let tokenBaseURI = await myAssetContract.methods.getData( ERC725YDataKeys.LSP8['LSP8TokenMetadataBaseURI'], ); if (tokenBaseURI == '0x') { console.log('BaseURI not set.'); return; } if (tokenIdFormat >= 100) { tokenBaseURI = await myAssetContract.methods.getDataForTokenId( byte32TokenId, ERC725YDataKeys.LSP8['LSP8TokenIdFormat'], ); } // Decode the baseURI const decodedBaseURI = erc725js.decodeData([ { keyName: 'LSP8TokenMetadataBaseURI', value: tokenBaseURI, }, ]); // Return Base URI return decodedBaseURI; } const baseURI = fetchBaseURI(byte32TokenId, tokenIdFormat); console.log(baseURI); // https://my.metadata-link.xyz/asset ``` ## Get the JSON Content After **retrieving and decoding** the [Token ID Metadata](#get-data-from-token-id) or [Base URI](#get-data-from-base-uri), you can fetch the metadata JSON. If you retrieved the metadata using [`getDataFromTokenID(...)`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#getdatafortokenid), the URL will be nested within the `value` field of the metadata. However, this link might only be partial string or content ID, instead of a full link. Therefore, you may have to adjust the link before it can be fetched: ```js // ... const metadataURL = decodedMetadata[0].value.url; function generateMetadataLink(link: string) { // If link is a regular Web2 Link, it can be passed back if (link.startsWith('https://') || link.startsWith('http://')) { // Use your default IPFS Gateway address return link; } // If link has custom protocol, adjust the link if (link.startsWith('ipfs://')) { // Use your default IPFS Gateway address return `https://api.universalprofile.cloud/ipfs/${link.slice(7)}`; } else { return null; } // Handle other cases if needed ... } // Build link to JSON metadata const metadataJsonLink = generateMetadataLink(metadataURL); // Fetch the URL if (metadataJsonLink) { const response = await fetch(metadataJsonLink); const jsonMetadata = await response.json(); console.log('Metadata Contents: ', jsonMetadata); } else { console.log('Could not generate metadata link based on value.url content.'); } ``` If you retrieved the metadata using [`LSP8TokenMetadataBaseURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenmetadatabaseuri), the URL will always be generated by combining the Base URL with previously prepared token ID as Byte32 Hex String. You can simply concatenate them to retrieve the full link. However, the token ID needs to be decoded first.
How to decode a tokenID from Byte32 Hex String according to LSP8TokenIdFormat ```js // ... function decodeTokenId(encodedTokenId: string, tokenIdFormat: number) { switch (tokenIdFormat) { // Number case 0: case 100: return BigInt(encodedTokenId).toString(); // String case 1: case 101: return ethers.toUtf8String(encodedTokenId).replace(/\0+$/, ''); // Address case 2: case 102: return '0x' + encodedTokenId.slice(encodedTokenId.length - 40); // Byte Value case 3: case 103: // Extracts the non-zero portion (right padded) return encodedTokenId.replace(/0+$/, ''); // Hash Digest case 4: case 104: // Hash digests are not modified during encoding, so return as is return encodedTokenId; } } // Decode the token ID based on the token ID format const decodedTokenId = decodeTokenId(byte32TokenId, tokenIdFormat); ``` ```js // ... function decodeTokenId(encodedTokenId: string, tokenIdFormat: number) { switch (tokenIdFormat) { // Number case 0: case 100: return BigInt(encodedTokenId).toString(); // String case 1: case 101: return web3.utils.hexToUtf8(encodedTokenId).replace(/\0+$/, ''); // Address case 2: case 102: return '0x' + encodedTokenId.slice(encodedTokenId.length - 40); // Byte Value case 3: case 103: // Extracts the non-zero portion (right padded) return encodedTokenId.replace(/0+$/, ''); // Hash Digest case 4: case 104: // Hash digests are not modified during encoding, so return as is return encodedTokenId; } } // Decode the token ID based on the token ID format const decodedTokenId = decodeTokenId(byte32TokenId, tokenIdFormat); ```
```js // ... // Build link to JSON metadata const baseURLlink = decodedBaseURI[0].value.url; const metadataJsonLink = `${baseURLlink}${decodedTokenId}`; // Fetch the URL const response = await fetch(metadataJsonLink); const jsonMetadata = await response.json(); console.log('Metadata Contents: ', jsonMetadata); ```
Show result ```js { "LSP4Metadata": { "name": "My Token Name", "description": "Sample Description", "links": [{ "title": "", "url": "" }], "icon": [ { "width": 1600, "height": 1600, "url": "ipfs://QmRHz3nbd2wQ4uNCJQS9JDnZRdD6aqueWRZ2h89dMkCLXf" } ], "images": [ [ { "width": 1000, "height": 1000, "url": "ipfs://QmRHz3nbd2wQ4uNCJQS9JDnZRdD6aqueWRZ2h89dMkCLXf", "verification": { "method": "keccak256(bytes)", "data": "0x7e89fc626703412916d27580af2bae16db479036f12d4d48f4efd24d70224dc2" } } ] ], "assets": [], "attributes": [ { "key": "Standard type", "value": "LSP", "type": "string" }, { "key": "Standard number", "value": 4, "type": "number" } ] } } ```
--- --- sidebar_label: 'Set LSP8 NFT Metadata' sidebar_position: 5 description: Learn how to set the metadata of a NFT part of a LSP8 Identifiable Digital Asset Collection. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Set LSP8 NFT Metadata In this guide you will learn how to set the metadata of a specific NFT (represented by its `bytes32 tokenId`) part of a [LSP8 Identifiable Digital Asset](../../../standards/tokens/LSP8-Identifiable-Digital-Asset.md) collection. ## Setup You will need the address of an existing LSP8 NFT collection in order to follow this tutorial. This represent the LSP8 collection that includes the NFT you want to update metadata for. For instance [`0x37934A275EFd47DFce671CA3CBaE34d9138CF2D2.`](https://explorer.execution.testnet.lukso.network/address/0x37934A275EFd47DFce671CA3CBaE34d9138CF2D2?tab=read_contract) The following code snippets require the installation of the following libraries: - [`ethers.js`](https://github.com/ethers-io/ethers.js/) or [`web3.js`](https://www.npmjs.com/package/web3) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) ```shell npm install ethers @lukso/lsp-smart-contracts ``` ```shell npm install web3 @lukso/lsp-smart-contracts ``` ## Imports and constants Import `web3.js`/`ethers`, the [`LSP8IdentifiableDigitalAsset`](../../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md) ABI from [`@lukso/lsp-smart-contracts`](../../../contracts/introduction.md) and create an instance of this contract with the `lsp8ContractAddress`. ```javascript import { ethers } from 'ethers'; // import smart contract ABI import LSP8IdentifiableDigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; const provider = new ethers.BrowserProvider(window.lukso); await provider.send('eth_requestAccounts', []); const signer = await provider.getSigner(); const lsp8ContractAddress = '0x...'; ``` ```javascript import Web3 from 'web3'; // import smart contract ABI import LSP8IdentifiableDigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; const web3 = new Web3(window.lukso); await web3.eth.requestAccounts(); const accounts = await web3.eth.getAccounts(); const lsp8ContractAddress = '0x...'; ``` ## Instantiate the LSP8 contract Create an instance of the LSP8 collection contract as shown below: ```javascript const lsp8Contract = new ethers.Contract( lsp8ContractAddress, LSP8IdentifiableDigitalAsset.abi, ); ``` ```javascript const myToken = new web3.eth.Contract( LSP8IdentifiableDigitalAsset.abi, lsp8ContractAddress, ); ``` ## Encode the Metadata The next step is to encode the metadata. To do so, we need: - a JSON file that contains all the metadata of the specific NFT. This metadata has the same format as the `LSP4Metadata`. - the IPFS url where this JSON file has been uploaded The value will be encoded as a `VerifiableURI`. We will use the `encodeData` function from the [_erc725.js_](../../../tools/dapps/erc725js/methods.md#encodedata) library to encode a `VerifiableURI` easily. ```js title="encodeVerifiableURI.ts" import { ERC725 } from '@erc725/erc725.js'; import NFTMetadataJSON from './NFTMetadata.json'; const schema = [ { name: 'LSP4Metadata', key: '0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e', keyType: 'Singleton', valueType: 'bytes', valueContent: 'VerifiableURI', }, ]; const myErc725 = new ERC725(schema); myErc725.encodeData([ { keyName: 'LSP4Metadata', value: { json: NFTMetadataJSON, url: 'ipfs://QmQTqheBLZFnQUxu5RDs8tA9JtkxfZqMBcmGd9sukXxwRm', }, }, ]); ``` You can also check the code snippet example in the LSP2 specs to learn in details the [encoding of a `VerifiableURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#verifiableuri). ## Send the transaction to set metadata for a tokenId The last step is to set the metadata for a specific [`tokenId`](../../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#format-of-tokenids). You can then send the transaction to set the metadata for the given NFT represented by its `tokenId`. Here we will use the following parameters as examples: - `tokenId`: `0x0000000000000000000000000000000000000000000000000000000000000001` - `dataKey`: [`LSP4Metadata`](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata) - `metadataValue`: some placeholder value as a [`VerifiableURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#verifiableuri). > Note that the `tokenId` is a `bytes32` value (hex) ```javascript import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; // import and instantiate contract from previous steps // change this with the actual tokenId to update metadata for const tokenId = '0x0000000000000000000000000000000000000000000000000000000000000001'; // change this with the actual VerifiableURI of the metadata uploaded somewhere (S3, IPFS, etc...) const metadataValue = '0x...'; await lsp8Contract.setDataForTokenId( tokenId, ERC725YDataKeys.LSP4['LSP4Metadata'], metadataValue, ); ``` ```javascript import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; // import and instantiate contract from previous steps // change this with the actual tokenId to update metadata for const tokenId = '0x0000000000000000000000000000000000000000000000000000000000000001'; // change this with the actual VerifiableURI of the metadata uploaded somewhere (S3, IPFS, etc...) const metadataValue = '0x...'; await lsp8Contract.methods .setDataForTokenId( tokenId, ERC725YDataKeys.LSP4['LSP4Metadata'], metadataValue, ) .send({ from: accounts[0] }); ``` --- --- sidebar_label: '🔍 Detect Token Type' sidebar_position: 3 description: Retrieve LUKSO LSP token types and detect if an asset is a Token, an NFT, or a collection. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 🗃️ Retrieve Token Type To detect if an asset is a **Token**, an **NFT** or a **Collection**, we can check the value stored in the [`LSP4TokenType`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#types-of-digital-assets) data key. This guide show you how to retrieve the token type of a deployed token contract using the [`getData(...)`](../../contracts/contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.md#getdata) function, passing the `LSP4TokenType` data key as a parameter. We will show you example with 3 different libraries: _erc725.js_, _web3.js_ and _ethers.js_ ## Introduction Token Types are beneficial because of the wide range of asset use cases. The [LSP7](../../standards/tokens/LSP7-Digital-Asset.md) and [LSP8](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md) can both be used as NFTs. - LSP7 can be used for building NFTs where each individual items have the same metadata, and users are allowed to mint multiple NFTs at once. - In comparison, LSP8 is mainly used for NFTs with unique properties per item (like phygitals, dynamic NFTs or unique collections like [Chillwhales](https://www.chillwhales.com/)). :::tip Convenience Tools You can use the ⚒️ [`erc725.js`](../../tools/dapps/erc725js/getting-started.md) library, which automatically decodes [ERC725Y](/standards/erc725.md#erc725y-generic-data-keyvalue-store) storage keys for you. If you are using a regular contract instance from Ethers or Web3, you can use the data keys from the [`lsp-smart-contracts`](../../tools/lsp-smart-contracts/getting-started.md) library by importing the `ERC725YDataKeys` constant. ::: ```bash npm install @erc725/erc725.js ``` ```bash npm install ethers @lukso/lsp-smart-contracts ``` ```bash npm install web3 @lukso/lsp-smart-contracts ``` ## Retrieve the Token Type After setting up the contract, retrieving its token type is as simple as making one contract call to the `getData(...)` function. ```js import { ERC725 } from '@erc725/erc725.js'; import lsp4Schema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; const myAsset = new ERC725( lsp4Schema, '', // Your Asset Address 'https://4201.rpc.thirdweb.com', // LUKSO Testnet RPC {}, ); // Retrieve the token type const tokenType = await myAsset.getData('LSP4TokenType'); console.log(tokenType); // 0 = Token // 1 = NFT // 2 = Collection ``` ```js import { ethers } from 'ethers'; // Import LSP4 Token ABI. LSP4 is inherited by both LSP7 and LSP8. // LSP4 represents the metadata storage of the token contract and contains the functions to get and set data. // Since we are only using the `getData(...)` function, we only need the LSP4 ABI. import LSP4Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP4DigitalAssetMetadata.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; // Connect provider to LUKSO Testnet const provider = new ethers.JsonRpcProvider('https://4201.rpc.thirdweb.com'); // Create contract instance const myAssetContract = new ethers.Contract( '', LSP4Artifact.abi, provider, ); // Retrieve the token type (this will be abi-encoded) const tokenTypeEncoded = await myAssetContract.getData( ERC725YDataKeys.LSP4.LSP4TokenType, ); // Decode from abi-encoded uint256 to a number // e.g: 0x0000...0002 -> 2 const abiCoder = ethers.AbiCoder.defaultAbiCoder(); const tokenType = abiCoder.decode(['uint256'], tokenTypeEncoded); console.log(tokenType); // 0 = Token // 1 = NFT // 2 = Collection ``` ```js import Web3 from 'web3'; // Import LSP4 Token ABI. LSP4 is inherited by both LSP7 and LSP8. // LSP4 represents the metadata storage of the token contract and contains the functions to get and set data. // Since we are only using the `getData(...)` function, we only need the LSP4 ABI. import LSP4Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP4DigitalAssetMetadata.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; // Connect provider to LUKSO Testnet const web3 = new Web3( new Web3.providers.HttpProvider('https://4201.rpc.thirdweb.com'), ); // Create contract instance const myAssetContract = new web3.eth.Contract( LSP4Artifact.abi, '', ); // Retrieve the token type const tokenTypeValue = await myAssetContract.methods.getData( ERC725YDataKeys.LSP4.LSP4TokenType, ); // Decode from abi-encoded uint256 to a number // e.g: 0x0000...0002 -> 2 const tokenType = web3.eth.abi.decodeParameter('uint256', tokenTypeValue); console.log(tokenType); // 0 = Token // 1 = NFT // 2 = Collection ``` --- --- sidebar_label: 'Basic LSP7 Token' sidebar_position: 2 description: Learn how to create your own basic fungible token on LUKSO using the LSP7 Digital Asset standard. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 🪙 Create a LSP7 Token This guide will walk you through the process of creating and deploying a custom [LSP7 Digital Asset](/standards/tokens/LSP7-Digital-Asset.md) and pre-mint a certain amount of tokens to the token owner. To build a smart contract using LSPs, you can **inherit functionality** from modular and standardized presets in the [`@lukso/lsp-smart-contracts`](/tools/lsp-smart-contracts/getting-started.md) library. To learn more about the contract standards itself, please refer to the [Contracts section](/contracts/introduction.md) of our documentation. :::tip You can learn about the project setup and Hardhat & Foundry workflow by checking the [Getting Started](/tools/#smart-contracts) section. ::: ## Create the Token For our sample deployment of the LSP7 token, we will use the following presets: - [`LSP7Mintable`](/contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md): allow the contract [`owner`](/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#owner) to mint new tokens. - [`LSP7Burnable`](/contracts/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.md): allow any token holders to burn tokens. You can then import them within your Solidity contract file: ```solidity title="MyCustomToken.sol" // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.9; import "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.sol"; import "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.sol"; contract CustomToken is LSP7Mintable, LSP7Burnable { // your custom token logic ... } ``` After inheriting, the contract **expects the mandatory parameters** related to the imported standards. In case of [`LSP7`](/standards/tokens/LSP7-Digital-Asset.md), you must define default token parameters in the constructor of the smart contract, that will be set during the deployment of the contract: - the [token name and symbol](/standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokenname) (inherited from [LSP4](/standards/tokens/LSP4-Digital-Asset-Metadata.md)) - the address of the initial token owner - the [token type](/standards/tokens/LSP4-Digital-Asset-Metadata#with-lsp7-digital-asset-token) of the asset - the [divisibility](/standards/tokens/LSP7-Digital-Asset#divisible-vs-non-divisible) of token units (specific to [LSP7](/standards/tokens/LSP7-Digital-Asset)) You can specify the parameters and the mint function as seen below. ```solidity title="MyCustomToken.sol" // ... contract CustomToken is LSP7Mintable, LSP7Burnable { constructor( string memory tokenName_, string memory tokenSymbol_, address tokenContractOwner_, uint256 lsp4TokenType_, bool isNonDivisible_ ) LSP7Mintable( tokenName_, tokenSymbol_, tokenContractOwner_, lsp4TokenType_, isNonDivisible_ ) { { // your custom smart contract logic ... mint( msg.sender, // deployer will receive initial tokens 20_000 * 10 ** decimals(), // will mint 20k tokens true, // force parameter "" // optional transaction data ); } } } ``` :::info To adjust the parameters of the mint, please have a look at the related [LSP7 function documentation](/contracts/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md#mint). You can find the **full documentation** for [LSP7](/contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable#parameters-16) and other **presets** within the [Technical ABI Reference](/contracts/contracts/ERC725/). ::: ## Deploy the Token :::success Want to deploy token contracts from your 🆙? Have a look at our [Deploy Contracts from UP](../../universal-profile/interactions/deploy-contracts.md) guide on how to deploy any contract using the Universal Profile Browser Extension! ::: ```ts title="scripts/deployLSP7AsEOA.ts" import { ethers } from 'hardhat'; import * as dotenv from 'dotenv'; // Load environment variables dotenv.config(); async function deployToken() { // Signer used for deployment const [deployer] = await ethers.getSigners(); console.log('Deploying contract with EOA: ', deployer.address); // Deploy the contract with custom constructor parameters const customToken = await ethers.deployContract('MyCustomToken', [ 'My Custom Token', // token name 'MCT', // token symbol deployer.address, // owner 0, // token type = TOKEN false, // isNonDivisible? ]); // Wait for the transaction to be included in a block await customToken.waitForDeployment(); const customTokenAddress = await customToken.getAddress(); console.log('Token deployed at: ', customTokenAddress); } deployToken() .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); }); ``` If you have not yet setup the LUKSO networks and private keys in Hardhat, please check out the previous [Getting Started](/learn/getting-started.mdx) guide for smart contract developers. If you set up the Hardhat configuration, you can execute the deployment script using the following command: ```bash npx hardhat --network luksoTestnet run scripts/deployLSP7AsUP.ts ``` :::tip You can check the deployed token address on the [Testnet Execution Explorer](https://explorer.execution.testnet.lukso.network/). ::: ## Verify the Token In order to verify a contract, you have to create a file with all the constructor arguments that you've set during deployment. The parameters and the compiled contract code are then compared with the payload of the deployed contract. First, create the file with all constructor parameters: ```ts title="verify/myCustomToken.ts" module.exports = [ 'My Custom Token', // token name 'MCT', // token symbol '0x...', // deployer address 0, // token type false, // divisibility ]; ``` To verify the deployed token, you can use the **blockscout API properties** set up within the [Getting Started](/learn/getting-started.mdx) section. If you configured the API, you will be able to run the verification by specifying the _token address_, _paramter file_, and _network_: ```bash npx hardhat verify --constructor-args ./verify/myCustomToken.ts --network luksoTestnet ``` --- --- sidebar_label: '🔀 Transfer Tokens / NFTs in Batch' sidebar_position: 6 description: This guide shows you how to transfer a token to multiple addresses or multiple NFTs from a collection to the same or different recipient addresses. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Transfer Tokens / NFTs in Batch The LSP7 and LSP8 standards contain a `transferBatch(...)` function that can be useful to perform batch transfers in a single transaction. For instance, it enables to: - transfer the same LSP7 token to multiple different addresses. - transfer multiple NFTs from the same LSP8 collection to the same recipient. - transfer multiple NFTs from the same LSP8 collection to different recipients. The code snippets below are coupled with examples of use cases of how the `transferBatch(...)` can be used for real life examples in applications. ## Setup You will need the following dependencies here: ```bash npm install ethers @lukso/lsp-smart-contracts ``` ```bash npm install web3 @lukso/lsp-smart-contracts ``` ## Transfer tokens to multiple recipients The code snippet below uses the [`transferBatch(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#transferbatch) function from `LSP7DigitalAsset` to transfer to multiple recipients can be useful for scenarios such as: Examples scenarios of transferring the same or different amounts of a token to multiple recipients could be: - distribute token dividends to multiple shareholders in a single transaction. - provide the same token for different liquidity pools in a defi protocol. ```ts import { ethers } from 'ethers'; import LSP7DigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; // Connect to the wallet in the browser 🧩 // and retrieve signer (🆙 Browser Extension or any other wallet 👝) const provider = new ethers.BrowserProvider(window.lukso || window.ethereum); const account = await provider.getSigner(); console.log('Connect to account: ', account.address); const token = new ethers.Contract( '0x...', // token contract address LSP7DigitalAssetArtifact.abi, account, ); await token.transferBatch( [ // from account.address, account.address, account.address, ] [ // to (= recipients) "0x...", // alice address "0x...", // bob address "0x...", // carol address ], [ ethers.parseEther("10"), // transfer 10 tokens to Alice ethers.parseEther("20"), // transfer 20 tokens to Bob ethers.parseEther("30"), // transfer 30 tokens to Carol ], [ // `force` parameter, defines if we can transfer to EOA or contracts that do not implement LSP1 true, true, true ], [ // data "0x", // no extra data "0x", "0x", ] ); ``` ```ts import Web3 from 'web3'; import LSP7Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; // Connect to the wallet in the browser 🧩 // and retrieve signer (🆙 Browser Extension or any other wallet 👝) const web3 = new Web3(window.lukso || window.ethereum); const [account] = await web3.eth.getAccounts(); // get the first account console.log('Connect to account: ', account); const token = new web3.eth.Contract( LSP7Artifact.abi, '0x...', // token contract address ); await token.methods.transferBatch( [ // from account.address, account.address, account.address, ] [ // to (= recipients) "0x...", // alice address "0x...", // bob address "0x...", // carol address ], [ ethers.parseEther("10"), // transfer 10 tokens to Alice ethers.parseEther("20"), // transfer 20 tokens to Bob ethers.parseEther("30"), // transfer 30 tokens to Carol ], [ // `force` parameter, defines if we can transfer to EOA or contracts that do not implement LSP1 true, true, true ], [ // data "0x", // no extra data "0x", "0x", ] ).send({ from: account }); ``` ## Transfer multiple NFTs to one recipient Examples scenarios of transferring NFTs from the same collection in batch for the same recipient could be: - putting some valuable NFTs from a collection you hold into a safe vault. ```ts import { ethers } from 'ethers'; import LSP8Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; // Connect to the wallet in the browser 🧩 // and retrieve signer (🆙 Browser Extension or any other wallet 👝) const provider = new ethers.BrowserProvider(window.lukso || window.ethereum); const account = await provider.getSigner(); console.log('Connected to account: ', account.address); const nftContract = new ethers.Contract( '0x86e817172b5c07f7036bf8aa46e2db9063743a83', // Chillwhale NFT contract address LSP8Artifact.abi, account, ); const nftsRecipient = "0xcafecafecafecafecafecafecafecafecafecafe"; await nftContract.transferBatch( [ // from account.address, account.address, account.address, ] [ // to (= recipient, 3 x times the same address) nftsRecipient, nftsRecipient, nftsRecipient, ], [ // bytes32 tokenIds "0x0000000000000000000000000000000000000000000000000000000000001579", // chillwhale ID 5497 (= 0x1579 in hex) "0x00000000000000000000000000000000000000000000000000000000000006e6", // chillwhale ID 1766 (= 0x06e6 in hex) "0x00000000000000000000000000000000000000000000000000000000000016a1", // chillwhale ID 5793 (= 0x16a1 in hex) ], [ // `force` parameter, defines if we can transfer to EOA or contracts that do not implement LSP1 true, true, true ], [ // data "0x", // no extra data "0x", "0x", ] ); ``` ```ts import Web3 from 'web3'; import LSP8Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; // Connect to the wallet in the browser 🧩 // and retrieve signer (🆙 Browser Extension or any other wallet 👝) const web3 = new Web3(window.lukso || window.ethereum); const [account] = await web3.eth.getSigner(); // get the first account console.log('Connected to account: ', account); const nftContract = new ethers.Contract( LSP8Artifact.abi, '0x86e817172b5c07f7036bf8aa46e2db9063743a83', // Chillwhale NFT contract address ); const nftsRecipient = "0xcafecafecafecafecafecafecafecafecafecafe"; await nftContract.methods.transferBatch( [ // from account.address, account.address, account.address, ] [ // to (= recipient, 3 x times the same address) nftsRecipient, nftsRecipient, nftsRecipient, ], [ // bytes32 tokenIds "0x0000000000000000000000000000000000000000000000000000000000001579", // chillwhale ID 5497 (= 0x1579 in hex) "0x00000000000000000000000000000000000000000000000000000000000006e6", // chillwhale ID 1766 (= 0x06e6 in hex) "0x00000000000000000000000000000000000000000000000000000000000016a1", // chillwhale ID 5793 (= 0x16a1 in hex) ], [ // `force` parameter, defines if we can transfer to EOA or contracts that do not implement LSP1 true, true, true ], [ // data "0x", // no extra data "0x", "0x", ] ).send({ from: account }); ``` ## Transfer multiple NFTs to many recipients Examples scenarios of transferring NFTs from the same collection in batch to different recipients could be: - perform an airdrop. - following an auction for the same collection, transfer the NFTs to the winner of each lot (lot referring to each `tokenId`). ```ts import { ethers } from 'ethers'; import LSP8Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; // Connect to the wallet in the browser 🧩 // and retrieve signer (🆙 Browser Extension or any other wallet 👝) const provider = new ethers.BrowserProvider(window.lukso || window.ethereum); const account = await provider.getSigner(); console.log('Connected to account: ', account.address); const nftContract = new ethers.Contract( '0x86e817172b5c07f7036bf8aa46e2db9063743a83', // Chillwhale NFT contract address LSP8Artifact.abi, account, ); await nftContract.transferBatch( [ // from account.address, account.address, account.address, ] [ // to (= recipients) "0x...", // Alice address "0x...", // Bob address "0x...", // Carol address ], [ // bytes32 tokenIds "0x0000000000000000000000000000000000000000000000000000000000001579", // chillwhale ID 5497 (= 0x1579 in hex) "0x00000000000000000000000000000000000000000000000000000000000006e6", // chillwhale ID 1766 (= 0x06e6 in hex) "0x00000000000000000000000000000000000000000000000000000000000016a1", // chillwhale ID 5793 (= 0x16a1 in hex) ], [ // `force` parameter, defines if we can transfer to EOA or contracts that do not implement LSP1 true, true, true ], [ // data "0x", // no extra data "0x", "0x", ] ); ``` ```ts import Web3 from 'web3'; import LSP8Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; // Connect to the wallet in the browser 🧩 // and retrieve signer (🆙 Browser Extension or any other wallet 👝) const web3 = new Web3(window.lukso || window.ethereum); const [account] = await web3.eth.getSigner(); // get the first account console.log('Connected to account: ', account); const nftContract = new ethers.Contract( '0x86e817172b5c07f7036bf8aa46e2db9063743a83', // Chillwhale NFT contract address LSP8Artifact.abi, account, ); await nftContract.methods.transferBatch( [ // from account.address, account.address, account.address, ] [ // to (= recipients) "0x...", // Alice address "0x...", // Bob address "0x...", // Carol address ], [ // bytes32 tokenIds "0x0000000000000000000000000000000000000000000000000000000000001579", // chillwhale ID 5497 (= 0x1579 in hex) "0x00000000000000000000000000000000000000000000000000000000000006e6", // chillwhale ID 1766 (= 0x06e6 in hex) "0x00000000000000000000000000000000000000000000000000000000000016a1", // chillwhale ID 5793 (= 0x16a1 in hex) ], [ // `force` parameter, defines if we can transfer to EOA or contracts that do not implement LSP1 true, true, true ], [ // data "0x", // no extra data "0x", "0x", ] ).send({ from: account }); ``` --- --- sidebar_label: '🏎️ Developer Quickstart' description: Introduction to the LUKSO Ecosystem - why choose LUKSO? Who is LUKSO intended for? title: 'Quick Start' --- import CallToActionButton from '@site/src/components/CallToActionButton'; import Chip from '@site/src/components/Chip'; import CardWithContent from '@site/src/components/CardWithContent'; import LinkCards from '@site/src/components/LinkCards'; import Link from '@docusaurus/Link'; import styles from './learn.module.scss'; import DappBannerImage from '../../static/img/learn/DEVELOPERS_dApp.png'; import SmartContractBannerImage from '../../static/img/learn/DEVELOPERS_SmartContract.png'; # Developer Quickstart
  • Learn how to develop with Universal Profiles
  • Explore code examples in the LUKSO playground
  • Get started with Tokens and NFTs
  • Create a token
  • Create an Automatic Token Forwarder for your UP
  • Migrate to LUKSO
  • Refactor a Solidity ERC20 token to LSP7
  • Refactor a Solidity ERC721 NFT to LSP8
  • Visit our support website
  • Join the Developer community on Discord
  • Contact the tech team
:::info In order to follow the guides and tutorial of the LUKSO Developer documentation, you should have some basic knowledge and be familiar with the following: - Building general applications on Ethereum: [**Learning Tools of the Ethereum Foundation**](https://ethereum.org/en/developers/learning-tools/) - For smart contract developers: - Smart contract development in [**Solidity**](https://docs.soliditylang.org). - If you pick a template, [**Foundry**](https://book.getfoundry.sh/) or [**Hardhat**](https://hardhat.org/docs). - For dApp developers: - Basic programming skills in [**Javascript**](https://developer.mozilla.org/en-US/docs/Web/JavaScript) or [**Typescript**](https://www.typescriptlang.org/docs/). - Using a javascript library to interaction with web3 applications like [**web3.js**](https://docs.web3js.org/), [**ethers**](https://docs.ethers.org/v6/) or [**viem**](https://viem.sh/). ::: ## Building dApps for Universal Profiles When building dApps on LUKSO, you are interacting with [Universal Profiles 🆙](../standards/accounts/introduction.md) through the [Universal Profile Browser Extension](https://chromewebstore.google.com/detail/universal-profiles/abpickdkkbnbcoepogfhkhennhfhehfn). This page guides you on the first step to get started building on LUKSO with the 🆙 Browser Extension.
The [LUKSO Relayer API](../tools/apis/relayer-api.md) allows you to easily create and deploy Universal Profiles from your dApp in Javascript. Your users will benefit from a free monthly gas quota and will be able to submit transactions without requiring to pay for gas. A great way to onboard new users quickly and easily into your dApp! 🔌 [**Deploy with the LUKSO Relayer API**](../tools/apis/relayer-api.md). If you prefer to create a Universal Profile manually, use the LSP23 Linked Contracts Factory contract on LUKSO Mainnet. This factory contract can help you to deploy a Universal Profile + its Key Manager. However, you will have to set the metadata and permissions as well on deployment. Follow our guide below. 🏭 [**Deploy with LSP23 Linked Contract Factory**](./universal-profile/advanced-guides/deploy-up-with-lsp23.md).
:::caution Please note that Universal Profile created and deployed manually are not registered on the [LUKSO Transaction Relay Service](../tools/apis/relayer-api.md), do not get a free monthly gas quota, and as a result, do not benefit from gas-less transactions. ::: ## Resources for Builders
LUKSO is a Layer 1 EVM Blockchain. All tools and tutorials for Ethereum also work for LUKSO by default. Developers building on LUKSO can write smart contracts in any EVM-based smart contract languages (Solidity, Vyper, etc...), and use existing standards already developed for other Ethereum networks. ## Code Repositories Want to dive into the code directly? Check the following repos 😉 ### Next.js Boilerplate The [`tools-dapp-boilerplate`](https://github.com/lukso-network/tools-dapp-boilerplate) is a Next.js repository that gives you a fully working dApp with lot of ready to use components and features:
### Playground The [`lukso-playground`](https://github.com/lukso-network/lukso-playground) repository is a great place to start playing around with dApps. It includes: - ready-to-go network configurations with LUKSO [Mainnet](../networks/mainnet/parameters.md) and [Testnet](../networks/testnet/parameters.md). - a full Hardhat setup to work with smart contracts. - example scripts to fetch profile and asset metadata, update them, and even more code examples! - sample contracts for Tokens, NFTs and Universal Receivers to build smart contracts based on the [LSP standards](./benefits-lukso-standards.md). - scripts to deploy and verify contracts on the network.
--- --- sidebar_label: '🪙 ERC20 to LSP7' sidebar_position: 2 description: Learn how to migrate your ERC20 token to the LSP7 Digital Asset standard on LUKSO. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import Erc20LSP7Table from '@site/src/components/Erc20LSP7Table'; # 🪙 Migrate ERC20 to LSP7 > 👇🏻 Hands on 📽️ Solidity Workshop Video for the [**Oxford Blockchain Society**](https://x.com/oxfordblocksoc) from March 2024.
[LSP7DigitalAsset](../../standards/tokens/LSP7-Digital-Asset.md) is a new token standard that offers a wider range of functionality compared to [ERC20](https://eips.ethereum.org/EIPS/eip-20), as described in the [standard section](../../standards/tokens/LSP7-Digital-Asset.md). For migrating from ERC20 to LSP7, developers need to be aware of several key differences. :::info Resources See the [contract overview](../../contracts/overview/Token/index.md#comparisons-with-erc20--erc721) page for the interface differences between ERC20 and LSP7. ::: ## Comparisons ### Solidity code Usually, to create an ERC20 token, we import and inherit the `ERC20` contract from the [@openzeppelin/contracts](https://www.npmjs.com/package/@openzeppelin/contracts) package. ```solidity title="ERC20 Token" // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract MyERC20Token is ERC20 { constructor(string memory name, string memory symbol) ERC20(name, symbol) { // Your constructor logic } } ``` To create an LSP7 token, we should instead import `LSP7DigitalAsset` from the [`@lukso/lsp7-contracts`](https://www.npmjs.com/package/@lukso/lsp7-contracts) package, and replace it in the inheritance. To deploy an `LSP7DigitalAsset` we can use the same [`constructor`](../../contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md#constructor) parameters. but we also need to specify 2 extra parameters (_explanations of params provided in the code comments below_). - the `lsp4TokenType`. - if the token `isNonDivisible`. ```solidity title="LSP7 Token" // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.15; import "@lukso/lsp7-contracts/contracts/LSP7DigitalAsset.sol"; // highlight-next-line contract MyLSP7Token is LSP7DigitalAsset { constructor( string memory name, // Name of the token string memory symbol, // Symbol of the token address tokenOwner, // Owner able to add extensions and change metadata // highlight-next-line uint256 lsp4tokenType, // 0 if representing a fungible token, 1 if representing an NFT // highlight-next-line bool isNonDivisible // false for decimals equal to 18, true for decimals equal to 0 ) LSP7DigitalAsset(name, symbol, tokenOwner, lsp4tokenType, isNonDivisible) { // _mint(to, amount, force, data) // force: should be set to true to allow EOA to receive tokens // data: only relevant if the `to` is a smart contract supporting LSP1. _mint(tokenOwner, 200000, true, ""); } } ``` ### Functions & Behaviors Below are the function signatures of the transfer functions for ERC20 and LSP7, respectively.
**ERC20** ```solidity function transferFrom( address from, address to, uint256 amount ) external; ```
**LSP7** ```solidity function transfer( address from, address to, uint256 amount, // highlight-next-line bool force, // highlight-next-line bytes data ) external; ```
There are 3 main differences for LSP7 to note - **Additional `force` parameter**: for the [`mint(...)`](../../contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md#mint) and [`transfer(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#ransfer) functions. For full compatibility with ERC20 behavior (where the recipient can be any address), set this to `true`. Setting it to `false` will only allow the transfer to smart contract addresses supporting the [**LSP1UniversalReceiver** interfaceId](../../contracts/interface-ids.md). > See the [**LSP7 Standard > `force` mint and transfer**](../../standards/tokens/LSP7-Digital-Asset.md#lsp1-token-hooks#force-mint-and-transfer) section for more details. - **Additional `data` field**: for the `mint(...)`, `transfer(...)`, and [`burn(...)`](../../contracts/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.md#burn) functions. For full compatibility with ERC20 behavior, set this to empty bytes `""`. This data is only relevant when the recipient is a smart contract that supports the LSP1 interfaceId, where the data will be sent and the recipient can act on it (_e.g., reject the transfer, forward the tokens to a vault, etc..._). > See the [**LSP7 Standard > LSP1 Token Hooks**](../../standards/tokens/LSP7-Digital-Asset.md#lsp1-token-hooks) section for more details. - **LSP7 metadata is generic**: via a [flexible data key / value store](<(../../standards/erc725.md#erc725y-generic-data-keyvalue-store)>). It can be set and retrieved via [`setData(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#setdata) / [`setDataBatch(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#setdatabatch) and [`getData(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#getdata) / [`getDataBatch(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#getdatabatch). ERC20 metadata is limited to `name()` and `symbol()`. LSP7 allows to store any data after deployment without limitations. ### Interact with the Token Contract :::info To check function definitions and explanations of behavior and each parameter, check [API Reference](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md) section. ::: To interact with the LSP7DigitalAsset contract, different functions should be called. This is a table comparing the different function definitions: ### Events :::info To check event definitions and explanations of behavior and each parameter, check [API Reference](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md) section. ::: Services like dApps and Indexers can use different events from LSP7 to listen to activities. The table below shows the different event definitions that should be used to track activity on an LSP7-DigitalAsset contract. | ERC20 Event | LSP7 Event | | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | |
Transfer(
address indexed from,
address indexed to,
uint256 value
);
|
Transfer(
address indexed operator,
address indexed from,
address indexed to,
uint256 amount,
bool force,
bytes data
)
| |
Approval(
address indexed owner,
address indexed spender,
uint256 value
)
|
OperatorAuthorizationChanged(
address indexed operator,
address indexed tokenOwner,
uint256 indexed amount,
bytes operatorNotificationData
);
| | _No equivalent_ |
OperatorRevoked(
address indexed operator,
address indexed tokenOwner,
bool indexed notified,
bytes operatorNotificationData
)
| ## Metadata Management ### Basic Token Information
**ERC20** ```javascript const name = await token.name(); const symbol = await token.symbol(); ```
**How to retrieve?** In ERC20, the name and symbol of a token can be retrieved by calling their own function.
**LSP7** ```javascript import { keccak256, toUtf8Bytes } from 'ethers'; const nameKey = keccak256(toUtf8Bytes('LSP4TokenName')); const symbolKey = keccak256(toUtf8Bytes('LSP4TokenSymbol')); const nameValue = await token.getData(nameKey); const symbolValue = await token.getData(symbolKey); const name = ethers.toUtf8String(nameValue); const symbol = ethers.toUtf8String(symbolValue); ```
**How to retrieve?** In LSP7, the token name and symbol can be retrieved with [`getData(bytes32)`](../../contracts/contracts/ERC725/ERC725.md#getdata). They are stored in the generic metadata key-value store under the data keys [`LSP4TokenName`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokenname) and [`LSP4TokenSymbol`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokensymbol). Once you have fetched the raw hex encoded value, you will need to decode it into a human readable string.
You can import the list of data keys related to each individual LSP standard from one of our library. There are 2 options: For dApp developers, you can import the data keys from the `@lukso/lsp-smart-contracts` and use them directly in your scripts via _ethers.js_ or _web3.js_. ```javascript import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; const nameKey = ERC725YDataKeys.LSP4.LSP4TokenName; const symbolKey = ERC725YDataKeys.LSP4.LSP4TokenSymbol; const nameValue = await token.getData(nameKey); // 0x555020417374726f20373235 const symbolValue = await token.getData(symbolKey); // 0x5550373235 const name = ethers.toUtf8String(nameValue); // UP Astro 725 const symbol = ethers.toUtf8String(symbolValue); // UP725 ``` You can also obtain the full schema with all the definitions from our [`@erc725/erc725.js`](../../tools/dapps/erc725js/getting-started.md) library. **This library will also help you to [encode easily](../../tools/dapps/erc725js/methods.md#encodedata) data key value pairs.** You can also import the [full schema definition](../../tools/dapps/erc725js/schemas.md) of the LSP4 Metadata from `@erc725/erc725.js`. The library can also provide convenience for fetching, encoding and decoding. ```javascript title="Example of decoding using the LSP4 schema and erc725.js" import { ERC725 } from '@erc725/erc725.js'; import LSP4Schema from '@erc725/erc725.js/schemas/LSP4DigitalAssetMetadata.json'; const nameKey = LSP4Schema.find((schema) => schema.name == 'LSP4TokenName').key; const symbolKey = LSP4Schema.find((schema) => schema.name == 'LSP4TokenSymbol').key; const nameValue = await token.getData(nameKey); // 0x555020417374726f20373235 const symbolValue = await token.getData(symbolKey); // 0x5550373235 const [name, symbol] = ERC725.decodeData([ { keyName: 'LSP4TokenName', value: nameValue, }, { keyName: 'LSP4TokenSymbol', value: symbolValue, }, ]); /** [ { name: 'LSP4TokenName', key: '0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1', value: "UP Astro 725", }, { name: 'LSP4TokenSymbol', key: '0x2f0a68ab07768e01943a599e73362a0e17a63a72e94dd2e384d2c1d4db932756', value: "UP725", }, ] */ ``` ### Extended Token Metadata :::success Tutorial 🎥 See the [**Metadata Management**](../digital-assets/metadata-management/edit-token-metadata.md) guide + video for how to create and set the JSON metadata for your LSP7 Token. ::: LSP7 allows for more flexible and extensible metadata. The [`LSP4Metadata`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata) is a JSON object that can contain many information about the token, including: - 🌐 **official link to websites** (_e.g: project website, social media, community channels, etc..._). - 🖼️ **images** (token icon and backgrounds) to display the token in dApps, explorers, or decentralised exchanges. - 🏷️ **custom attributes** (can be displayed as badges on UIs). ```javascript const metadataKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4Metadata')); const storedMetadata = await token.getData(metadataKey); const retrievedJsonMetadata = JSON.parse(ethers.toUtf8String(storedMetadata)); // JSON Stored: { LSP4Metadata: { description: 'The first digital golden pig.', links: [ { title: 'Twitter', url: 'https://twitter.com/goldenpig123' }, { title: 'goldenpig.org', url: 'https://goldenpig.org' } ], icon: [ { width: 256, height: 256, url: 'ifps://QmW5cF4r9yWeY1gUCtt7c6v3ve7Fzdg8CKvTS96NU9Uiwr', verification: { method: 'keccak256(bytes)', data: '0x01299df007997de92a820c6c2ec1cb2d3f5aa5fc1adf294157de563eba39bb6f', } } ], images: [ // COULD be used for LSP8 NFT art [ { width: 1024, height: 974, url: 'ifps://QmW4wM4r9yWeY1gUCtt7c6v3ve7Fzdg8CKvTS96NU9Uiwr', verification: { method: 'keccak256(bytes)', data: '0xa9399df007997de92a820c6c2ec1cb2d3f5aa5fc1adf294157de563eba39bb6e', } }, ... // more image sizes ], ... // more images ], assets: [{ verification: { method: 'keccak256(bytes)', data: '0x98fe032f81c43426fbcfb21c780c879667a08e2a65e8ae38027d4d61cdfe6f55', }, url: 'ifps://QmPJESHbVkPtSaHntNVY5F6JDLW8v69M2d6khXEYGUMn7N', fileType: 'fbx' }], attributes: [ { key: 'Standard type', value: 'LSP', type: "string" }, { key: 'Standard number', value: 4, type: "number" }, { key: '🆙', value: true, type: "boolean" } ] } } ``` --- --- sidebar_label: '🖼️ ERC721 to LSP8' sidebar_position: 3 description: Learn how to migrate your ERC721 token to the LSP8 Identifiable Digital Asset standard on LUKSO. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import Erc721LSP8Table from '@site/src/components/Erc721LSP8Table'; # 🖼️ Migrate ERC721 to LSP8 > 👇🏻 Hands on 📽️ Solidity Workshop Video for the [**Oxford Blockchain Society**](https://x.com/oxfordblocksoc) from March 2024.
[LSP8IdentifiableDigitalAsset](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md) is a new token standard that offers a wider range of functionality compared to [ERC721](https://eips.ethereum.org/EIPS/eip-721), as described in the [standard section](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md). For migrating from ERC721 to LSP8, developers need to be aware of several key differences. :::info Resources See the [contract overview](../../contracts/overview/NFT/index.md#comparisons-with-erc20--erc721) page for the interface differences between ERC721 and LSP8. ::: ## Comparisons ### Solidity code Usually, to create an ERC721 token, we import and inherit the `ERC721` contract from the [@openzeppelin/contracts](https://www.npmjs.com/package/@openzeppelin/contracts) package. ```solidity title="ERC721 Token" // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; contract MyERC721Token is ERC721 { constructor(string memory name, string memory symbol) ERC721(name, symbol) { // Your constructor logic } } ``` To create an LSP8 token, we should instead import `LSP8IdentifiableDigitalAsset` from the [`@lukso/lsp8-contracts`](https://www.npmjs.com/package/@lukso/lsp8-contracts) package, and replace it in the inheritance. To deploy an `LSP8IdentifiableDigitalAsset` we can use the same [`constructor`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md#constructor) parameters, but we also need to specify 2 extra parameters (_explanations of params provided in the code comments below_). - the `lsp4TokenType_`. - the `lsp8TokenIdFormat_`. ```solidity title="LSP8 Token" // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.15; import "@lukso/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol"; // highlight-next-line contract MyLSP8Token is LSP8IdentifiableDigitalAsset { constructor( string memory name, // Name of the token string memory symbol, // Symbol of the token address tokenOwner, // Owner able to add extensions and change metadata // highlight-next-line uint256 lsp4TokenType_, // 1 if NFT, 2 if an advanced collection of multiple NFTs // highlight-next-line uint256 lsp8TokenIdFormat_ // 0 for compatibility with ERC721, check LSP8 specs for other values ) LSP8IdentifiableDigitalAsset(name, symbol, tokenOwner, lsp4TokenType_, lsp8TokenIdFormat_) { // _mint(to, tokenId, force, data) // force: should be set to true to allow EOA to receive tokens // data: only relevant if the `to` is a smart contract supporting LSP1. _mint(tokenOwner, bytes32(uint256(1)), true, ""); } } ``` ### Functions & Behaviors Below are the function signatures of the transfer functions for ERC721 and LSP8, respectively.
**ERC721** ```solidity function transferFrom( address from, address to, uint256 tokenId ) external; ```
**LSP8** ```solidity function transfer( address from, address to, bytes32 tokenId, // highlight-next-line bool force, // highlight-next-line bytes data ) external; ```
There are 4 main differences for LSP8 to note: - **TokenId representation**: In LSP8, the `tokenId` is represented as `bytes32` instead of `uint256` in ERC721. This allows for more flexible token identification schemes. - **Additional `force` parameter**: for the [`mint(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md#mint) and [`transfer(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#transfer) functions. For full compatibility with ERC721 behavior (where the recipient can be any address), set this to `true`. Setting it to `false` will only allow the transfer to smart contract addresses supporting the [**LSP1UniversalReceiver** interfaceId](../../contracts/interface-ids.md). > See the [**LSP8 Standard > `force` mint and transfer**](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#lsp1-token-hooks#force-mint-and-transfer) section for more details. - **Additional `data` field**: for the `mint(...)`, `transfer(...)`, and [`burn(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md#burn) functions. For full compatibility with ERC721 behavior, set this to empty bytes `""`. This data is only relevant when the recipient is a smart contract that supports the LSP1 interfaceId, where the data will be sent and the recipient can act on it (_e.g., reject the transfer, forward the tokens to a vault, etc..._). > See the [**LSP8 Standard > LSP1 Token Hooks**](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#lsp1-token-hooks) section for more details. - **LSP8 metadata is generic**: via a [flexible data key / value store](<(../../standards/erc725.md#erc725y-generic-data-keyvalue-store)>). It can be set and retrieved via [`setData(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdata) / [`setDataBatch(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatabatch) and [`getData(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#getdata) / [`getDataBatch(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#getdatabatch). ### Interact with the Token Contract :::info To check function definitions and explanations of behavior and each parameter, check [API Reference](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md) section. ::: To interact with the LSP8IdentifiableDigitalAsset contract, different functions should be called. This is a table comparing the different function definitions: ### Events :::info To check event definitions and explanations of behavior and each parameter, check [API Reference](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#events) section. ::: Services like dApps and Indexers can use different events from LSP8 to listen to activities. The table below shows the different event definitions that should be used to track activity on an LSP8-IdentifiableDigitalAsset contract. | ERC721 Event | LSP8 Event | | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
);
|
Transfer(
address operator,
address indexed from,
address indexed to,
bytes32 indexed tokenId,
bool force,
bytes data
)
| |
Approval(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
)
|
OperatorAuthorizationChanged(
address indexed operator,
address indexed tokenOwner,
bytes32 indexed tokenId,
bytes operatorNotificationData
);
| |
ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
)
| _No direct equivalent_ | | _No equivalent_ |
OperatorRevoked(
address indexed operator,
address indexed tokenOwner,
bytes32 indexed tokenId,
bool notified,
bytes operatorNotificationData
)
| ## Metadata Management ### Basic Token Information
**ERC721** ```javascript const name = await token.name(); const symbol = await token.symbol(); const tokenURI = await token.tokenURI(tokenId); ```
**How to retrieve?** In ERC721, the name, symbol, and tokenURI of a token can be retrieved by calling their own functions.
**LSP8** ```javascript import { keccak256, toUtf8Bytes } from 'ethers'; const nameKey = keccak256(toUtf8Bytes('LSP4TokenName')); const symbolKey = keccak256(toUtf8Bytes('LSP4TokenSymbol')); const nameValue = await token.getData(nameKey); const symbolValue = await token.getData(symbolKey); const name = ethers.toUtf8String(nameValue); const symbol = ethers.toUtf8String(symbolValue); ```
**How to retrieve?** In LSP8, the token name, symbol and base URI can be retrieved with [`getData(bytes32)`](../../contracts/contracts/ERC725/ERC725.md#getdata). They are stored in the generic metadata key-value store under the data keys [`LSP4TokenName`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokenname), [`LSP4TokenSymbol`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokensymbol) and [`LSP8TokenMetadataBaseURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenmetadatabaseuri). Once you have fetched the raw hex encoded value, you will need to decode it into a human readable string.
You can import the list of data keys related to each individual LSP standard from one of our library. There are 2 options: For dApp developers, you can import the data keys from the `@lukso/lsp-smart-contracts` and use them directly in your scripts via _ethers.js_ or _web3.js_. ```javascript import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; const nameKey = ERC725YDataKeys.LSP4.LSP4TokenName; const symbolKey = ERC725YDataKeys.LSP4.LSP4TokenSymbol; const nameValue = await token.getData(nameKey); // 0x4c5350382050726f66696c65 const symbolValue = await token.getData(symbolKey); // 0x4c5350382050726f66696c65 const name = ethers.toUtf8String(nameValue); // Cool NFT const symbol = ethers.toUtf8String(symbolValue); // COOL ``` You can also obtain the [full schema definition](../../tools/dapps/erc725js/schemas.md) of the LSP4 Metadata from [`@erc725/erc725.js`](../../tools/dapps/erc725js/getting-started.md) library. **This library will also help you to [encode easily](../../tools/dapps/erc725js/methods.md#encodedata) data key value pairs.** ```javascript import { ERC725 } from '@erc725/erc725.js'; import LSP4Schema from '@erc725/erc725.js/schemas/LSP4DigitalAssetMetadata.json'; const nameKey = LSP4Schema.find((schema) => schema.name == 'LSP4TokenName').key; const symbolKey = LSP4Schema.find( (schema) => schema.name == 'LSP4TokenSymbol', ).key; const nameValue = await token.getData(nameKey); // 0x4c5350382050726f66696c65 const symbolValue = await token.getData(symbolKey); // 0x4c5350382050726f66696c65 const [name, symbol] = ERC725.decodeData([ { keyName: 'LSP4TokenName', value: nameValue, }, { keyName: 'LSP4TokenSymbol', value: symbolValue, }, ]); /** [ { name: 'LSP4TokenName', key: '0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1', value: "Cool NFT", }, { name: 'LSP4TokenSymbol', key: '0x2f0a68ab07768e01943a599e73362a0e17a63a72e94dd2e384d2c1d4db932756', value: "COOL", }, ] */ ``` ### Extended Collection Metadata :::success Tutorial 🎥 See the [**Metadata Management**](../digital-assets/metadata-management/edit-token-metadata.md) guide + video for how to create and set the JSON metadata for your LSP8 Token. ::: [LSP8 allows for more flexible and extensible metadata](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#lsp8-collection-vs-tokenid-metadata). You can store a JSON object containing information about: - the whole NFT Collection contract - and for each individual NFT `tokenId`. The [`LSP4Metadata`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata) is a JSON object that can contain many information about the token, including: - 🌐 **official link to websites** (_e.g: project website, social media, community channels, etc..._). - 🖼️ **images** (token icon and backgrounds) to display the token in dApps, explorers, or decentralised exchanges. - 🏷️ **custom attributes** (for each specific NFTs for instance, can be displayed as badges on UIs). ```javascript const metadataKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4Metadata')); const storedMetadata = await token.getData(metadataKey); const retrievedJsonMetadata = JSON.parse(ethers.toUtf8String(storedMetadata)); // JSON Stored: { LSP4Metadata: { description: 'A unique digital artwork collection.', links: [ { title: 'Website', url: 'https://myawesomenft.com' }, { title: 'Twitter', url: 'https://twitter.com/myawesomenft' } ], icon: [ { width: 256, height: 256, url: 'ipfs://QmW5cF4r9yWeY1gUCtt7c6v3ve7Fzdg8CKvTS96NU9Uiwr', verification: { method: 'keccak256(bytes)', data: '0x01299df007997de92a820c6c2ec1cb2d3f5aa5fc1adf294157de563eba39bb6f', } } ], images: [ [ { width: 1024, height: 974, url: 'ipfs://QmW4wM4r9yWeY1gUCtt7c6v3ve7Fzdg8CKvTS96NU9Uiwr', verification: { method: 'keccak256(bytes)', data: '0xa9399df007997de92a820c6c2ec1cb2d3f5aa5fc1adf294157de563eba39bb6e', } }, // ... more image sizes ], // ... more images ], assets: [{ verification: { method: 'keccak256(bytes)', data: '0x98fe032f81c43426fbcfb21c780c879667a08e2a65e8ae38027d4d61cdfe6f55', }, url: 'ipfs://QmPJESHbVkPtSaHntNVY5F6JDLW8v69M2d6khXEYGUMn7N', fileType: 'json' }], attributes: [ { key: 'Artist', value: 'Jane Doe', type: "string" }, { key: 'Edition', value: 1, type: "number" }, { key: 'Original', value: true, type: "boolean" } ] } } ``` ### NFT-specific Metadata LSP8 allows you to set and retrieve metadata for individual tokens using the [`setDataForTokenId(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatafortokenid) and [`getDataForTokenId(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#getdatafortokenid) functions. This is particularly useful for NFTs where each token might have unique properties. ```javascript // Setting token-specific metadata const tokenId = '0x1234...'; // your token ID in bytes32 format const metadataKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4Metadata')); const metadataValue = ethers.toUtf8Bytes(JSON.stringify({ // Your token-specific metadata here })); await token.setDataForTokenId(tokenId, metadataKey, metadataValue); // Retrieving token-specific metadata const storedMetadata = await token.getDataForTokenId(tokenId, metadataKey); const retrievedJsonMetadata = JSON.parse(ethers.toUtf8String(storedMetadata)); // Example of token-specific metadata { LSP4Metadata: { description: 'Unique NFT #1234', image: 'ipfs://QmYourImageCID', attributes: [ { trait_type: 'Rarity', value: 'Legendary' }, { trait_type: 'Power Level', value: 9000 } ] } } ``` This feature allows for much more flexible and dynamic NFTs compared to the static `tokenURI` approach in ERC721. --- --- sidebar_label: '🔧 Integration Guide' sidebar_position: 1 description: What to consider when building on LUKSO with LSPs (LUKSO Standard Proposals)? --- # Migrate to LUKSO :::info This page gives an overview of the differences between building on LUKSO vs other EVM chains. For more information on specific topics, see the following pages: - [Introduction to the LSPs](/standards/introduction.md). - [Concepts & Glossary](../concepts.md) if you are not understanding certain terms. - [Features & Benefits of Universal Profiles](../benefits-lukso-standards.md#universal-profiles-vs-smart-wallets) compared to traditional wallets. - [Features & Benefits of LSP7/8 Token standards over](../benefits-lukso-standards.md#features-of-lsp-token-standards-over-erc20-and-erc721) compared to traditional wallets. ::: ## Migrating from other EVM Chain LUKSO is EVM-compatible. Any traditional web3 wallet (_e.g: Metamask_) can interact with LUKSO dApps. 1. Simply [add the LUKSO network in your wallet](/networks/testnet/parameters.md) and switch to the LUKSO chain. 2. Any Ethereum smart contract can be redeployed on LUKSO by connecting to a [LUKSO RPC endpoint](/networks/mainnet/parameters). 3. Allow Universal Profiles to log-in to your dApp is easy and not different than other web3 wallet. Check our dedicated guide [**Connect 🆙**](/learn/universal-profile/connect-profile/connect-up.md)! You can start holding assets (LYX, tokens, and NFTs), transfer them, and deploy and interact with smart contracts. ## From ERCs → to LSPs :::info Why using the LSP standards? Wondering what are the benefits and features of the LSPs and Universal Profiles compared to ERCs and traditional web3 wallets? Learn more under our dedicated page [**Benefits of LUKSO Standards**](../benefits-lukso-standards.md) to see how your project can leverage the LUKSO standard and tech! ::: :::success Useful guides Interested to migrate your token or NFT collection? See our hands-on developer guides: - [Migrate from ERC20 to LSP7](./migrate-erc20-to-lsp7.md) - [Migrate from ERC721 to LSP8](./migrate-erc721-to-lsp8.md) ::: :::note Solidity functions For more details on the different functions and Solidity interface, see the following pages and sections: - [**Digital Asset (Token) > Comparison with ERC20**](/contracts/overview/Token/index.md#comparisons-with-erc20). - [**Identifiable Digital Asset (NFT) > Comparison with ERC721**](/contracts/overview/NFT/index.md#comparisons-with-erc721). ::: Developers are encouraged to leverage the LSPs (**L**UKSO **S**tandards **P**roposals) to develop smart contracts, protocols and applications on LUKSO. The LSPs offer flexible functionalities that can: - enable more complex and various features not available with ERCs. - be tailored to suit different use cases. - bring a better experience to end dApp users. Some codebases may need adjustments to convert ERC interactions to LSP interactions. We provide guides above to help with such refactoring. --- --- sidebar_label: '🔌 Connect to a Mini-App' description: 'How to connect your Mini-App using the UP Provider' sidebar_position: 1 --- # Connect to a Mini-App ## What are Mini-Apps? Mini-Apps are dApps that run in an iframe of a parent page that hosts them. You can see [examples of Mini-Apps in action on universaleverything.io](https://universaleverything.io/0x7b258dD350227CFc9Da1EDD7f4D978f7Df20fD40). ## The Challenge with Mini-Apps Traditionally, users would need to connect to each Mini-App individually through: - Connect buttons - Web3 modals - WalletConnect processes This makes the user experience cumbersome. ## Introducing the UP Provider The [up-provider](/tools/dapps/up-provider/getting-started) solves this by giving Mini-Apps a way for the user visiting the parent page, to connect to the Mini-App directly with one-click. Additionally, **the Mini-App has access to `context addresses`**, which in the case of [universaleverything.io](https://universaleverything.io) is the Universal Profile under which the Mini-App is hosted in the Grid. > The up-provider is a [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) compatible provider, meaning it will work with all major web3 libraries. For examples using viem, web3.js or ethers, [see the readme of the up-provider](https://github.com/lukso-network/tools-up-provider/blob/main/README.md#provider-for-mini-apps). ## Installation ```bash npm install @lukso/up-provider ``` ## Example implementation using React Here's a step-by-step guide to implement UP Provider connection in your React application: 1. First, import the necessary dependencies: ```typescript import { createClientUPProvider } from '@lukso/up-provider'; ``` 2. Create a provider instance outside your component: ```typescript const provider = createClientUPProvider(); ``` 3. To implement the UP Provider connection in your component, you can use the following code: ```typescript // Track connected accounts const [accounts, setAccounts] = useState>([]); const [contextAccounts, setContextAccounts] = useState>( [], ); const [profileConnected, setProfileConnected] = useState(false); // Helper to check connection status const updateConnected = useCallback( (_accounts: Array<`0x${string}`>, _contextAccounts: Array<`0x${string}`>) => { setProfileConnected(_accounts.length > 0 && _contextAccounts.length > 0); }, [], ); useEffect(() => { async function init() { try { const _accounts = provider.accounts as Array<`0x${string}`>; setAccounts(_accounts); const _contextAccounts = provider.contextAccounts; updateConnected(_accounts, _contextAccounts); } catch (error) { console.error('Failed to initialize provider:', error); } } // Handle account changes const accountsChanged = (_accounts: Array<`0x${string}`>) => { setAccounts(_accounts); updateConnected(_accounts, contextAccounts); }; const contextAccountsChanged = (_accounts: Array<`0x${string}`>) => { setContextAccounts(_accounts); updateConnected(accounts, _accounts); }; init(); // Set up event listeners provider.on('accountsChanged', accountsChanged); provider.on('contextAccountsChanged', contextAccountsChanged); // Cleanup listeners return () => { provider.removeListener('accountsChanged', accountsChanged); provider.removeListener('contextAccountsChanged', contextAccountsChanged); }; }, [accounts[0], contextAccounts[0], updateConnected]); ``` ## Understanding the Implementation ### Provider Creation The `createClientUPProvider()` function creates a new instance of the UP Provider. This should be done outside your component to maintain a single instance. ### State variables This implementation gives you access to: - `accounts`: Array of connected accounts, in our case the universal profile of the visitor - `contextAccounts`: Array of context accounts, which in our case is the universal profile on [universaleverything.io](https://universaleverything.io) where the mini-app is hosted under. - `profileConnected`: Boolean indicating if a user is connected to the mini-app ### Event Handling The provider emits two important events: - `accountsChanged`: Triggered when the connected accounts change, this is universal profile of the visitor - `contextAccountsChanged`: Triggered when the context accounts change, this is the universal profile on [universaleverything.io](https://universaleverything.io) where the mini-app is hosted under. ### Cleanup Clean up the event listeners when unmounting to prevent memory leaks. --- --- sidebar_label: '🧩 Setting Your Grid' sidebar_position: 0 description: Learn how to set up LSP28 Grid on your Universal Profile — encode Grid JSON, build VerifiableURI, and write on-chain with erc725.js. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Setting Your Grid

A customizable Grid layout on a Universal Profile, hosting mini-apps, social embeds, and content.

The **Grid** ([LSP28](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-28-TheGrid.md)) is a standard that lets Universal Profiles display **customizable, modular layouts** made of mini-apps, social media embeds, images, text, and other interactive content. Think of it as a personal dashboard you can attach to any Universal Profile. This guide walks you through: 1. Understanding the JSON structure of a Grid and all its available element types 2. How to encode the Grid as a [VerifiableURI](/standards/metadata/lsp2-json-schema.md#verifiableuri) 3. Encode the grid data either on-chain as base64 or off-chain on IPFS 4. Set it on your Universal Profile via `setData(bytes32,bytes)` :::info What are Mini-Apps? Mini-Apps are dApps that run inside an ` ## Introduction :::info Read the standard docs about including [LSP17-ContractExtension in the Universal Profile](../../../standards/accounts/lsp0-erc725account.md#lsp17---contract-extension). ::: A Universal Profile contains non-biased features, including generic execution capabilities, the ability to attach generic information, and the ability to be notified and react to various actions. However, post-deployment, a Universal Profile, like any smart contract, becomes immutable. This immutability restricts the ability to add new functionalities into the code of the contract. To overcome this limitation, the concept of **extensions** is introduced. Extensions are essentially external contracts that act as supplementary modules to the Universal Profile. They provide a dynamic way to enhance and extend the profile's capabilities. When a call is made to the Universal Profile for a function not natively supported, the contract checks if this function exists as an extension. If found, the call is seamlessly redirected to the appropriate external contract (extension), thereby effectively expanding the functionality of the Universal Profile without altering its core, immutable code. This approach enables greater flexibility and adaptability, ensuring the Universal Profile can evolve to meet diverse requirements. ## Extending Functionalities ### Setup Install the dependencies ```bash npm install ethers @lukso/lsp-smart-contracts ``` ### Step 1: Create the Extension Contract Next, we will create a Solidity contract named `TipMe` which will inherit from [`LSP17Extension`](../../../contracts/contracts/LSP17ContractExtension/LSP17Extension.md) and have a function `tipMe(..)` that emits an event `Tipped`. ```solidity title="TipMe.sol" // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@lukso/lsp-smart-contracts/contracts/LSP17ContractExtension/LSP17Extension.sol"; // Contract used as an extension to have the `tipMe()` function contract TipMe is LSP17Extension { event Tipped(address tipper); function tipMe() public payable { // _extendableMsgSender() is a method inherited from LSP17Extension. // It extracts the address who initially called the Universal Profile with the `tipMe(..)` selector // `msg.sender` in this case will be the Universal Profile address/ emit Tipped(_extendableMsgSender()); } // You can access the value sent to the UniversalProfile with // _extendableMsgValue() if the value is being preserved in the UniversalProfile // or with msg.value in case the UniversalProfile is forwarding the value to the extension } ``` The contract can be compiled with any blockchain development environment like Hardhat or Foundry to extract the ABI and bytecode from the `artifacts` or `out` folder. Create `TipMe.json` in the same directory of the main file.
The ABI and the bytecode of the contract: ```json title="TipMe.json" { "abi": [ { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "address", "name": "tipper", "type": "address" } ], "name": "Tipped", "type": "event" }, { "inputs": [], "name": "VERSION", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } ], "name": "supportsInterface", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "tipMe", "outputs": [], "stateMutability": "payable", "type": "function" } ], "bytecode": "0x608060405234801561001057600080fd5b50610359806100206000396000f3fe6080604052600436106100345760003560e01c806301ffc9a714610039578063c753619d1461006e578063ffa1ad7414610078575b600080fd5b34801561004557600080fd5b506100596100543660046101f3565b6100ce565b60405190151581526020015b60405180910390f35b610076610167565b005b34801561008457600080fd5b506100c16040518060400160405280600681526020017f302e31342e30000000000000000000000000000000000000000000000000000081525081565b604051610065919061023c565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fcee78b4000000000000000000000000000000000000000000000000000000000148061016157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b7f6e6dc9fb40a5073d46db20aeeb93e8a1b65bcd97624d5be4bcb7105fd7256b586101906101ba565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b600080366101c960348261028a565b906101d560203661028a565b926101e2939291906102c4565b6101eb916102ee565b60601c905090565b60006020828403121561020557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461023557600080fd5b9392505050565b600060208083528351808285015260005b818110156102695785810183015185820160400152820161024d565b506000604082860101526040601f19601f8301168501019250505092915050565b81810381811115610161577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080858511156102d457600080fd5b838611156102e157600080fd5b5050820193919092039150565b6bffffffffffffffffffffffff19813581811691601485101561031b5780818660140360031b1b83161692505b50509291505056fea26469706673582212207cb079856f6eb296cf0fe4131f43256d95ad69524df0a266ae3952295688c20964736f6c63430008110033" } ```
### Step 2: Instantiate the Universal Profile #### Generate a Signer First, we need to generate a signer. This signer will be used to interact with the blockchain. We'll use the private key of the Universal Profile main controller and an RPC URL. ```js import { ethers } from 'ethers'; // RPC URL (e.g: LUKSO testnet) const RPC_URL = 'https://rpc.testnet.lukso.network'; // Replace with your private key const privateKey = 'your-private-key'; const provider = new ethers.JsonRpcProvider(RPC_URL); const signer = new ethers.Wallet(privateKey, provider); ``` #### Instantiate the Universal Profile Contract Now, we'll create an instance of the Universal Profile contract. ```js import { abi as UniversalProfileABI } from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // Replace with the address of your Universal Profile const universalProfileAddress = 'your-universal-profile-address'; const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfileABI, signer, ); ``` ### Step 3: Deploy the Extension Contract We will use the abi and bytecode to deploy the extension contract ```js // We get the ABI and bytecode from Step1 after compiling the extension contract import { abi as TipMeABI } from './TipMe.json'; import { bytecode as TipMeBytecode } from './TipMe.json'; const TipMeFactory = new ethers.ContractFactory( TipMeABI, TipMeBytecode, signer, ); const tipMeContract = await TipMeFactory.deploy(); await tipMeContract.deployTransaction.wait(); const tipMeExtensionAddress = tipMeContract.address; console.log('Contract deployed at:', tipMeExtensionAddress); ``` ### Step 4: Encode Function Selector and Store in Universal Profile :::info Requirements The address calling the `setData(..)` function needs to have `ADDEXTENSIONS` and `CHANGEEXTENSIONS` permission otherwise the call will fail. Check the [keyManager guides](../key-manager/get-controller-permissions.md) to learn more about permissions. ::: We need to encode the function selector of `tipMe(..)` and store it in the Universal Profile with a specific data key according to the [LSP17-ContractExtension](../../../standards/accounts/lsp17-contract-extension.md) standard. #### Prepare data key and data value ```js import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; // We get `TipMeABI` from the last step // import {abi as TipMeABI} from './TipMe.json'; const tipMeInterface = new ethers.Interface(TipMeABI); const tipMeFunctionSelector = tipMeInterface.getSighash('tipMe()'); // Define the DataKey for the extension // according to the LSP17-ContractExtension standard // erc725.js can be used to encode the key const extensionDataKey = ERC725YDataKeys.LSP17.LSP17ExtensionPrefix + tipMeFunctionSelector.substr(2) + '0'.repeat(32); ``` #### Controlling Value Forwarding to Extensions When calling an extension through a UniversalProfile, **in case value was sent along the call**, there's an option to either retain the sent value within the UniversalProfile contract or forward it to the extension contract. This choice depends on the intended purpose of the extension. In scenarios where multiple users collectively use a single extension, keeping the value within the UniversalProfile might be preferable. Alternatively, forwarding the value might be necessary if the extension requires funds to perform specific actions. This behavior is controlled by appending a boolean value to the address stored under the extension's data key for a particular function selector. For example, to forward the value along with the call, the address would be stored with a "0x01" boolean appended: ```js const tx = await universalProfile.setData( extensionDataKey, tipMeContract.address + '01', ); await tx.wait(); ``` > **Note**: Ensure that the function called in the extension is marked as `payable`. Conversely, to keep the value sent within the UniversalProfile, store the address as is, without appending any boolean: ```js const tx = await universalProfile.setData( extensionDataKey, tipMeContract.address, ); await tx.wait(); ``` ### Step 5: Test the Function Call Finally, test calling the tipMe function on the Universal Profile. ```js // Attaching the ABI of TipMe to the Universal Profile so we can call tipMe() function directly on it const universalProfileWithExtension = new ethers.Contract( universalProfileAddress, TipMeABI, signer, ); // Calling the tipMe() function on the Universal Profile // Make sure the address associated with the private key have enough native tokens to send const tipMeTx = await universalProfileWithExtension.tipMe({ value: ethers.parseEther('0.1'), }); await tipMeTx.wait(); ``` The event should be emitted and the value should be seen on the Universal Profile or the extension contract depending whether the value was retained or forwarded. ### Final Code (Function) Below is the complete code snippet of this guide, with all the steps compiled together. ```js title="extendingFunctionalities.js" import { ethers } from 'ethers'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; import { abi as UniversalProfileABI } from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // We get the ABI and bytecode from Step1 after compiling the extension contract import { abi as TipMeABI } from './TipMe.json'; import { bytecode as TipMeBytecode } from './TipMe.json'; async function main() { // RPC URL (e.g., LUKSO testnet) const RPC_URL = 'https://rpc.testnet.lukso.network'; // Make sure the address associated with this private key has the 'ADDEXTENSIONS' and 'CHANGEEXTENSIONS' permissions // Replace with your private key const privateKey = 'your-private-key'; const provider = new ethers.JsonRpcProvider(RPC_URL); const signer = new ethers.Wallet(privateKey, provider); const universalProfileAddress = 'your-universal-profile-address'; const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfileABI, signer, ); const TipMeFactory = new ethers.ContractFactory( TipMeABI, TipMeBytecode, signer, ); const tipMeContract = await TipMeFactory.deploy(); await tipMeContract.deployTransaction.wait(); const tipMeInterface = new ethers.Interface(TipMeABI); const tipMeFunctionSelector = tipMeInterface.getSighash('tipMe()'); // Define the DataKey for the extension // according to the LSP17-ContractExtension standard // erc725.js can be used to encode the key const extensionDataKey = ERC725YDataKeys.LSP17.LSP17ExtensionPrefix + tipMeFunctionSelector.substr(2) + '0'.repeat(32); const tx = await universalProfile.setData( extensionDataKey, tipMeContract.address, ); await tx.wait(); // Attaching the ABI of TipMe to the Universal Profile so we can call tipMe() function directly on it const universalProfileWithExtension = new ethers.Contract( universalProfileAddress, TipMeABI, signer, ); // Calling the tipMe() function on the Universal Profile const tipMeTx = await universalProfileWithExtension.tipMe({ value: ethers.parseEther('0.1'), }); await tipMeTx.wait(); } main(); ``` ## Extending InterfaceIds Extending `interfaceIds` is crucial for Universal Profiles, as many protocols check for support of specific `interfaceIds` before executing calls to certain functions. Extending interfaceIds typically follows a similar approach to extending functions, with the main distinction being the existence of the `supportsInterface` function. ### Step 1: Create a Contract Supporting a Specific InterfaceId First, you need to create a Solidity contract that implements the [`supportsInterface(..)`](../../../contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#supportsinterface) function. This function should return true for at least one specific interfaceId, in this case, a dummy interfaceId like `0xaabbccdd`. ```solidity title="SupportsInterface.sol" // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract SupportsInterface { bytes4 constant DUMMY_INTERFACE_ID = 0xaabbccdd; function supportsInterface(bytes4 interfaceId) external pure returns (bool) { return interfaceId == DUMMY_INTERFACE_ID; } } ``` The contract can be compiled with any blockchain development environment like Hardhat or Foundry to extract the ABI and bytecode from the `artifacts` or `out` folder. Create `SupportsInterface.json` in the same directory of the main file.
The ABI and the bytecode of the contract: ```json title="SupportsInterface.json" { "abi": [ { "inputs": [ { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } ], "name": "supportsInterface", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "pure", "type": "function" } ], "bytecode": "0x608060405234801561001057600080fd5b50610110806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806301ffc9a714602d575b600080fd5b607f60383660046093565b7fffffffff00000000000000000000000000000000000000000000000000000000167faabbccdd000000000000000000000000000000000000000000000000000000001490565b604051901515815260200160405180910390f35b60006020828403121560a457600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811460d357600080fd5b939250505056fea2646970667358221220f5bcd4c144943e9ab139d02d2609c021af3361f19e8d47a551246e3678d74e9264736f6c63430008110033" } ```
### Step 2: Deploy the Extension Contract We will use the abi and bytecode to deploy the extension contract ```js // We get the ABI and bytecode from Step1 after compiling the extension contract import { abi as SupportsInterfaceABI } from './SupportsInterface.json'; import { bytecode as SupportsInterfaceBytecode } from './SupportsInterface.json'; const supportsInterfaceFactory = new ethers.ContractFactory( SupportsInterfaceABI, SupportsInterfaceBytecode, signer, ); const supportsInterfaceContract = await supportsInterfaceFactory.deploy(); await supportsInterfaceContract.deployTransaction.wait(); const supportsInterfaceExtensionAddress = supportsInterfaceContract.address; console.log('Contract deployed at:', tipMeExtensionAddress); ``` ### Step 3: Encode Function Selector and Store in Universal Profile :::info Requirements The address calling the `setData(..)` function needs to have `ADDEXTENSIONS` and `CHANGEEXTENSIONS` permissions, otherwise, the call will fail. Check the [keyManager guides](../../universal-profile/key-manager/get-controller-permissions.md) to learn more about permissions. ::: We need to encode the function selector of `supportsInterface(..)` and store it in the Universal Profile with a specific data key according to the [LSP17-ContractExtension](../../../standards/accounts/lsp17-contract-extension.md) standard. ```js import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; const supportsInterfaceInterface = new ethers.Interface(SupportsInterfaceABI); const supportsInterfaceFunctionSelector = supportsInterfaceInterface.getSighash( 'supportsInterface(bytes4)', ); // Define the DataKey for the extension const extensionDataKey = ERC725YDataKeys.LSP17.LSP17ExtensionPrefix + supportsInterfaceFunctionSelector.substr(2) + '0'.repeat(32); const tx = await universalProfile.setData( extensionDataKey, supportsInterfaceContract.address, ); await tx.wait(); ``` ### Step 4: Call supportsInterface with the InterfaceId Finally, you can verify that the extension was successful by calling the `supportsInterface(..)` function with the dummy interfaceId `0xaabbccdd`. The function should return `true`, indicating that the Universal Profile now supports this interfaceId through the extension. ```js const result = await universalProfile.callStatic.supportsInterface('0xaabbccdd'); console.log('Supports Dummy InterfaceId:', result); ``` This process effectively extends the capabilities of your Universal Profile to acknowledge support for additional interfaceIds, enhancing its interoperability within the broader ecosystem. ### Final Code (InterfaceId) Below is the complete code snippet of this guide, with all the steps compiled together. ```js title="extendingInterfaceIds.js" import { ethers } from 'ethers'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; import { abi as UniversalProfileABI } from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // We get the ABI and bytecode from Step1 after compiling the extension contract import { abi as SupportsInterfaceABI } from './SupportsInterface.json'; import { bytecode as SupportsInterfaceBytecode } from './SupportsInterface.json'; async function main() { // RPC URL (e.g., LUKSO testnet) const RPC_URL = 'https://rpc.testnet.lukso.network'; // Make sure the address associated with this private key has the 'ADDEXTENSIONS' and 'CHANGEEXTENSIONS' permissions // Replace with your private key const privateKey = 'your-private-key'; const provider = new ethers.JsonRpcProvider(RPC_URL); const signer = new ethers.Wallet(privateKey, provider); const universalProfileAddress = 'your-universal-profile-address'; const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfileABI, signer, ); const supportsInterfaceFactory = new ethers.ContractFactory( SupportsInterfaceABI, SupportsInterfaceBytecode, signer, ); const supportsInterfaceContract = await supportsInterfaceFactory.deploy(); await supportsInterfaceContract.deployTransaction.wait(); const supportsInterfaceExtensionAddress = supportsInterfaceContract.address; const supportsInterfaceInterface = new ethers.Interface(SupportsInterfaceABI); const supportsInterfaceFunctionSelector = supportsInterfaceInterface.getSighash('supportsInterface(bytes4)'); // Define the DataKey for the extension const extensionDataKey = ERC725YDataKeys.LSP17.LSP17ExtensionPrefix + supportsInterfaceFunctionSelector.substr(2) + '0'.repeat(32); const tx = await universalProfile.setData( extensionDataKey, supportsInterfaceContract.address, ); await tx.wait(); const result = await universalProfile.callStatic.supportsInterface('0xaabbccdd'); console.log('Supports Dummy InterfaceId:', result); } main(); ``` --- --- sidebar_label: '📐 Upgrade Key Manager' sidebar_position: 4 description: This advanced tutorial shows how you can upgrade the `owner()` of a Universal Profile. For instance upgrading the Key Manager with a better one. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Upgrade Key Manager :::danger Warning This guide is an **advanced guide**. It is intended for developers who are looking to upgrade the Key Manager of their Universal Profile to a new one. For instance, if a new Key Manager with enhanced features. For normal user using the UP Browser Extension, their UP is currently setup with a basic Key Manager already deployed for them on profile creation. **It is therefore not recommended to follow this guide as this could affect the functionality of their UP, making it not possible to interact with it via the Browser Extension**. ::: This advanced guide shows how to upgrade the [`LSP6KeyManager`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md) of your UP, which is the [`owner()`](/contracts/contracts/UniversalProfile/UniversalProfile.md#owner) of the [`UniversalProfile`](/contracts/contracts/UniversalProfile/UniversalProfile.md). We will: 1. Deploy a new `LSP6KeyManager` contract on LUKSO Testnet. 2. Upgrade by transferring ownership of the UniversalProfile to the newly deployed `LSP6KeyManager`. 3. Confirm the upgrade by accepting ownership via the new Key Manager. ## Setup Make sure you have the following dependencies installed before beginning this tutorial: - Either [`web3.js`](https://github.com/web3/web3.js) or [`ethers.js`](https://github.com/ethers-io/ethers.js/) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) ```shell title="Install the dependencies" npm install ethers @lukso/lsp-smart-contracts ``` ```shell title="Install the dependencies" npm install web3 @lukso/lsp-smart-contracts ``` ## Step 1 - Set up constants and imports Create a JavaScript file and add the following imports on the top of the file: - `privateKey`: private key of a controller address, **MUST** have [**CHANGEOWNER**](/standards/access-control/lsp6-key-manager.md#permissions) permission. - `universalProfileAddress`: address of your Universal Profile. ```js title="Imports & Constants" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP6KeyManager from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; import { ethers } from 'ethers'; const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const privateKey = '0x...'; const universalProfileAddress = '0x...'; ``` ```js title="Imports & Constants" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP6KeyManager from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; import Web3 from 'web3'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const privateKey = '0x...'; const universalProfileAddress = '0x...'; ``` ## Step 2 - Initialize the controller > **Requirement:** the EOA controller that we will use MUST have the [**`CHANGEOWNER`**](/standards/access-control/lsp6-key-manager.md#permissions) permission on the UP ```js title="Initialise EOA" const account = new ethers.Wallet(privateKey).connect(provider); ``` ```js title="Initialise EOA" const account = web3.eth.accounts.wallet.add(privateKey); ``` ## Step 3 - Initialize UP contract In order to transfer ownership of your Universal Profile, you need to initialize the UP's contract. ```js title="Create an instance of the old Key Manager" const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); ``` ```js title="Create an instance of the old Key Manager" const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); ``` ## Step 4 - Deploy the new Key Manager Deploy a new LSP6 Key Manager with the latest updates. ```js title="Deploy a new Key Manager" const newKeyManager = await new ethers.ContractFactory( LSP6KeyManager.abi, LSP6KeyManager.bytecode, ) .connect(account) .deploy(universalProfileAddress); ``` ```js title="Deploy a new Key Manager" const newKeyManager = new web3.eth.Contract(LSP6KeyManager.abi); await newKeyManager .deploy({ data: LSP6KeyManager.bytecode, arguments: [universalProfileAddress], }) .send({ from: account.address, gas: 3_000_000, gasPrice: '1000000000', }); ``` ## Step 5 - Upgrade your Key Manager ### Step 5.1 - Transfer Ownership to your new Key Manager Create a calldata for the [`transferOwnership(address)`](/contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md#transferownership) function and shift the ownership of your Universal Profile from your current LSP6 Key Manager. ```js title="Transfer ownership of the Universal Profile from the old Key Manager to the new one" await universalProfile .connect(account) .transferOwnership(newKeyManager.address); ``` ```js title="Transfer ownership of the Universal Profile from the old Key Manager to the new one" await universalProfile.methods.transferOwnership(newKeyManager.address).send({ from: account.address, gas: 1_000_000, gasPrice: '1000000000', }); ``` ### Step 5.2 - Accept Ownership from your new Key Manager Create a calldata for the [`acceptOwnership()`](/contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md#acceptownership) function and take the ownership of your Universal Profile from your new LSP6 Key Manager. ```js title="Accept ownership of the Universal Profile via the new Key Manager" const acceptOwnershipCalldata = new ethers.Interface( UniversalProfile.abi, ).encodeFunctionData('acceptOwnership()'); await newKeyManager.connect(account).execute(acceptOwnershipCalldata); ``` ```js title="Accept ownership of the Universal Profile via the new Key Manager" const acceptOwnershipCalldata = new web3.eth.Contract( UniversalProfile.abi, ).methods .acceptOwnership() .encodeABI(); await newKeyManager.methods.execute(acceptOwnershipCalldata).send({ from: account.address, gas: 1_000_000, gasPrice: '1000000000', }); ``` :::success 🥳 The upgrade has been completed successfully. ::: ## Final code ```js title="upgrade-lsp6.js" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP6KeyManager from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; import { ethers } from 'ethers'; const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const privateKey = '0x...'; const universalProfileAddress = '0x...'; const upgradeLSP6 = async () => { // Initialize the controller account const account = new ethers.Wallet(privateKey).connect(provider); // Initialize your current UP const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); // Deploy a new LSP6 Key Manager const newKeyManager = await new ethers.ContractFactory( LSP6KeyManager.abi, LSP6KeyManager.bytecode, ) .connect(account) .deploy(universalProfileAddress); // Transfer the ownership of your Universal Profile from the current LSP6 Key Manager to a new LSP6 Key Manager await universalProfile .connect(account) .transferOwnership(newKeyManager.address); // Accept the ownership of your Universal Profile from the new LSP6 Key Manager const acceptOwnershipCalldata = new ethers.Interface( UniversalProfile.abi, ).encodeFunctionData('acceptOwnership()'); await newKeyManager.connect(account).execute(acceptOwnershipCalldata); }; await upgradeLSP6(); ``` ```javascript title="upgrade-lsp6.js" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP6KeyManager from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; import Web3 from 'web3'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const privateKey = '0x...'; const universalProfileAddress = '0x...'; const upgradeLSP6 = async () => { // Initialize the controller account const account = web3.eth.accounts.wallet.add(privateKey); // Initialize your current UP const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); // Deploy a new LSP6 Key Manager const newKeyManager = new web3.eth.Contract(LSP6KeyManager.abi); await newKeyManager .deploy({ data: LSP6KeyManager.bytecode, arguments: [universalProfileAddress], }) .send({ from: account.address, gas: 3_000_000, gasPrice: '1000000000', }); // Transfer the ownership of your Universal Profile from the current LSP6 Key Manager to a new LSP6 Key Manager await universalProfile.methods.transferOwnership(newKeyManager.address).send({ from: account.address, gas: 1_000_000, gasPrice: '1000000000', }); // Accept the ownership of your Universal Profile from the new LSP6 Key Manager const acceptOwnershipCalldata = new web3.eth.Contract( UniversalProfile.abi, ).methods .acceptOwnership() .encodeABI(); await newKeyManager.methods.execute(acceptOwnershipCalldata).send({ from: account.address, gas: 1_000_000, gasPrice: '1000000000', }); }; await upgradeLSP6(); ``` ## Test the new LSP6 Key Manager We can now check the owner of the Universal Profile. If everything went through, the owner should be the address of the new LSP6 Key Manager. Create the following file with the name `test-new-lsp6.js` and run: ```shell node test-new-lsp6.js ``` ```javascript title="test-new-lsp6.js" import LSP0ERC725YAccount from '@lukso/lsp-smart-contracts/artifacts/LSP0ERC725YAccount.json'; import LSP6KeyManager from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; import Web3 from 'web3'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const universalProfileAddress = '0x...'; const testLSP6 = async () => { const universalProfile = new web3.eth.Contract( LSP0ERC725YAccount.abi, universalProfileAddress, ); const universalProfileOwner = await universalProfile.methods.owner().call(); console.log( `The new owner of the Universal Profile is: ${universalProfileOwner}`, ); console.log(`The old LSP6 Key Manager is at address: ${keyManagerAdderss}`); const keyManager = new web3.eth.Contract( LSP6KeyManager.abi, universalProfileOwner, ); const keyManagerTarget = await keyManager.methods.target().call(); console.log( `The address of the Universal Profile is: ${universalProfile._address}`, ); console.log(`The target of the new LSP6 Key Manager: ${keyManagerTarget}`); }; await testLSP6(); ``` --- --- sidebar_label: 'Connect UP with Providers' sidebar_position: 1 description: Learn how to connect your Universal Profile to a dApp (decentralized application) on LUKSO. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import LayersIcon from '@mui/icons-material/Layers'; # Connect a Universal Profile [Universal Profiles](../../../standards/accounts/introduction.md) can connect to dApps on LUKSO using one of the two UP Apps available: - [🧩 UP Browser Extension](/install-up-browser-extension/#up-browser-extension) - [📱 UP Mobile App] Connecting your Universal Profile will trigger one the following connection screen.
:::success Request Handling The [Universal Profile Extension](/install-up-browser-extension) returns the address of the connected [Universal Profile](../../../standards/accounts/introduction.md). Making transactions is the same as with any wallet, you just use the profile address as a `from` in your transactions. ::: ## Connection Methods There are multiple ways to connect a dApp to Universal Profiles, from high-level libraries to low-level provider access. Choose the method that best fits your application's needs: | Option | Difficulty | Recommended for | | --------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [**Third-Party Libraries**](#third-party-libraries) | **Easy** 🌶️
Plug in existing connectors and focus on UX. | Most dApps. Provides pre-built components, ready-made modals, with multi-wallet support out of the box and connection logic handled automatically.
**Recommended for quick and easy integration while keeping a seamless user experience.** | | [**Provider Injection**](#provider-injection) | **Medium** 🌶️🌶️
Require to manage the `window.lukso` object. | Lightweight builds needing minimal dependencies and full control over wallet connection logic.
**Recommended for full control over the connection logic (_e.g: only allow UPs to connect_) and to build custom connection modals.** | | [**Provider Discovery**](#provider-discovery) | **Complex** 🌶️🌶️🌶️
Connect multiple wallet extensions simultaneously. | Advanced apps where users run several extensions (e.g., MetaMask + Universal Profile) simultaneously using EIP-6963.
**Recommended for handling multiple connected wallets.** | :::info Currently, only the **third-party libraries** method can be used to connect the [📱 UP Mobile App] to a dApp. ::: ### Third-Party Libraries You can connect to Universal Profile using the following third-party libraries. These libraries simplify dApp development by abstracting complex wallet connection logic: - [**RainbowKit**](https://rainbowkit.com/docs/) (since [`v2.2.9`](https://github.com/rainbow-me/rainbowkit/releases/tag/%40rainbow-me%2Frainbowkit%402.2.9)) - [**Reown AppKit**](https://docs.reown.com/appkit/overview) (formerly WalletConnect)
See flow diagram on how third party libraries handle the connection flow with EIP-6963 ```mermaid sequenceDiagram participant User participant Your App participant Third-Party Libraries participant Wagmi participant UP Apps User->>Your App: Click Connect Your App->>Third-Party Libraries: Open Modal Third-Party Libraries->>Wagmi: Request Connection Wagmi->>UP Apps: Initiate Connection UP Apps->>Wagmi: Approve & Return UP Address Wagmi->>Third-Party Libraries: Connection Established Third-Party Libraries->>Your App: Return UP Address ```
Choose your preferred library and follow the configuration steps below. Both options are built on top of **Wagmi**! **Step 1: Install Dependencies** ```sh npm install @rainbow-me/rainbowkit wagmi @tanstack/react-query ``` **Step 2: Configure Wagmi with LUKSO and RainbowKit Connectors** Set up Wagmi configuration with LUKSO network and RainbowKit's Universal Profile wallet connector: :::info Using the connectors `universalProfilesWallet` connector is required to integrate your app with the Universal Profiles Mobile App. ::: ```js import { WagmiProvider, createConfig, http } from 'wagmi'; import { lukso } from 'wagmi/chains'; import { connectorsForWallets } from '@rainbow-me/rainbowkit'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; // highlight-next-line import { universalProfilesWallet } from '@rainbow-me/rainbowkit/wallets'; // Wagmi uses QueryClient to manage cache, background updates, and request deduplication. // This is required to provide higher up in your component tree. const queryClient = new QueryClient(); const config = createConfig({ chains: [lukso], transports: { [lukso.id]: http(), }, // highlight-start connectors: connectorsForWallets( [ { groupName: 'Login with Universal Profile', // highlight-next-line wallets: [universalProfilesWallet], }, ], { appName: 'LUKSO dApp', projectId: 'YOUR_PROJECT_ID', // Get your project ID from WalletConnect Cloud }, ), // highlight-end }); ``` **Step 3: Wrap Your App with Providers** Import RainbowKit styles and wrap your application with the required providers in the correct order: ```jsx import { RainbowKitProvider } from '@rainbow-me/rainbowkit'; import '@rainbow-me/rainbowkit/styles.css'; function App() { return ( {/* Place your main application content here. This ensures that all components within have access to the connected wallet context provided by WagmiProvider, enabling features like reading connection state or sending transactions. */} ); } ``` **Step 4: Add the Connect Button** Use RainbowKit's pre-built `ConnectButton` component to handle wallet connections: ```jsx import { ConnectButton } from '@rainbow-me/rainbowkit'; function YourAppContent() { return (
); } ``` **Step 5: Access Connection State** Use Wagmi hooks to read the connected Universal Profile details: ```js import { useAccount, useChainId } from 'wagmi'; function YourAppContent() { const { address, isConnected, chain } = useAccount(); const chainId = useChainId(); return (
{isConnected && (

Address: {address}

Network: {chain?.name}

Chain ID: {chainId}

)}
); } ``` Reown AppKit}> **Step 1: Install Dependencies** ```sh npm install @reown/appkit @reown/appkit-adapter-wagmi wagmi @tanstack/react-query ``` **Step 2: Configure the WagmiAdapter with LUKSO** Set up the adapter with LUKSO network configuration: ```js import { WagmiProvider } from 'wagmi'; import { createAppKit } from '@reown/appkit/react'; import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'; import { lukso } from '@reown/appkit/networks'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; // Wagmi uses QueryClient to manage cache, background updates, and request deduplication. // This is required to provide higher up in your component tree. const queryClient = new QueryClient(); // highlight-start const wagmiAdapter = new WagmiAdapter({ projectId: 'YOUR_PROJECT_ID', // Get your project ID from ReOwn dashboard networks: [lukso], transports: { [lukso.id]: http('https://rpc.mainnet.lukso.network'), }, }); // highlight-end ``` **Step 3: Create the AppKit Modal** Initialize the modal with your dApp metadata and LUKSO-specific settings: ```js const metadata = { name: 'LUKSO Wallet Connect', description: 'Connect your Universal Profile', url: 'https://universaleverything.io', icons: ['https://lukso.network/favicon.ico'], }; // highlight-start createAppKit({ adapters: [wagmiAdapter], projectId: 'YOUR_PROJECT_ID', // Get your project ID from ReOwn dashboard networks: [lukso], defaultNetwork: lukso, metadata, features: { analytics: false, email: false, socials: false, }, }); // highlight-end ``` **Step 4: Wrap Your App with the Provider** Wrap your application with the required providers in the correct order: ```jsx function App() { return ( {/* Place your main application content here. This ensures that all components within have access to the connected wallet context provided by WagmiProvider, enabling features like reading connection state or sending transactions. */} ); } ``` **Step 5: Use the `Connect` button and access to connection state** Use `Wagmi` hooks to read the connected Universal Profile details: ```js import { useAccount, useChainId } from 'wagmi'; function YourAppContent() { const { address, isConnected, chain } = useAccount(); const chainId = useChainId(); return (
{isConnected && (

Address: {address}

Network: {chain?.name}

Chain ID: {chainId}

)}
); } ``` **Optional: Configure the DeepLink for UP Mobile** DeepLink can be configured for QR login when using the UP Mobile app with _ReOwn (WalletConnect)_. :::success Configuring DeepLink Simply replace the `wc:` alias with `io.universaleverything.universalprofiles://wallet-connect/`: ```js const exampleWcUri = 'wc:8c4d7a9e5f2b3c1d@2?relay-protocol=irn&symKey=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6'; const exampleDeepLink = exampleWcUri.replace( 'wc:', 'io.universaleverything.universalprofiles://wallet-connect/', ); ``` ::: ### Provider Injection You can use the `window.lukso` object, tailored for a direct integration with the UP Browser Extension. This approach allows developers to engage directly with the UP Browser Extension without the need to consider compatibility with other extensions. ```sh npm install viem ``` ```sh npm install ethers ``` ```sh npm install web3 ``` ```js import { createWalletClient, custom } from 'viem'; import { lukso } from 'viem/chains'; const client = createWalletClient({ chain: lukso, transport: custom(window.lukso), }); const accounts = await client.requestAddresses(); console.log('Connected with', accounts[0]); ``` ```js import { ethers } from 'ethers'; const provider = new ethers.BrowserProvider(window.lukso); const accounts = await provider.send('eth_requestAccounts', []); console.log('Connected with', accounts[0]); ``` ```js import Web3 from 'web3'; const provider = new Web3(window.lukso); const accounts = await provider.eth.requestAccounts(); console.log('Connected with', accounts[0]); ``` :::info Wallet Compatibility Alternatively to the `window.lukso`, the equivalent `window.ethereum` object can be called within [supported browsers](/install-up-browser-extension), just like other Ethereum wallets. Both follow the [EIP-1193 Ethereum Provider JavaScript API](https://eips.ethereum.org/EIPS/eip-1193). You can use a simple fallback to allow regular wallet connections, if the [Universal Profile Browser Extension](/install-up-browser-extension) is not installed: ::: ```js import { createWalletClient, custom } from 'viem'; import { lukso } from 'viem/chains'; const client = createWalletClient({ chain: lukso, // highlight-next-line transport: custom(window.lukso || window.ethereum), }); ``` ```js const provider = new ethers.BrowserProvider(window.lukso || window.ethereum); ``` ```js const provider = new Web3(window.lukso || window.ethereum); ``` ### Provider Discovery :::tip Example Implementation If you want to implement _Injected Provider Discovery_ you can visit our [Example EIP-6963 Test dApp](https://github.com/lukso-network/example-eip-6963-test-dapp). ::: :::info Wallet Compatibility Using [EIP-6963 Provider Discovery](https://eips.ethereum.org/EIPS/eip-6963) is the latest industry standardization, solving previous connectivity issues when having multiple wallet extensions installed at the same time. ::: You can listen to `eip6963:announceProvider` events following the [EIP-6963: Multi Injected Provider](https://eips.ethereum.org/EIPS/eip-6963) standardization to facilitate a more versatile connection to multiple wallet extensions. This method is beneficial for developers who require the ability to maintain low-level control over how different extensions are targeted and managed within their dApp. **Step 1: Install Dependencies** ```sh npm install viem ``` **Step 2: Implement Provider Discovery** ```js import { createWalletClient, custom } from 'viem'; import { lukso } from 'viem/chains'; let providers = []; window.addEventListener('eip6963:announceProvider', (event) => { providers.push(event.detail); }); // Request installed providers window.dispatchEvent(new Event('eip6963:requestProvider')); // ... pick a provider to instantiate (providers[n].info) // Create a wallet client using the selected provider const walletClient = createWalletClient({ chain: lukso, transport: custom(providers[0].provider), }); const accounts = await walletClient.requestAddresses(); console.log('Connected with', accounts[0]); ``` ## Helpful Resources - Next Stop: [Read Universal Profile Data](/docs/learn/universal-profile/metadata/read-profile-data.md) - [LUKSO Mainnet Parameters, RPC Providers](/docs/networks/mainnet/parameters.md#add-lukso-to-wallets) [📱 UP Mobile App]: /install-up-browser-extension/#up-mobile-app --- --- sidebar_label: 'UP Log-in & SIWE' sidebar_position: 2 description: Learn how to log-in a Universal Profile using SIWE (Sign-In With Ethereum). --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Log-in a Universal Profile (SIWE)
The [Universal Profile Browser Extension](https://chrome.google.com/webstore/detail/universal-profiles/abpickdkkbnbcoepogfhkhennhfhehfn) supports [EIP-4361: Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) to sign custom messages and prove ownership of the connected account. In order to show the log-in screen in the extension and verify the signature of the controller, you have to ensure that the message complies with this standard. ## Setup To implement Sign In With Ethereum for Universal Profiles (smart accounts), you will have to install: - a **provider library** to connect to the account - the **SIWE library** to prepare and manage the custom messages - the **LSP smart contracts library** to verify the signature of the profile's controller. ```shell npm install ethers @lukso/lsp-smart-contracts siwe ``` ```shell npm install web3 @lukso/lsp-smart-contracts siwe ``` ## Get the Universal Profile address ```js import { ethers } from 'ethers'; const provider = new ethers.BrowserProvider(window.lukso); const accounts = await provider.send('eth_requestAccounts', []); ``` ```js import Web3 from 'web3'; const provider = new Web3(window.lukso); const accounts = await provider.eth.requestAccounts(); ``` ## Sign the message Once you have access to the Universal Profile address, you can request a signature. As a smart contract can't sign by itself, the Universal Profile Browser Extension will automatically redirect the request to **sign the message with the related controller key** of the extension. :::tip SIWE Specification If you need further explanation on the `SiweMessage` properties, please have a look at the [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) specification. ::: ```js import UniversalProfileContract from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { SiweMessage } from 'siwe'; const { chainId } = await provider.getNetwork() // Prepare a message with the SIWE-specific format const siweMessage = new SiweMessage({ domain: window.location.host, // Domain requesting the signing address: accounts[0], // Address performing the signing statement: 'By logging in you agree to the terms and conditions.', // Human-readable assertion the user signs uri: window.location.origin, // URI from the resource that is the subject of the signature version: '1', // Current version of the SIWE Message chainId: chainId, // Chain ID to which the session is bound to resources: ['https://terms.website.com'], // Authentication resource as part of authentication by the relying party }).prepareMessage(); // Get the signer of the Universal Profile const signer = await provider.getSigner(accounts[0]); // Request the extension to sign the message const signature = await signer.signMessage(siweMessage); // 0x38c53... // Create a contract instance to verify the signature on const universalProfileContract = new ethers.Contract( accounts[0], UniversalProfileContract.abi, provider ); // Create the message's hash for verification purposes const hashedMessage = ethers.hashMessage(siweMessage); ``` ```js import UniversalProfileContract from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { SiweMessage } from 'siwe'; const { chainId } = await provider.getNetwork() // Prepare a message with the SIWE-specific format const siweMessage = new SiweMessage({ domain: window.location.host, // Domain requesting the signing address: accounts[0], // Address performing the signing statement: 'By logging in you agree to the terms and conditions.', // Human-readable assertion the user signs uri: window.location.origin, // URI from the resource that is the subject of the signature version: '1', // Current version of the SIWE Message chainId: chainId, // Chain ID to which the session is bound to resources: ['https://terms.website.com'], // Authentication resource as part of authentication by the relying party }).prepareMessage(); // Request the extension to sign the message const signature = await web3.eth.sign(siweMessage, accounts[0]); // 0x38c53... // Create a contract instance to verify the signature on const universalProfileContract = new web3.eth.Contract( UniversalProfileContract.abi, accounts[0], ); // Create the message's hash for verification purposes const hashedMessage = web3.eth.accounts.hashMessage(siweMessage); ``` ## Verify the signature Your dApp has now received a message signed by the controller address of the Universal Profile. To finalise the login, you need to verify if the message was signed by an address which has the [`SIGN`](/standards/access-control/lsp6-key-manager.md#permissions) permission for this Universal Profile. To check the signature, you can use the [`isValidSignature(...)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#isvalidsignature) method of the [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) standardization. If the signature is valid, the method will return the magic value `0x1626ba7e`, indicating a successful verification. ```js // Execute the contract verification call const isValidSignature = await myUniversalProfileContract .isValidSignature(hashedMessage, signature) .call(); // Check if the response is equal to the magic value if (isValidSignature === '0x1626ba7e') { console.log('Log In successful!'); } else { // The signing EOA has no SIGN permission on this UP. console.log('Log In failed'); } ``` ```js // Execute the contract verification call const isValidSignature = await myUniversalProfileContract.methods .isValidSignature(hashedMessage, signature) .call(); // Check if the response is equal to the magic value if (isValidSignature === '0x1626ba7e') { console.log('Log In successful!'); } else { // The signing EOA has no SIGN permission on this UP. console.log('Log In failed'); } ``` ## Further authentication To apply security measures on the server side of your application, you can use the **raw message format** below to authenticate users based on their Ethereum wallet signatures. The standardized format enables a non-custodial authentication mechanism where users prove ownership of their Ethereum address without revealing any sensitive information: ```js title="Raw SIWE message format" const domain = window.location.host; // Domain requesting the signing const uri = window.location.origin; // URI from the resource that is the subject of the signature const LUKSO_TESTNET_CHAIN_ID = '4201'; // The Chain ID to which the session is bound to const nonce = 'm97bdsjo'; // A randomized token, at least 8 alphanumeric characters const issuedAt = new Date().toISOString(); // The time when the message was generated const siweMessage = `${domain} wants you to sign in with your Ethereum account: ${usersUPaddress} By logging in you agree to the terms and conditions. URI: ${uri} Version: 1 Chain ID: ${LUKSO_TESTNET_CHAIN_ID} Nonce: ${nonce} Issued At: ${issuedAt} Resources: - https://terms.website.com`; ``` One practical application of the raw SIWI message is to generate _JSON Web Tokens_ after verifying the user's signature. This approach ensures that only the rightful owner of an Ethereum address can obtain a session token, enhancing the security and privacy of your Web3-based application. You can get additional guidance on the following resources: - [🎥 BuildUP #2 | Web3 Auth: Using Universal Profile and SIWE for Login (YouTube)](https://www.youtube.com/watch?v=lY18lBu3_XA) - [🛠️ LUKSO SIWE Demo Repository | Generating JWT's using Universal Profiles (GitHub)](https://github.com/richtera/lukso-siwe-demo) --- --- sidebar_label: 'Execute Batch Transactions' sidebar_position: 5 description: Discover how you can do batch transactions with your Universal Profile Browser Extension, such as transferring different tokens and NFTs to different addresses in one transaction. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Execute Batch Transactions :::tip Code repository All the contracts, sample metadata, and scripts of this guide are available in the [`lukso-playground`](https://github.com/lukso-network/lukso-playground/tree/main/smart-contracts) repository. :::

Universal Profiles support natively batch transactions to perform complex transfer scenarios. Like transferring LYX or multiple tokens and NFTs to different recipient addresses.

A Universal Profile contains a function called [`executeBatch(...)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#executebatch) to perform batch transaction. With some thinking, we will see that this function can enables a countless number of creative use cases. Below are some useful and simple example code snippets covered, around transferring LYX, tokens and NFTs to one or multiple different addresses. ## Transfer Examples ### Transfer LYX to different recipients ```ts import { ethers, hexlify, toUtf8Bytes } from 'ethers'; import { OPERATION_TYPES } from '@lukso/lsp-smart-contracts'; import UniversalProfileArtifacts from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; const provider = new ethers.BrowserProvider(window.lukso); const universalProfile = await provider.getSigner(); console.log('UP address: ', universalProfile); const upContract = new Contract( universalProfile, // Universal Profile address UniversalProfileArtifacts.abi, universalProfile, // signer that will sign the transaction ); const operationTypes = [ OPERATION_TYPES.CALL, // 0 OPERATION_TYPES.CALL, // 0 OPERATION_TYPES.CALL, // 0 ]; const lyxRecipients = ['0x...', '0x...', '0x...']; const lyxAmounts = [parseEther('1'), parseEther('2'), parseEther('3')]; const data = [ '0x', // transferring LYX without any data hexlify(toUtf8Bytes('Here is a tip, buy yourself a coffee!')), // you can also add any data as utf8-hex in the LYX transfer hexlify(toUtf8Bytes('Paying back my debt I owe you')), ]; await upContract.executeBatch(operationTypes, lyxRecipients, lyxAmounts, data); ``` ```ts import Web3 from 'web3'; import { OPERATION_TYPES } from '@lukso/lsp-smart-contracts'; import UniversalProfileArtifacts from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; const web3 = new Web3(window.lukso); const [universalProfile] = await web3.eth.personal.getAccounts(); console.log('UP address: ', universalProfile); const upContract = new Contract( UniversalProfileArtifacts.abi, universalProfile, // Universal Profile address ); const operationTypes = [ OPERATION_TYPES.CALL, // 0 OPERATION_TYPES.CALL, // 0 OPERATION_TYPES.CALL, // 0 ]; const lyxRecipients = ['0x...', '0x...', '0x...']; const lyxAmounts = [ web3.utils.toWei('1', 'ether'), web3.utils.toWei('2', 'ether'), web3.utils.toWei('3', 'ether'), ]; const data = [ '0x', // transferring LYX without any data web3.utils.utf8ToHex('Here is a tip, buy yourself a coffee!'), // you can also add any data as utf8-hex in the LYX transfer web3.utils.utf8ToHex('Paying back my debt I owe you'), ]; await upContract.methods .executeBatch(operationTypes, lyxRecipients, lyxAmounts, data) .send({ from: universalProfile }); ``` ### Transfer 3 x tokens to the same recipient ```ts import { ethers } from 'ethers'; import { OPERATION_TYPES } from '@lukso/lsp-smart-contracts'; import UniversalProfileArtifacts from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP7DigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; const provider = new ethers.BrowserProvider(window.lukso); const universalProfile = await provider.getSigner(); const upContract = new Contract( universalProfile, UniversalProfileArtifacts.abi, universalProfile, ); // List of tokens addresses (including meme coins) const FABS_TOKEN = '0x650e14f636295af421D9BB788636356aA7F5924c'; const CHILL_TOKEN = '0x5B8B0E44D4719F8A328470DcCD3746BFc73d6B14'; const SOON_TOKEN = '0x3B56718C2AcC074B6640b2fa90DbB755f20033eA'; // We do not need to create an instance for each contracts, they are all LSP7 const lsp7Token = new Contract(FABS_TOKEN, LSP7DigitalAssetArtifact.abi); const recipient = '0x...'; // address that will receive the tokens const transferFabsCalldata = await lsp7Token.transfer.populateTransaction( universalProfile, // from '0x...', // to parseEther('10'), // amount true, // force transfer '0x', // data ); const transferChillCalldata = await lsp7Token.transfer.populateTransaction( universalProfile, recipient, parseEther('20'), true, '0x', ); const transferSoonCalldata = await lsp7Token.transfer.populateTransaction( universalProfile, recipient, parseEther('30'), true, '0x', ); const operationTypes = [ OPERATION_TYPES.CALL, OPERATION_TYPES.CALL, OPERATION_TYPES.CALL, ]; const tokenContractsToCall = [FABS_TOKEN, CHILL_TOKEN, SOON_TOKEN]; const values = [parseEther('0'), parseEther('0'), parseEther('0')]; const calldatas = [ transferFabsCalldata.data, transferChillCalldata.data, transferSoonCalldata.data, ]; await upContract.executeBatch( operationTypes, tokenContractsToCall, values, calldatas, { from: universalProfile, }, ); ``` ```ts import Web3 from 'web3'; import { OPERATION_TYPES } from '@lukso/lsp-smart-contracts'; import UniversalProfileArtifacts from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP7DigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; const web3 = new Web3(window.lukso); const [universalProfile] = await web3.eth.personal.getAccounts(); const upContract = new web3.eth.Contract( UniversalProfileArtifacts.abi, universalProfile, ); // List of tokens addresses (including meme coins) const FABS_TOKEN = '0x650e14f636295af421D9BB788636356aA7F5924c'; const CHILL_TOKEN = '0x5B8B0E44D4719F8A328470DcCD3746BFc73d6B14'; const SOON_TOKEN = '0x3B56718C2AcC074B6640b2fa90DbB755f20033eA'; // We do not need to create an instance for each contracts, they are all LSP7 const lsp7Token = new web3.eth.Contract( LSP7DigitalAssetArtifact.abi, FABS_TOKEN, ); const recipient = '0x...'; // address that will receive the tokens const transferFabsCalldata = await lsp7Token.methods .transfer( universalProfile, // from '0x...', // to web3.utils.toWei('10', 'ether'), // amount true, // force transfer '0x', // data ) .encodeABI(); const transferChillCalldata = await lsp7Token.methods .transfer( universalProfile, recipient, web3.utils.toWei('20', 'ether'), true, '0x', ) .encodeABI(); const transferSoonCalldata = await lsp7Token.methods .transfer( universalProfile, recipient, web3.utils.toWei('30', 'ether'), true, '0x', ) .encodeABI(); const operationTypes = [ OPERATION_TYPES.CALL, // 0 OPERATION_TYPES.CALL, // 0 OPERATION_TYPES.CALL, // 0 ]; const tokenContractsToCall = [FABS_TOKEN, CHILL_TOKEN, SOON_TOKEN]; const values = [ web3.utils.toWei('0', 'ether'), web3.utils.toWei('0', 'ether'), web3.utils.toWei('0', 'ether'), ]; const calldatas = [ transferFabsCalldata, transferChillCalldata, transferSoonCalldata, ]; await upContract.methods .executeBatch(operationTypes, tokenContractsToCall, values, calldatas) .send({ from: universalProfile, }); ``` ### Transfer different NFTs to the same recipient ```ts import { ethers } from 'ethers'; import { OPERATION_TYPES } from '@lukso/lsp-smart-contracts'; import UniversalProfileArtifacts from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP7DigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; import LSP8IdentifiableDigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; const provider = new ethers.BrowserProvider(window.lukso); const universalProfile = await provider.getSigner(); const recipient = '0x...'; // address that will receive the NFTs const upContract = new Contract( universalProfile, UniversalProfileArtifacts.abi, universalProfile, ); // List of NFT contracts const CHILLWHALE_NFT = '0x86E817172b5c07f7036Bf8aA46e2db9063743A83'; const PLATTIES_NFT = '0x5021E9ED50D8C71E3D74c0de7964342AAA1A0F62'; const PANGOLYX_NFT = '0xCDD480a4d3a9961be62eF40b01bf86175b341fBB'; const chillwhaleTokenId = '0x000000000000000000000000000000000000000000000000000000000000013f'; const plattyTokenId = '0x00000000000000000000000000000000000000000000000000000000000002b7'; const pangolyxTokenId = '0x0000000000000000000000000000000000000000000000000000000000000164'; // We do not need to create an instance for each contracts, they are all LSP7 const lsp8Nft = new Contract( CHILLWHALE_NFT, LSP8IdentifiableDigitalAssetArtifact.abi, ); const transferChillwhaleCalldata = await lsp8Nft.transfer.populateTransaction( universalProfile, // from recipient, // to chillwhaleTokenId, // bytes32 tokenId true, // force '0x', // data ); const transferPlattyCalldata = await lsp8Nft.transfer.populateTransaction( universalProfile, recipient, plattyTokenId, true, '0x', ); const transferPangolyxCalldata = await lsp8Nft.transfer.populateTransaction( universalProfile, recipient, pangolyxTokenId, true, '0x', ); const operationTypes = [ OPERATION_TYPES.CALL, OPERATION_TYPES.CALL, OPERATION_TYPES.CALL, ]; const tokenContractsToCall = [CHILLWHALE_NFT, PLATTIES_NFT, PANGOLYX_NFT]; const values = [parseEther('0'), parseEther('0'), parseEther('0')]; const calldatas = [ transferChillwhaleCalldata.data, transferPlattyCalldata.data, transferPangolyxCalldata.data, ]; await upContract.executeBatch( operationTypes, tokenContractsToCall, values, calldatas, { from: universalProfile, }, ); ``` ```ts import Web3 from 'web3'; import { OPERATION_TYPES } from '@lukso/lsp-smart-contracts'; import UniversalProfileArtifacts from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP8IdentifiableDigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; const web3 = new Web3(window.lukso); const [universalProfile] = await web3.eth.personal.getAccounts(); const recipient = '0x...'; // address that will receive the NFTs const upContract = new Contract( universalProfile, UniversalProfileArtifacts.abi, universalProfile, ); // List of NFT contracts const CHILLWHALE_NFT = '0x86E817172b5c07f7036Bf8aA46e2db9063743A83'; const PLATTIES_NFT = '0x5021E9ED50D8C71E3D74c0de7964342AAA1A0F62'; const PANGOLYX_NFT = '0xCDD480a4d3a9961be62eF40b01bf86175b341fBB'; const chillwhaleTokenId = '0x000000000000000000000000000000000000000000000000000000000000013f'; const plattyTokenId = '0x00000000000000000000000000000000000000000000000000000000000002b7'; const pangolyxTokenId = '0x0000000000000000000000000000000000000000000000000000000000000164'; // We do not need to create an instance for each contracts, they are all LSP7 const lsp8Nft = new web3.eth.Contract( LSP8IdentifiableDigitalAssetArtifact.abi, CHILLWHALE_NFT, ); const transferChillwhaleCalldata = await lsp8Nft.methods .transfer( universalProfile, // from recipient, // to chillwhaleTokenId, // bytes32 tokenId true, // force '0x', // data ) .encodeABI(); const transferPlattyCalldata = await lsp8Nft.methods .transfer(universalProfile, recipient, plattyTokenId, true, '0x') .encodeABI(); const transferPangolyxCalldata = await lsp8Nft.methods .transfer(universalProfile, recipient, pangolyxTokenId, true, '0x') .encodeABI(); const operationTypes = [ OPERATION_TYPES.CALL, // 0 OPERATION_TYPES.CALL, // 0 OPERATION_TYPES.CALL, // 0 ]; const tokenContractsToCall = [CHILLWHALE_NFT, PLATTIES_NFT, PANGOLYX_NFT]; const values = [ web3.utils.toWei('0', 'ether'), web3.utils.toWei('0', 'ether'), web3.utils.toWei('0', 'ether'), ]; const calldatas = [ transferChillwhaleCalldata.data, transferPlattyCalldata.data, transferPangolyxCalldata.data, ]; await upContract .executeBatch(operationTypes, tokenContractsToCall, values, calldatas) .send({ from: universalProfile, }); ``` ### Mixing LYX, Tokens, NFT and recipient addresses This example shows how to transfer three different assets to different addresses in a single transaction. For instance, from our 🆙, we can: - send LYX to Alice. - send some LSP7 tokens to Bob. - send an LSP8 NFT to Carol. ```ts import { ethers } from 'ethers'; import { OPERATION_TYPES } from '@lukso/lsp-smart-contracts'; import UniversalProfileArtifacts from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP7DigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; import LSP8IdentifiableDigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; const provider = new ethers.BrowserProvider(window.lukso); const universalProfile = await provider.getSigner(); // Addresses that will receive some digital assets const lyxRecipient = '0x...'; const tokenRecipient = '0x...'; const nftRecipient = '0x...'; const upContract = new Contract( universalProfile, UniversalProfileArtifacts.abi, universalProfile, ); // List of Tokens and NFT contracts const CHILL_TOKEN = '0x5B8B0E44D4719F8A328470DcCD3746BFc73d6B14'; const PANGOLYX_NFT = '0xCDD480a4d3a9961be62eF40b01bf86175b341fBB'; const pangolyxTokenId = '0x0000000000000000000000000000000000000000000000000000000000000164'; // Create instances of the Token and NFT contracts const lsp7Token = new Contract(CHILL_TOKEN, LSP7DigitalAssetArtifact.abi); const lsp8Nft = new Contract( PANGOLYX_NFT, LSP8IdentifiableDigitalAssetArtifact.abi, ); // Create the calldatas that will be passed to the `data` field of `executeBatch` const transferTokensCalldata = await lsp7Token.transfer.populateTransaction( universalProfile, tokenRecipient, parseEth('100'), // send 100 tokens true, '0x', ); const transferNftCalldata = await lsp8Nft.transfer.populateTransaction( universalProfile, // from nftRecipient, // to pangolyxTokenId, // bytes32 tokenId true, // force '0x', // data ); await upContract.executeBatch( [OPERATION_TYPES.CALL, OPERATION_TYPES.CALL, OPERATION_TYPES.CALL], [lyxRecipient, lsp7Token.address, lsp8Nft.address], [ parseEther('10'), // send 10 LYX 0, 0, ], [ '0x', // no data sent when transferring LYX transferTokensCalldata.data, // calldata of `LSP7.transfer(address,address,uint256,bool,bytes) transferNftCalldata.data, // calldata of `LSP7.transfer(address,address,bytes32,bool,bytes) ], { from: universalProfile, }, ); ``` ```ts import Web3 from 'web3'; import { OPERATION_TYPES } from '@lukso/lsp-smart-contracts'; import UniversalProfileArtifacts from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP7DigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; import LSP8IdentifiableDigitalAssetArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; const web3 = new Web3(window.lukso); const universalProfile = await web3.eth.personal.getAccounts(); // Addresses that will receive some digital assets const lyxRecipient = '0x...'; const tokenRecipient = '0x...'; const nftRecipient = '0x...'; const upContract = new web3.eth.Contract( UniversalProfileArtifacts.abi, universalProfile, ); // List of Tokens and NFT contracts const CHILL_TOKEN = '0x5B8B0E44D4719F8A328470DcCD3746BFc73d6B14'; const PANGOLYX_NFT = '0xCDD480a4d3a9961be62eF40b01bf86175b341fBB'; const pangolyxTokenId = '0x0000000000000000000000000000000000000000000000000000000000000164'; // Create instances of the Token and NFT contracts const lsp7Token = new web3.eth.Contract( LSP7DigitalAssetArtifact.abi, CHILL_TOKEN, ); const lsp8Nft = new web3.eth.Contract( LSP8IdentifiableDigitalAssetArtifact.abi, PANGOLYX_NFT, ); // Create the calldatas that will be passed to the `data` field of `executeBatch` const transferTokensCalldata = await lsp7Token.methods .transfer( universalProfile, tokenRecipient, parseEth('100'), // send 100 tokens true, '0x', ) .encodeABI(); const transferNftCalldata = await lsp8Nft.methods .transfer( universalProfile, // from nftRecipient, // to pangolyxTokenId, // bytes32 tokenId true, // force '0x', // data ) .encodeABI(); await upContract.methods .executeBatch( [OPERATION_TYPES.CALL, OPERATION_TYPES.CALL, OPERATION_TYPES.CALL], [lyxRecipient, lsp7Token.address, lsp8Nft.address], [ web3.utils.toWei('10', 'ether'), // send 10 LYX 0, 0, ], [ '0x', // no data sent when transferring LYX transferTokensCalldata.data, // calldata of `LSP7.transfer(address,address,uint256,bool,bytes) transferNftCalldata.data, // calldata of `LSP7.transfer(address,address,bytes32,bool,bytes) ], ) .send({ from: universalProfile, }); ``` ## Contract Deployment Examples The [`executeBatch`](../../../contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#executebatch) function is also useful to perform any action on a contract after deploying it from a 🆙. ### Deploy a Token + Set Metadata :::info Info For demonstration purpose, the code below deploys a `LSP7Mintable`, a preset token contract available in the `@lukso/lsp-smart-contracts` package. Feel free to use the bytecode of any custom or extended token contract you have created. You can then adjust any extra constructor parameters as per your needs. ::: This code shows how to set the [metadata](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md) of a [LSP7 Digital Asset](../../../standards/tokens/LSP7-Digital-Asset.md) contract while deploying it. The batch will contain two actions that will run successively: 1. deploy the token contract with some deployment parameters (token name, symbol, etc...). For this, we will encode the constructor parameters used when deploying the token contract. and then generate the bytecode for the contract deployment. 2. set the metadata on the token contract. For this we will first encode the `LSP4Metadata` using the [`erc725.js`](../../../tools/dapps/erc725js/getting-started.md) library. We will then generate the payload to call `setData` on the token contract using this encoded parameter. > _"How can we set the token metadata if we don't know the deployed token address yet?"_ > > We have to mimic deploying the contract from the UP using `staticCall`. This will not dispatch the transaction return **the future token contract address**. > > The second call in the [`executeBatch()`](../../../contracts/contracts/ERC725/ERC725.md#executebatch) function will then use the [previously generated contract address](#prepare-the-transaction-payloads) from the `staticCall` in order to set the metadata. ```ts showLineNumbers import { ethers } from 'ethers'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; import UniversalProfileArtifact from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP7Mintable from '@lukso/lsp-smart-contracts/artifacts/LSP7Mintable.json'; import { ERC725 } from '@erc725/erc725.js'; import LSP4DigitalAssetSchema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; // link to the JSON metadata file of the digital asset import { lsp4SampleMetadata } from './LSP4SampleMetadata'; // UP controller used for deployment // Connect to your Universal Profile from your dApp const provider = new ethers.BrowserProvider(window.lukso); const universalProfile = await ethers.getSigner(); console.log( 'Deploying contract with Universal Profile: ', universalProfile.address, ); // Create an instance of the Universal Profile const universalProfile = new Contract( universalProfile.address, // address of the Universal Profile UniversalProfileArtifact.abi, // Smart Contract ABI universalProfile, // provider connected to that will run transactions ); // highlight-start // Create custom bytecode for the token deployment const tokenBytecode = LSP7Mintable.bytecode; const abiEncoder = new ethers.AbiCoder(); // Encode constructor parameters const encodedConstructorParams = abiEncoder.encode( ['string', 'string', 'address', 'uint256', 'bool'], [ 'My Custom Token', // token name 'MCT', // token symbol universalProfile.address, // token owner 0, // token type = TOKEN false, // isNonDivisible? ], ); // Add the constructor parameters to the token bytecode const tokenBytecodeWithConstructor = ethers.concat([ tokenBytecode, encodedConstructorParams, ]); // Get the address of the custom token contract that will be created // https://docs.lukso.tech/contracts/contracts/ERC725/#execute const customTokenAddress = await universalProfile.execute.staticCall( 1, // Operation type: CREATE ethers.ZeroAddress, // Target: 0x0 as contract will be initialized 0, // Value is empty tokenBytecodeWithConstructor, // Payload of the contract ); // Encode the metadata for deployment // https://docs.lukso.tech/tools/erc725js/classes/ERC725#encodedata const encodedLSP4Metadata = ERC725.encodeData( [ { keyName: 'LSP4Metadata', value: { json: lsp4SampleMetadata, url: 'ipfs://...', }, }, ], LSP4DigitalAssetSchema, ); // Set up the token contract const token = new ethers.Interface(LSP7Mintable.abi); // Get the ERC725Y data key of LSP4 const metadataKey = ERC725YDataKeys.LSP4['LSP4Metadata']; // Create the transaction payload for setting storage data // https://docs.lukso.tech/contracts/contracts/ERC725/#setdata const setLSP4MetadataPayload = token.interface.encodeFunctionData('setData', [ encodedLSP4Metadata.keys[0], // LSP4Metadata data key encodedLSP4Metadata.values[0], // value as an encoded VerifiableURI ]); // Deploy the contract by the Universal Profile // https://docs.lukso.tech/contracts/contracts/ERC725/#executebatch const tx = await universalProfile.executeBatch( [ // Array of Operation types 1, // Operation type: CREATE (Contract deployment) 0, // Operation type: CALL (Set storage key on contract) ], [ ethers.ZeroAddress, // 0x0 as contract will be initialized customTokenAddress, // Contract address after deployment ], [0, 0], // Value is empty for both operations [ tokenBytecodeWithConstructor, // Payload for contract deployment setLSP4MetadataPayload, // Payload for setting a data key on the deployed contract ], ); // Wait for the transaction to be included in a block await tx.wait(); console.log('Token deployed at: ', customTokenAddress); ``` --- --- sidebar_label: 'Deploy contracts from UP' sidebar_position: 4 description: Learn how to deploy a contract from your Universal Profile. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Deploy Contracts

Deploying a contract from a Universal Profile using the Browser Extension showing the bytecode of the contract

## Setup ```shell npm install ethers ``` ## Deploy a contract from a UP The Universal Profile browser extension will magically wrap all the calls internally so you don't have to worry about crafting custom transactions. Simply use [`eth_sendTransaction`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction) as you always did while working with EOA. ```js import { ethers } from 'ethers'; const provider = new ethers.BrowserProvider(window.lukso); await provider.send("eth_requestAccounts", []); const signer = await provider.getSigner(); const account = await signer.getAddress(); // Send transaction const tx = await signer.sendTransaction({ from: account, // The Universal Profile address value: 0, // optional, in case constructor is payable data: "0x608060405234801561001..." // Full bytecode of the contract to deploy + constructor args }); const receipt = await tx.wait(); ``` You can use the [contract factory from ethers.js](https://docs.ethers.org/v5/api/contract/contract-factory/#ContractFactory) to deploy a contract by supplying its ABI and bytecode. For instance, if you're deploying an [LSP7Mintable](../../../contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md) contract, you can obtain its ABI and bytecode from the `@lukso/lsp-smart-contracts` package. ```shell npm install @lukso/lsp-smart-contracts ``` ```js import LSP7Mintable from "@lukso/lsp-smart-contracts/artifacts/LSP7Mintable.json" // Prepare the factory with the abi and bytecode const lsp7Factory = new ethers.ContractFactory( LSP7Mintable.abi, LSP7Mintable.bytecode, signer ); // send the transaction of deployment const transaction = await lsp7Factory.deploy( 'Yamen token', 'no desc', "0x0000000000000000000000000000000000000011", 0, false ); const receipt = await transaction.waitForDeployment(); ``` ## Retrieve Contract Deployment Infos There will be no `contractAddress` field in the transaction `receipt` unlike normal transactions happening with Metamask. This is because the UP browser extension wraps the deployment transaction within a normal contract execution transaction. The contract address can be calculated using the **nonce** and the **address** of the profile or retrieved using the logs (code snippet below). ```js import { ethers } from 'ethers'; const provider = new ethers.BrowserProvider(window.lukso); await provider.send("eth_requestAccounts", []); const signer = await provider.getSigner(); const account = await signer.getAddress(); // Send transaction const tx = await signer.sendTransaction({ from: account, // The Universal Profile address value: 0 // optional, in case constructor is payable data: "0x0x608060405234801561001.." // Full bytecode of the contract to deploy + constructor args }); const receipt = await tx.wait(); // The signature of the ContractCreated event emitted by the profile /** * event ContractCreated( * uint256 indexed operationType, * address indexed contractAddress, * uint256 value, * bytes32 indexed salt * ) * * 0xa1fb700aaee2ae4a2ff6f91ce7eba292f89c2f5488b8ec4c5c5c8150692595c3 = keccak256('ContractCreated(uint256,address,uint256,bytes32)') */ const targetTopic0 = '0xa1fb700aaee2ae4a2ff6f91ce7eba292f89c2f5488b8ec4c5c5c8150692595c3'; for (const log of receipt.logs) { // Check if the first topic matches the target topic if (log.topics[0] === targetTopic0) { // Decode the operation type from bytes32 to number const operationType = parseInt(log.topics[1], 16); // Decode the contract address from bytes32 to Ethereum address const contractAddress = `0x${log.topics[2].slice(-40)}`; // Keep the salt as is const salt = log.topics[3]; console.log('Found target event:'); console.log('Operation Type:', operationType); console.log('Contract Address:', contractAddress); console.log('Salt:', salt); } } ``` ## Examples ### Deploy an LSP7 Token ```ts import { ethers } from 'ethers'; import UniversalProfileArtifact from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // Path to generated artifact for your Custom Token Contract import MyCustomToken from './path/to/artifacts/MyCustomToken.json'; // Connect to UP Browser Extension and get the UP address const provider = new ethers.BrowserProvider(window.lukso); await provider.send('eth_requestAccounts', []); const account = await deployer.getAddress(); console.log('Deploying contract from Universal Profile: ', account); // Create instance of the Universal Profile const universalProfile = new ethers.Contract(UniversalProfileArtifact, account); const abiEncoder = new ethers.AbiCoder(); // Encode constructor parameters const encodedConstructorParams = abiEncoder.encode( ['string', 'string', 'address', 'uint256', 'bool'], [ 'My Custom Token', // token name 'MCT', // token symbol accounts, // token owner (our UP) 0, // token type = TOKEN false, // isNonDivisible? ], ); // Add the constructor parameters to the token bytecode const tokenBytecodeWithConstructor = ethers.concat([ MyCustomToken.bytecode, encodedConstructorParams, ]); // Get the address of the custom token contract that will be created // https://docs.lukso.tech/contracts/contracts/ERC725/#execute const customTokenAddress = await universalProfile.execute.staticCall( 1, // Operation type: CREATE ethers.ZeroAddress, // Target: 0x0 as contract will be initialized 0, // Value is empty tokenBytecodeWithConstructor, // Payload of the contract ); // Deploy the contract by the Universal Profile // https://docs.lukso.tech/contracts/contracts/ERC725/#execute const tx = await universalProfile.execute( 1, // Operation type: CREATE ethers.ZeroAddress, // Target: 0x0000...0000 as contract will be initialized 0, // Value is empty tokenBytecodeWithConstructor, // Payload of the contract ); // Wait for the transaction to be included in a block await tx.wait(); console.log('🪙 Token contract deployed by 🆙 at: ', customTokenAddress); ``` --- --- sidebar_label: 'Interact with Contracts' sidebar_position: 3 description: This guide shows how to interact with any smart contracts programmatically from a dApp using the UP Browser Extension and ethers.js (or web3.js). --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Interact with other contracts

Examples of interacting with contracts, like minting tokens or refining burntpix.

In this guide, you will learn how to use your Universal Profile to interact with any other smart contract. You will see from the examples below that **there is no difference with writing the code for interacting with regular EOA-based wallet _vs_ using Universal Profile**. The code is the same! Simply: 1. create an instance of the contract you want to interact with. 2. call the function you want on this contract. 3. use the 🆙 address as `{ from: "0x..." }` in the transaction options. ## Setup To complete this guide, we will need some initial constants values and install some dependencies - the address of the contract we want to interact with. - the ABI of the contract we want to interact with. - Either [`web3.js`](https://github.com/web3/web3.js) or [`ethers.js`](https://github.com/ethers-io/ethers.js/) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) ```shell npm install ethers @lukso/lsp-smart-contracts ``` ```shell npm install web3 @lukso/lsp-smart-contracts ``` ## Interactions Examples Below you will find some examples to perform the following: - Mint a free NFT and see it appear in your wallet on [_universalprofile.cloud_](https://my.universalprofile.cloud). - Execute a swap on UniversalSwap.io - Refine a BurntPix ### Example 1 - Mint some Tokens

```typescript title="mintTokens.ts" import { ethers } from 'ethers'; import LSP7Mintable from '@lukso/lsp-smart-contracts/artifacts/LSP7Mintable.json'; const TOKEN_CONTRACT_ADDRESS = '0x...'; await ethers.provider.send('eth_requestAccounts', []); const universalProfile = await ethers.getSigner(); const myToken = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, LSP7Mintable.abi); const mintTxn = await myToken.mint( universalProfile.address, // recipient address ethers.parseUnits('100', 'ether'), // token amount (mint 100 tokens) true, // force parameter '0x', // additional data { from: universalProfile, }, ); console.log(mintTxn); const balance = await myToken.balanceOf(signer.address); console.log('🏦 Balance: ', balance.toString()); ``` ```typescript title="mintTokens.ts" import Web3 from 'web3'; import LSP7Mintable from '@lukso/lsp-smart-contracts/artifacts/LSP7Mintable.json'; const web3 = new Web3(window.lukso); await web3.eth.requestAccounts(); const accounts = await web3.eth.getAccounts(); const universalProfile = accounts[0]; const myToken = new web3.eth.Contract( LSP7Mintable.abi, '0x6E872Eb9942db637cd82ad7C33C2206eACB81181', // Token contract address ); const mintTxn = await myToken.methods .mint( universalProfile, // recipient address web3.utils.toWei('100', 'ether'), // token amount (mint 100 tokens) true, // force parameter '0x', // additional data ) .send({ from: universalProfile }); console.log(mintTxn); const balance = await myToken.methods.balanceOf(accounts[0]); console.log('🏦 Balance: ', balance.toString()); ``` ### Example 2 - Refine a BurntPix

```typescript title="refineBurntPix.ts" import { ethers } from 'ethers'; // Constants: // - BurntPix Registry contract to interact with const BURNT_PIX_REGISTRY_ADDRESS = "0x3983151E0442906000DAb83c8b1cF3f2D2535F82"; // - bytes32 ID of the BurntPix to refine const BURNT_PIX_ID "0x0000000000000000000000000a3c1ed77de72af03acfaeab282a06e6fbeed5a8"; // 1. Connect to UP Browser Extension const provider = new ethers.BrowserProvider(window.lukso); const accounts = await provider.send('eth_requestAccounts', []); const universalProfile = accounts[0]; // 2. Create an instance of the BurntPix Registry contract const burntPixRegistry = new ethers.Contract( BURNT_PIX_REGISTRY_ADDRESS, ["function refine(bytes32 tokenId, uint256 iterations) external"] ); // Perform 500 iteration to refine a specific Burnt Pix await contract.refine(BURNT_PIX_ID, "500", { from: universalProfile, gasPrice: ethers.formatUnits("1", 'gwei'), gasLimit: 15_000_000, }); ``` ```typescript title="refineBurntPix.ts" import Web3 from 'web3'; // 1. Connect to UP Browser Extension const provider = new Web3(window.lukso); const accounts = await provider.eth.requestAccounts(); const universalProfile = accounts[0]; // 2. Create an instance of the BurntPix Registry contract const burntPixRegistry = new web3.eth.Contract(BURNT_PIX_REGISTRY_ADDRESS, [ refineFunctionABI, ]); // Perform 500 iteration to refine a specific Burnt Pix await contract.methods.refine(BURNT_PIX_ID, '500').send({ from: universalProfile, gasPrice: web3.utils.fromWei('1000000000', 'gwei'), gasLimit: 15_000_000, }); ``` --- --- sidebar_label: 'Transfer LYX' sidebar_position: 1 description: Learn how to write a simple dApp code to transfer LYX from your Universal Profile Browser Extension programmatically. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Transfer LYX

Transferring 0.5 LYXt between two Universal Profiles.

:::info The full code of this example can be found in the 👾 [lukso-playground](https://github.com/lukso-network/lukso-playground/tree/main/dapps/transfer-lyx) repository. ::: The 🆙 [Universal Profile Extension](https://chrome.google.com/webstore/detail/universal-profiles/abpickdkkbnbcoepogfhkhennhfhehfn) magically wraps all the calls internally so you don't have to craft custom transactions. This makes it easy to send transaction like LYX transfer (= native token transfers). Simply use [`eth_sendTransaction`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction) as you always did while working with wallets and smart accounts that used EOAs. No need to make contract calls to instruct the smart contract of the Universal Profile what to do. The Browser Extension handles all of that behind the scene for you! ## Setup Dependencies ```shell npm install ethers ``` ```shell npm install web3@v1 ``` ## Code Examples ```js import { ethers } from 'ethers'; const provider = new ethers.BrowserProvider(window.lukso); await provider.send('eth_requestAccounts', []); const signer = await provider.getSigner(); const account = await signer.getAddress(); // Send transaction const tx = await signer.sendTransaction({ from: account, // The Universal Profile address to: '0x...', // Receiving address, can be a UP or EOA value: ethers.parseEther('0.5'), // 0.5 amount in ETH, in wei unit }); ``` ```js import Web3 from 'web3'; const web3 = new Web3(window.lukso); await web3.eth.requestAccounts(); const accounts = await web3.eth.getAccounts(); await web3.eth.sendTransaction({ from: accounts[0], // The Universal Profile address to: '0x...', // receiving address, can be a UP or EOA value: web3.utils.toWei('0.5', 'ether'), // 0.5 amount in ETH, in wei unit }); ``` --- --- sidebar_label: 'Transfer Tokens & NFTs' sidebar_position: 2 description: Learn how to transfer LSP7 tokens and LSP8 individual NFT tokenIds from a Universal Profile to any address on the LUKSO Blockchain, using the UP Browser Extension. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Transfer Tokens & NFTs

Transferring 1,000 CHILL tokens between two Universal Profiles.

:::info The full code of this example can be found in the 👾 [lukso-playground](https://github.com/lukso-network/lukso-playground/tree/main/dapps/digital-assets). ::: This guide will teach you how to transfer [LSP7 tokens](/standards/tokens/LSP7-Digital-Asset.md) or [LSP8 NFTs](/standards/tokens/LSP8-Identifiable-Digital-Asset.md) from a [Universal Profile](/standards/accounts/lsp0-erc725account.md) to any address. ## Setup Dependencies You will need the following libraries to do this tutorial: - [`ethers.js`](https://github.com/ethers-io/ethers.js/) or [`web3.js`](https://www.npmjs.com/package/web3) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) ```shell npm install ethers @lukso/lsp-smart-contracts ``` ```shell npm install web3 @lukso/lsp-smart-contracts ``` ## Examples First, create an instance of the LSP7 or LSP8 contract. You will need: - the `address` of the LSP7 or LSP8 Token contract you want to transfer tokens / NFT from. - one of the following smart contract ABI from the `@lukso/lsp-smart-contracts` package: - `LSP7DigitalAsset` if you want to transfer tokens. - `LSP8IdentifiableDigitalAsset` if you want to transfer an NFT from the collection. ### Transfer LSP7 tokens Call the [LSP7 `transfer(address,address,uint256,bool,bytes)`](/contracts/contracts/LSP7DigitalAsset/#transfer) function and pass the amount as 3rd parameter. > Since most tokens have 18 [`decimals()`](/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#decimals), make sure to specify the `amount` with 18 decimals place. For instance, if you want to transfer 8 tokens the `amount` parameter will be: `8_000_000_000_000_000_000` ✅, not `8` ❌. > Otherwise, the transfer might have occurred but you might not see the balance of the recipient updated, since you transferred only a tiny small amount (`8` for a token with 18 decimals is basically 1 / 1e18). To do so easily, use one of number utility function from _ethers.js_ or _web3.js_. ```js import { ethers } from 'ethers'; // Import the LSP7 ABI import LSP7DigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; // Connect to the UP Browser extension const provider = new ethers.BrowserProvider(window.lukso); await provider.send('eth_requestAccounts', []); const signer = await provider.getSigner(); // Create instance of the CHILL token contract const chillToken = new ethers.Contract( '0x5b8b0e44d4719f8a328470dccd3746bfc73d6b14', // Chillwhale Token contract address LSP7DigitalAsset.abi, ); await chillToken.transfer( signer.getAddress(), // (from) sender address (= our Universal Profile) '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address ethers.parseUnits('15', 18), // (amount) of tokens to transfer (CHILL have 18 decimals) true, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) '0x', // (data) any additional data to send alongside the transfer ); ``` ```js import Web3 from 'web3'; // Import the LSP7 ABI import LSP7DigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; // Connect to the UP Browser extension const web3 = new Web3(window.lukso); await web3.eth.requestAccounts(); const accounts = await web3.eth.getAccounts(); // Create instance of the CHILL token contract const chillToken = new web3.eth.Contract( LSP7DigitalAsset.abi, '0x5b8b0e44d4719f8a328470dccd3746bfc73d6b14', // Chillwhale Token contract address ); await chillToken.methods .transfer( accounts[0], // (from) sender address (= our Universal Profile) '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address web3.utils.toWei('15'), // (amount) of tokens to transfer (CHILL have 18 decimals) false, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) '0x', // (data) any additional data to send alongside the transfer ) .send({ from: accounts[0] }); ``` :::info Notes on decimals If you are transferring LSP7 tokens with `0` as [`decimals()`](/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#decimals) or NFTs represented as LSP7 with [TokenType 1](/standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokentype), just pass the amount as a number without using the number formatting function. Here is an example to transfer 2 x digital trading cards from the **LUKSO Family Game** (series LFG03): ```ts // Create instance of the LUKSO Family Game (LFG03) token contract const luksoFamilyGameSeries03 = new ethers.Contract( '0x6a58a1f2cbb5b39d90618736a7730bff0fa72801', // LUKSO Family Game (LFG03) contract address LSP7DigitalAsset.abi, ); await luksoFamilyGameSeries03.transfer( signer.getAddress(), // (from) sender address (= our Universal Profile) '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address 2, // (amount) of tokens to transfer (LFG03 token contract has 0 decimals) true, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) '0x', // (data) any additional data to send alongside the transfer ); ``` ::: ### Transfer LSP8 NFTs Call the [LSP8 `transfer(address,address,bytes32,bool,bytes)`](/contracts/contracts/LSP8IdentifiableDigitalAsset/#transfer) function and pass the `tokenId` of the NFT from the collection you want to transfer as 3rd parameter. Make sure you specify the **_tokenId_ as a 32 bytes long value**, as shown in the code snippet below. ```js import { ethers } from 'ethers'; // Import the LSP8 ABI import LSP8IdentifiableDigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; // Connect to the UP Browser extension const provider = new ethers.BrowserProvider(window.lukso); await provider.send('eth_requestAccounts', []); const signer = await provider.getSigner(); // Create instance of the Chillwhale NFT collection contract const chillwhaleNft = new ethers.Contract( '0x86e817172b5c07f7036bf8aa46e2db9063743a83', // Chillwhale NFT collection contract address LSP8IdentifiableDigitalAsset.abi, ); // Create the bytes32 representation of the tokenId number 319 (2nd param right pad to 32 bytes) const tokenId = ethers.toBeHex(319, 32); await chillwhaleNft.transfer( signer.getAddress(), // (from) sender address (= our Universal Profile) '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address tokenId, // (tokenId) of the NFT to transfer true, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) '0x', // (data) any additional data to send alongside the transfer ); ``` ```js import Web3 from 'web3'; // Import the LSP8 ABI import LSP8IdentifiableDigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; // Connect to the UP Browser extension const web3 = new Web3(window.lukso); await web3.eth.requestAccounts(); const accounts = await web3.eth.getAccounts(); // Create instance of the Chillwhale NFT collection contract const chillwhaleNft = new web3.eth.Contract( LSP8IdentifiableDigitalAsset.abi, '0x86e817172b5c07f7036bf8aa46e2db9063743a83', // Chillwhale NFT collection contract address ); // Create the bytes32 representation of the tokenId number 319 (2nd param right pad to 32 bytes - web3.js expect to specify in character counts, not bytes) const tokenId = web3.utils.padLeft(319, 64); await chillwhaleNft.methods .transfer( accounts[0], // (from) sender address (= our Universal Profile) '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address tokenId, // (tokenId) of the NFT to transfer false, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) '0x', // (data) any additional data to send alongside the transfer ) .send({ from: accounts[0] }); ``` --- --- sidebar_label: 'Execute Relay Transactions' sidebar_position: 3 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Execute Relay Transactions In this guide, you will learn how to sign and execute **gas-less transactions**. Such transaction can be executed by any trusted third party who will pay for the gas on behalf of the user (= address) who signed the transaction. As an example for this guide, the transaction that will be executed without requiring to pay for gas will be a LYX transfer. ## What are Relay Transactions? The [LSP6 KeyManager](/standards/access-control/lsp6-key-manager.md) standard empowers any user to execute a transaction on behalf of a [Universal Profile](/standards/accounts/introduction.md), provided they possess a valid transaction signed by a key that controls the Universal Profile. This capability significantly enhances the user's control and flexibility in managing their transactions. Relayed execution enables the creation of [Transaction Relayer Services](/standards/accounts/lsp15-transaction-relayer-api.md), which can execute transactions on behalf of users, _without having any control over their Universal Profile_. Relayers abstract away the gas from users. Another example use case would be Alice sending an encoded transaction that updates the LSP3Profile picture of her Universal Profile to a second user, Bob, who executes the transaction and pays the gas cost on behalf of Alice. :::success Did you know? Users who created their 🆙 via [_universalprofile.cloud_](https://universalprofile.cloud) **benefit from a monthly gas quota paid by LUKSO**. ⛽️ ✅ This aims to help onboard new users to web3! 💪🏻 ::: :::info Execution Rights To execute relay calls, the address [signing the relay transaction](/standards/access-control/lsp6-key-manager#how-to-sign-relay-transactions) need the [`EXECUTE_RELAY_CALL`](/standards/access-control/lsp6-key-manager/#permissions) permission. ::: ## Setup You will need the following dependencies to follow this guide: - [`ethers.js`](https://github.com/ethers-io/ethers.js/) or [`web3.js`](https://github.com/web3/web3.js). - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) package to get the artifacts of the [LSP contracts](/standards/introduction.md). - [`@lukso/eip191-signer.js`](https://github.com/lukso-network/tools-eip191-signer) library to sign the relay transaction. ```shell npm install ethers @lukso/lsp-smart-contracts @lukso/eip191-signer.js ``` ```shell npm install web3 @lukso/lsp-smart-contracts @lukso/eip191-signer.js ``` ## Step 1 - Prepare the contact instances First, create an instance of the [Universal Profile](/standards/accounts/lsp0-erc725account.md) contract (at the defined address) and its [Key Manager](/standards/access-control/lsp6-key-manager.md). The Key Manager's address can be obtained by calling the [`owner()`](/contracts/contracts/UniversalProfile/UniversalProfile.md#owner) function on the Universal Profile. ```typescript import { ethers } from 'ethers'; import UniversalProfileContract from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import KeyManagerContract from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); // Setup the contract instance of the Universal Profile const universalProfile = new ethers.Contract( '0x...', // Universal Profile address UniversalProfileContract.abi, controllerAddress, // controller address with permissions on the Universal Profile ); // Call the Universal Profile contract to get the Key Manager const keyManagerAddress = await universalProfile.owner(); // Setup the contract instance of the Key Manager const keyManager = new ethers.Contract( keyManagerAddress, KeyManagerContract.abi, controllerAddress, ); ``` ```typescript import Web3 from 'web3'; import UniversalProfileContract from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import KeyManagerContract from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const universalProfileAddress = ; // Setup the contract instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfileContract.abi, '0x...', // Universal Profile address ); // Call the Universal Profile contract to get the Key Manager const keyManagerAddress = await universalProfile.methods.owner().call(); // Setup the contract instance of the Key Manager const keyManager = new web3.eth.Contract( KeyManagerContract.abi, keyManagerAddress, ); ``` ## Step 2 - Prepare & Sign the Relay Call :::info This logic must be implemented _client-side_ and sent to the _Transaction Relay Service_ (for instance via API). ::: ### 2.1 - Encode the calldata We need to define what the Universal Profile will execute. As mentioned in the introduction, this guide will use as an example of a transaction a [**LYX transfer from the Universal Profile**](/learn/universal-profile/interactions/transfer-lyx.md). The first step will therefore be to ABI-encode an [`execute(...)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#execute) function call to transfer some LYX to an address. ```ts // Generate the payload of the transaction const abiPayload = universalProfile.interface.encodeFunctionData('execute', [ 0, // Operation type: CALL '0xcafecafecafecafecafecafecafecafecafecafe', // Recipient ethers.parseEther('3'), // transfer 3 LYX to recipient '0x', // Optional transaction data ]); ``` ```ts // Generate the payload of the transaction const abiPayload = universalProfile.methods .execute( 0, // Operation type: CALL '0xcafecafecafecafecafecafecafecafecafecafe', // Recipient web3.utils.toWei(3), // Transfer 3 LYX to recipient '0x', // Optional transaction data ) .encodeABI(); ``` ### 2.2 - Prepare the parameters For the transaction to be executed by a third party, we need to prepare the [`executeRelayCall`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#executerelaycall) function parameters. ```solidity function executeRelayCall( bytes signature, uint256 nonce, uint256 validityTimestamps, bytes payload ) external payable returns (bytes); ``` | Parameter | | | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `nonce` | The nonce of the address (= controller) that will sign the `executeRelayCall`. Retrieved via [`getNonce`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#getnonce) on the [Key Manager](/standards/access-control/lsp6-key-manager.md) | | `channelId` | The channel where the call will be registered after execution. Define to execute the call either in parallel (across different channels) of other relay calls, or require it to be executed after another call.

📓 See [**"Out of order execution"**](/standards/access-control/lsp6-key-manager.md#out-of-order-execution) for more details | | `validityTimestamp` | Define the time interval during which the payload can be executed. Use a value of `0` to make the transaction always valid for an undefinite period of time.

📓 See section [**Contracts > Execute Relay Calls > Validity Timestamps**](/contracts/overview/ExecuteRelayCall.md#validity-timestamps) for more details. | | `payload` | The actual function being called (as an abi-encoded calldata from [**step 2**](#step-2---encode-the-calldata)) on the Universal Profile contract. In this example, the transaction payload will be a basic LYX transfer. | ```typescript // initiate contract instances from Step 2 const channelId = 0; // Retrieve the nonce of the EOA controller const nonce = await keyManager.getNonce(controllerAccount.address, channelId); const validityTimestamps = 0; // No validity timestamp set const msgValue = 0; // Amount of native tokens to fund the UP with while calling // Generate the payload of the transaction const abiPayload = universalProfile.interface.encodeFunctionData('execute', [ 0, // Operation type: CALL '0xcafecafecafecafecafecafecafecafecafecafe', // Recipient ethers.parseEther('3'), // transfer 3 LYX to recipient '0x', // Optional transaction data ]); ``` ```typescript // initiate contract instances from Step 2 const channelId = 0; // Retrieve the nonce of the EOA controller const nonce = await keyManager.methods .getNonce(controllerAccount.address, channelId) .call(); const validityTimestamps = 0; // No validity timestamp set const msgValue = 0; // Amount of native tokens to fund the UP with while calling // Generate the payload of the transaction const abiPayload = universalProfile.methods .execute( 0, // Operation type: CALL '0xcafecafecafecafecafecafecafecafecafecafe', // Recipient web3.utils.toWei(3), // Transfer 3 LYX to recipient '0x', // Optional transaction data ) .encodeABI(); ``` ### 3.2 - Sign with LSP25 Sig Format :::tip Signature Details For more information regarding the construction of an LSP25 signature, see [**"Signing Relay Transactions"**](/standards/access-control/lsp6-key-manager.md#how-to-sign-relay-transactions). ::: The next step for the client side is to sign the transaction message. This is done using the private key of a controller that has some permission on the Universal Profile to execute the transaction on, without needing us to pay for the gas. To do that, we will use our convenience library [_eip191-signer_](/tools/dapps/eip191-signerjs/getting-started.md) which make the signing for us. The transaction message is constructed by encoding and signing the following: - Version of the [LSP25 standard](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-25-ExecuteRelayCall.md) (`LSP25_VERSION`). - Address of the Key Manager (`keyManagerAddress`). - Identifier of the blockchain network (`chainId`). - Current nonce of the signing EOA controller (`nonce`). - The transaction validity timestamp (`validityTimestamps`). - Amount of native tokens to fund the UP with while calling (`msgValue`). - The ABI Payload of operations that will be executed (`abiPayload`). :::danger Caution when using your controller's private key Never share your private controller key or upload it to public repositories. Anyone who possesses it can access your funds and assets and gain control over your Universal Profile in case the controller has administrative rights! ::: ```typescript //... // Get the network ID const { chainId } = await provider.getNetwork(); // Encode the Message const encodedMessage = ethers.solidityPacked( // Types of the parameters that will be encoded ['uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'bytes'], [ // MUST be number `25` // Encoded value: `0x0000000000000000000000000000000000000000000000000000000000000019` LSP25_VERSION, // e.g: `4201` for LUKSO Testnet // Encoded value: `0x0000000000000000000000000000000000000000000000000000000000001069` chainId, // e.g: nonce number 5 of the signing controller that wants to execute the payload // Encoded value: `0x0000000000000000000000000000000000000000000000000000000000000005` nonce, // e.g: valid until 1st January 2025 at midnight (GMT). // Timestamp = 1735689600 // Encoded value: `0x0000000000000000000000000000000000000000000000000000000067748580` validityTimestamps, // e.g: not funding the contract with any LYX (0) // Encoded value: `0x0000000000000000000000000000000000000000000000000000000000000000` msgValue, // e.g: send 3 LYX to address 0xcafecafecafecafecafecafecafecafecafecafe // by calling execute(uint256,address,uint256,bytes) // Encoded value: `0x44c028fe00000000000000000000000000000000000000000000000000000000 // 00000000000000000000000000000000cafecafecafecafecafecafecafecafeca // fecafecafecafe00000000000000000000000000000000000000000000000029a2 // 241af62c0000000000000000000000000000000000000000000000000000000000 // 000000008000000000000000000000000000000000000000000000000000000000 // 00000000` abiPayload, ], ); // Instantiate EIP191 Signer const eip191Signer = new EIP191Signer(); const { signature } = await eip191Signer.signDataWithIntendedValidator( keyManagerAddress, encodedMessage, '0xxxxxxxxx...xxxxxxxx', // controller / signer private key (65 bytes long) ); ``` :::danger Caution when using your controller's private key Never share your private controller key or upload it to public repositories. Anyone who possesses it can access your funds and assets and gain control over your Universal Profile in case the controller has administrative rights! ::: ```typescript // ... // Get the network ID const chainId = await web3.eth.getChainId(); // Encode the Message const encodedMessage = web3.utils.encodePacked( // MUST be number `25` // Encoded value: `0x0000000000000000000000000000000000000000000000000000000000000019` { value: LSP25_VERSION, type: 'uint256' }, // e.g: `4201` for LUKSO Testnet // Encoded value: `0x0000000000000000000000000000000000000000000000000000000000001069` { value: chainId, type: 'uint256' }, // e.g: nonce number 5 of the signing controller that wants to execute the payload // Encoded value: `0x0000000000000000000000000000000000000000000000000000000000000005` { value: nonce, type: 'uint256' }, // e.g: not funding the contract with any LYX (0) // Encoded value: `0x0000000000000000000000000000000000000000000000000000000000000000` { value: validityTimestamps, type: 'uint256' }, // e.g: not funding the contract with any LYX (0) // Encoded value: `0x0000000000000000000000000000000000000000000000000000000000000000` { value: msgValue, type: 'uint256' }, // e.g: send 3 LYX to address 0xcafecafecafecafecafecafecafecafecafecafe // by calling execute(uint256,address,uint256,bytes) // Encoded value: `0x44c028fe00000000000000000000000000000000000000000000000000000000 // 00000000000000000000000000000000cafecafecafecafecafecafecafecafeca // fecafecafecafe00000000000000000000000000000000000000000000000029a2 // 241af62c0000000000000000000000000000000000000000000000000000000000 // 000000008000000000000000000000000000000000000000000000000000000000 // 00000000` { value: abiPayload, type: 'bytes' }, ); // Instantiate EIP191 Signer const eip191Signer = new EIP191Signer(); const { signature } = await eip191Signer.signDataWithIntendedValidator( keyManagerAddress, encodedMessage, '0xxxxxxxxx...xxxxxxxx', // controller / signer private key (65 bytes long) ); ``` After the signature has been generated, it can be sent to the third party to be executed on the network. We will cover this in the last section [**"Step 3 - Execute the Relay Call"**](#step-4---execute-the-relay-call). ## Step 3 - Execute the Relay Call :::info This logic must be implemented on the _relayer-side_ where the transaction will be sent to the network to be executed. ::: :::info Function Documentation You can find more information about `executeRelayCall` within the [LSP6 Contract Documentation](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#executerelaycall) . ::: To execute a previously signed transaction, the relayer will need all the following information: - `signature` generated in **step 2.3**. - `nonce` of the signing controller. - `validityTimestamps` of the transaction. - `abiPayload` as abi-encoded function call to execute on the 🆙. - `keyManagerAddress` associated with the Universal Profile we want to execute on. The relayer can now call the [`executeRelayCall`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#executerelaycall) function on the Key Manager (`keyManagerAddress`) of the profile, passing all these information as function arguments. ```javascript import { ethers } from 'ethers'; import KeyManagerContract from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); /** * Prepare received parameters: * keyManagerAddress, signature, nonce * validityTimestamps, abiPayload */ // Setup the Universal Profile controller account const relayControllerPrivateKey = '0x...'; const relayControllerAccount = new ethers.Wallet(controllerPrivateKey).connect( provider, ); // Setup the contract instance of the Key Manager const keyManager = new ethers.Contract( keyManagerAddress, KeyManagerContract.abi, relayControllerAccount, ); const executeRelayCallTransaction = await keyManager .connect(relayControllerAccount) .executeRelayCall(signature, nonce, validityTimestamps, abiPayload); const receipt = await executeRelayCallTransaction.wait(); console.log('Transaction receipt:', receipt); ``` ```javascript import Web3 from 'web3'; import KeyManagerContract from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; const web3 = new Web3('https://rpc.testnet.lukso.network'); /** * Prepare received parameters: * keyManagerAddress, signature, nonce * validityTimestamps, abiPayload */ // Setup your controller account executing the transaction const relayControllerPrivateKey = '0x...'; const relayControllerAccount = web3.eth.accounts.wallet.add(controllerPrivateKey); // Setup the contract instance of the Key Manager const keyManager = new web3.eth.Contract( KeyManagerContract.abi, keyManagerAddress, ); const executeRelayCallTransaction = await keyManager.methods .executeRelayCall(signature, nonce, validityTimestamps, abiPayload) .send({ from: relayControllerAccount.address, gasLimit: 300_000, }); const receipt = await executeRelayCallTransaction.wait(); console.log('Transaction receipt:', receipt); ``` --- --- sidebar_label: 'Get List of Controllers' sidebar_position: 1 description: Learn how to retrieve the list of controller addresses and their associated permissions from a Universal Profile on LUKSO. --- import CodeSandbox from "@site/src/components/CodeSandbox"; import ERC725 from '@site/static/img/tools/erc725-tools.png'; # Get List of Permissioned Addresses This guide shows how to retrieve the list of addresses that have some permissions on a Universal Profile. We commonly call these addresses **controllers**. :::tip Code repository You can find the scripts of this guide within our [`lukso-playground`](https://github.com/lukso-network/lukso-playground) repository. ::: Alongside each controller, we will also retrieve their associated permissions. All of this will involve 3 steps: 1. **retrieve all controller addresses** of a Universal Profile. 2. **retrieve the encoded permissions** of each controller. 3. **decode these permissions** in a human readable way :::tip ERC725 Inspect [ERC725 Inspect Tool](https://erc725-inspect.lukso.tech/?network=lukso+mainnet) allows you get all controllers of a Universal Profile under the `AddressPermissions[]` section. ::: ## Setup We will use the [`erc725.js`](/tools/dapps/erc725js/getting-started.md) library to easily query and decode the [`AddressPermissions[]`](/standards/access-control/lsp6-key-manager.md#retrieving-list-of-controllers) and [`AddressPermissions:Permissions:`](/standards/access-control/lsp6-key-manager.md#address-permissions) data keys on the Universal Profile. ```bash npm install @erc725/erc725.js ``` ## Step 1 - Instantiate erc725.js First let's initialize _erc725.js_ and connect it to a specific Universal Profile address on LUKSO Testnet. This will enable us to query its storage easily. ```js title="Create an instance of erc725.js connected to a 🆙" import { ERC725 } from '@erc725/erc725.js'; // This contains the schemas of the data keys: // - AddressPermissions[] -> list of controllers // - `AddressPermission:Permissions: -> permission of a specific controller import LSP6Schema from '@erc725/erc725.js/schemas/LSP6KeyManager.json'; // Sample Profile Address const UNIVERSAL_PROFILE = '0xEda145b45f76EDB44F112B0d46654044E7B8F319'; // Instantiate erc725.js with a Universal Profile address on Testnet const erc725 = new ERC725( LSP6Schema, UNIVERSAL_PROFILE, 'https://rpc.testnet.lukso.network', ); ``` ## Step 2 - Get the list of controllers You can now simply query the [`AddressPermissions[]`](/standards/access-control/lsp6-key-manager.md#retrieving-addresses-with-permissions) data key with the [`getData('AddressPermissions[]')`](/tools/dapps/erc725js/methods.md#getdata) function from _erc725.js_. This will return you an array of addresses. ```js title="Retrieve the list of addresses that have some permissions on the 🆙." async function getPermissionedAddresses() { // Get the list of addresses that have permissions on the Universal Profile const controllerAddresses = await erc725.getData('AddressPermissions[]'); if (!controllerAddresses) { console.log('No controllers listed under this Universal Profile '); } else { console.log(controllerAddresses); // { // key: '0xdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e3', // name: 'AddressPermissions[]', // value: [ // '0x5F606b5b237623463a90F63230F9b929321dbCBa', // '0xa1061408e55c971fD129eF5561dFB953d598dAD7' // ] // } } } ``` ## Step 3 - Get controller's permissions Now that we have all the controller's addresses, You can retrieve the permissions of each individual controller by querying the data key [`AddressPermissions:Permissions:`](/standards/access-control/lsp6-key-manager.md#retrieving-addresses-with-permissions). This involves 2 steps: 1. Get the raw encoded `bytes32` permission for the controller. 2. Decode this permission value to get an object listing which permissions are set or not for this controller. ### 3.1 - Get the encoded permission of the controller. Let's first understand how to query the controller's permission! You will have to replace the `` part with the actual address of the controller. Therefore the data key for the controller address `0xcafecafecafecafecafecafecafecafecafecafe` will look as follow: ```js title="From human readable to smart contract readable permission data key." // human readable `AddressPermissions:Permissions:` // in hex 0x4b80742de2bf82acb3630000 // final data key with actual controller address 0xcafecafe... 0x4b80742de2bf82acb3630000cafecafecafecafecafecafecafecafecafecafe ``` Thankfully, _erc725.js_ manages all this complexity for us! Simply use the `getData(...)` function and pass the controller address as option to the `dynamicKeyPart`. See the code snippet below: ```js title="Fetch the encoded permissions for a controller." async function getPermissionedAddresses() { // ... if (Array.isArray(controllerAddresses.value)) { // Get the permissions of each controller of the UP for (let i = 0; i < controllerAddresses.value.length; i++) { const address = controllerAddresses.value[i] as string; const permissionsValue = await erc725.getData({ keyName: 'AddressPermissions:Permissions:
', dynamicKeyParts: address, }); console.log(permissionsValue); // { // key: '0x4b80742de2bf82acb3630000a1061408e55c971fd129ef5561dfb953d598dad7', // name: 'AddressPermissions:Permissions:a1061408e55c971fD129eF5561dFB953d598dAD7', // value: '0x0000000000000000000000000000000000000000000000000000000000000008' // } } } } ``` ### 3.2 - Decode the permission The `value` above `0x0000...0008` in the object does not give us a lot of information. This is because **permissions are encoded as a [`BitArray`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#BitArray)**. Luckily, we don't need to understand the complexity behind the scene to understand the permissions that are set. After retrieving these encoded permission values, we can use again the [`decodePermissions(...)`](/tools/dapps/erc725js/methods#decodepermissions) function from the [_erc725.js_](/tools/dapps/erc725js/getting-started.md) library to decode them easily. The function returns an object showing which permissions the controller has with `true` or `false`. ```js title="Example of decoded permission value from hex to an object." async function getPermissionedAddresses() { // ... if (Array.isArray(controllerAddresses.value)) { // ... // Decode the permission of each address const decodedPermissions = erc725.decodePermissions(permissionsValue.value as string); // Display the permission in a readable format console.log( `Decoded permission for ${address} = ` + JSON.stringify(decodedPermissions, null, 2), ); // Decoded permission for 0x5F606b5b237623463a90F63230F9b929321dbCBa = { // "CHANGEOWNER": true, // "ADDCONTROLLER": true, // "EDITPERMISSIONS": true, // "ADDEXTENSIONS": true, // "CHANGEEXTENSIONS": true, // "ADDUNIVERSALRECEIVERDELEGATE": true, // "CHANGEUNIVERSALRECEIVERDELEGATE": true, // "REENTRANCY": false, // "SUPER_TRANSFERVALUE": true, // "TRANSFERVALUE": true, // "SUPER_CALL": true, // "CALL": true, // "SUPER_STATICCALL": true, // "STATICCALL": true, // "SUPER_DELEGATECALL": false, // "DELEGATECALL": false, // "DEPLOY": true, // "SUPER_SETDATA": true, // "SETDATA": true, // "ENCRYPT": true, // "DECRYPT": true, // "SIGN": true, // } } } getPermissionedAddresses(); ``` --- --- sidebar_label: 'Grant Permissions' sidebar_position: 2 description: Learn how to give some permissions to an address to perform specific actions on a Universal Profile on LUKSO. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Grant Permissions This guide will teach you how to grant [permissions](/standards/access-control/lsp6-key-manager.md#address-permissions) to any address so they can interact with your 🆙. You will learn: - How permissions in the LSP6 Key Manager work + how to create them using [_erc725.js_](/tools/dapps/erc725js/getting-started.md). - How to set permissions for a third party `address` on your Universal Profile :::info Code Examples The full code of this example can be found in the 👾 [lukso-playground](https://github.com/lukso-network/lukso-playground/tree/main/dapps/key-manager) repository. ::: ## Introduction The Key Manager enables to give permissions to any third-party address to perform certain actions on our Universal Profile (UP). This includes editing the UP's metadata, transferring LYX, tokens, and NFTs, and making any other interactions on behalf of the UP. We call such addresses **controllers**, as they can *"control"* a specific Universal Profile according to their permissions on this particular UP. The diagram above shows that when Alice sends a transaction to the [Universal Profile](/standards/accounts/introduction.md), the UP will first call its [Key Manager](/standards/access-control/lsp6-key-manager.md) to verify that Alice is authorised to execute this action by checking its **permissions**. If the check is successful, the transaction gets executed. Otherwise, it reverts. These permissions are stored in the Universal Profile. **We need to update three data keys in the Universal Profile's storage when adding and granting a new controller some permissions**. | :file_cabinet: ERC725Y data key | :page_with_curl: Description | :pen: **What should we update?** | | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------- | | [`AddressPermissions[]`](/standards/access-control/lsp6-key-manager.md#retrieving-addresses-with-permissions) | The number of addresses that have permissions on our UP. | We need to **increment it by +1**. | | [`AddressPermissions[index]`](/standards/access-control/lsp6-key-manager.md#retrieving-addresses-with-permissions) | holds a controller address at a specific index. | We need to **add the beneficiary address at the new index**. | | [`AddressPermissions:Permissions:`](/standards/access-control/lsp6-key-manager.md#address-permissions) | this data key holds the permissions of a controller address. | We need to **add the permissions of the beneficiary address** under this data key. | ## Setup To follow this guide, we will need the following libraries and packages: - [`erc725.js`](/tools/dapps/erc725js/getting-started.md) to encode the permissions - The [`lsp-smart-contracts`](/tools/lsp-smart-contracts/getting-started.md) package to get the [Universal Profile's ABI](/standards/accounts/introduction.md) - `web3.js` or `ethers.js` to interact with our `UniversalProfile` smart contract. ```shell title="Install the dependencies" npm install ethers @erc725/erc725.js @lukso/lsp-smart-contracts ``` ```shell title="Install the dependencies" npm install web3 @erc725/erc725.js @lukso/lsp-smart-contracts ``` ## Step 1 - Initialize erc725.js First initialize _erc725.js_ with the JSON schema of the LSP6 Key Manager. The schema is necessary to create and encode the permissions. ```js import { ERC725 } from '@erc725/erc725.js'; import LSP6Schema from '@erc725/erc725.js/schemas/LSP6KeyManager.json'; // step 1 - initialize erc725.js with the schemas of the permissions data keys from LSP6 Key Manager const erc725 = new ERC725( LSP6Schema, myUniversalProfileAddress, 'https://rpc.testnet.lukso.network', ); ``` ## Step 2 - Encode the permissions data :::success Permissions List More permissions are available in _erc725.js_. See the [`encodePermissions(...)`](/tools/dapps/erc725js/methods.md#encodepermissions) function for a complete list. To learn about what each permission enables, see the [**Standards > LSP6 Key Manager > Permissions**](/standards/access-control/lsp6-key-manager.md#permissions) section. ::: Let's consider in our example that we want to grant the permission `SUPER_SETDATA` to a `beneficiaryAddress`, so that it can edit any of the Universal Profile metadata. To do so, we will use the [`encodePermissions(..)`](/tools/dapps/erc725js/methods#encodepermissions) function, a convenience function from the _erc725.js_ library to encode permissions as their raw `bytes32` value. The function takes as an input will an object of all permissions that will be set. ```ts // Create the raw permissions value to allow an address // to set any data keys (except LSP17 extensions and LSP1 Universal Receiver Delegates) // on our Universal Profile const permissionSetAnyDataKey = erc725.encodePermissions({ SUPER_SETDATA: true, }); ``` If you want to grant more than one permission, simply pass the other available permissions in the object. For instance, to also grant permission to transfer the LYX of the UP: ```ts const multiplePermissions = erc725.encodePermissions({ SUPER_SETDATA: true, TRANSFERVALUE: true, }); ``` As we learnt, permissions of controllers live inside the Universal Profile storage. They are precisely stored inside the `ERC725Y` storage of the UP. Therefore, as per the data structure of ERC725Y, we need to assign the encoded permission and the controller address as **values** to specific data keys. We will do that | 🎯 **Objective** | ✍🏼 **How is this done?** | | :-------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Assign this permission to our `beneficiaryAddress`. | By setting this encoded permission as the value for the data key `AddressPermissions:Permissions:
`, where `
` will be the address of the beneficiary. | | Add our `beneficiaryAddress`. | By adding the `beneficiaryAddress` inside the `AddressPermissions[]` Array, and increment the `AddressPermissions[]` array length (+1). | ```ts title="Encode the data key and values for the permissions" // address to give permissions to (can be an EOA or a smart contract) const newControllerAddress = '0xcafecafecafecafecafecafecafecafecafecafe'; // Retrieve the list of addresses that have permissions on the Universal Profile (= controllers) const addressPermissionsArrayValue = await erc725.getData( 'AddressPermissions[]', ); const numberOfControllers = addressPermissionsArrayValue.value.length; // Encode the set of key-value pairs to set a new controller with permissions on the Universal Profile const permissionData = erc725.encodeData([ // this sets the permission `SUPER_SETDATA` to the new controller address { keyName: 'AddressPermissions:Permissions:
', dynamicKeyParts: beneficiaryAddress, value: beneficiaryPermissions, }, // The `AddressPermissions[]` array contains the list of permissioned addresses (= controllers) // This adds the `newControllerAddress` in this list at the end (at the last index) and increment the array length. { keyName: 'AddressPermissions[]', value: [newControllerAddress], startingIndex: numberOfControllers, totalArrayLength: numberOfControllers + 1, }, ]); ``` ## Step 3 - Set the permissions on the 🆙 We have now all the encoded data needed to setup the permissions of this third party address on our Universal Profile! 💪🏻 The last and final step is to simply call the [`setDataBatch(...)`](/contracts/contracts/UniversalProfile#setdatabatch) function on the `UniversalProfile` contract, passing the data keys and values previously encoded in **step 2**. The steps in the code will be: 1. Create an instance of the Universal Profile smart contract. You will need: - the `UniversalProfile` ABI from the [`@lukso/lsp-smart-contracts`](https://www.npmjs.com/package/@lukso/lsp-smart-contracts) npm package. - the address of the Universal Profile. 2. Call the `setDataBatch(bytes32[],bytes[])` function, passing as the arguments the content obtained from **step 2**. ```ts import { ether } from 'ethers'; import UniversalProfileArtifact from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // Connect the UP Browser Extension and retrieve our UP Address const provider = new ethers.BrowserProvider(window.lukso); const accounts = await provider.send('eth_requestAccounts', []); // Create an instance of the UniversalProfile contract const universalProfile = new ethers.Contract( accounts[0], UniversalProfileArtifact.abi, ); // Send the transaction await myUniversalProfile .connect(accounts[0]) .setData(permissionData.keys, permissionData.values); ``` ```ts import Web3 from 'web3'; import UniversalProfileArtifact from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // Connect the UP Browser Extension and retrieve our UP Address const provider = new Web3(window.lukso); const accounts = await provider.eth.requestAccounts(); // Create an instance of the UniversalProfile contract const myUniversalProfile = new web3.eth.Contract( UniversalProfileArtifact.abi, accounts[0], ); // Send the transaction await myUniversalProfile.methods .setData(permissionData.keys, permissionData.values) .send({ from: accounts[0], }); ``` ## Testing the permissions We can now check that the permissions have been correctly set by querying the `AddressPermissions:Permissions:
` data key on the Universal Profile. If everything went well, the code snippet below should return you an object with the permission `SETDATA` set to `true`. ```ts const result = await myUniversalProfile.getData(permissionData.keys[0]); console.log( `The beneficiary address ${newControllerAddress} has now the following permissions:`, ERC725.decodePermissions(result), ); ``` ```ts const result = await myUniversalProfile.methods .getData(permissionData.keys[0]) .call(); console.log( `The beneficiary address ${newControllerAddress} has now the following permissions:`, ERC725.decodePermissions(result), ); ``` ```ts const result = await erc725.getData({ keyName: 'AddressPermissions:Permissions:
', dynamicKeyParts: newControllerAddress, }); console.log( `The beneficiary address ${newControllerAddress} has now the following permissions:`, ERC725.decodePermissions(result), ); ``` Finally, to test the actual permissions, you can do this guide using a `beneficiaryAddress` that you have control over. You can try the [**Edit Universal Profile**](../metadata/edit-profile.md) guide, using this new 3rd party address that you have control over to test if it can successful edit the profile details. This will give you guarantee that this `beneficiaryAddress` has the `SETDATA` permission working. --- --- title: Adding Custom Data sidebar_label: Adding Custom Data --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; Universal Profiles are powered by **[LSP2](/standards/metadata/lsp2-json-schema.md)**, a standard that allows them to function as generic key-value data stores. Beyond the [predefined data keys](/tools/lsp-smart-contracts/constants) from standards like [LSP3 Profile Metadata](/standards/metadata/lsp3-profile-metadata.md), you can define and set your own completely custom data keys. This is incredibly powerful for dApps, allowing them to store application-specific information directly on a user's profile without needing a centralized database. For instance, a Web3 e-commerce dApp could store a user's preferred apparel sizes, or a gaming dApp could store a player's settings. This guide will walk you through defining a custom data key, creating its associated data, and storing it on a Universal Profile. We will use the example of creating an `ApparelSize` key to store a JSON object with a user's clothing sizes. :::tip Please check out [LSP2 - ERC725Y JSON Schema](/standards/metadata/lsp2-json-schema) to see which properties fits best to your needs. ::: ## Goal By the end of this guide, you will be able to: 1. Define a custom ERC725Y JSON schema for your new data key. 2. Create a JSON file with your custom data and upload it to IPFS. 3. Encode the data according to your custom schema. 4. Set the custom data on your Universal Profile by sending a transaction. ## Prerequisites - You have a Universal Profile address and and exported the private key of your Browser Extension which has permission to modify the profile's data. ### Step 1: Install Dependencies We'll use `erc725.js` to handle schema encoding and a web3 library to interact with the blockchain. ```shell npm install viem @erc725/erc725.js @lukso/lsp-smart-contracts ``` ```shell npm install web3 @erc725/erc725.js @lukso/lsp-smart-contracts ``` ### Step 2: Define a Custom Schema The first step is to define your custom data key. According to the **[LSP2 ERC725YJSONSchema](/standards/metadata/lsp2-json-schema.md)** standard, schemas define the name, `bytes32` key, and value format for a piece of data. Create a file named `MyCustomSchema.json`. For our example, we'll define a key named `ApparelSize`. Its `bytes32` representation is `keccak256('ApparelSize')`. We'll specify that its value will contain bytes data (`String`), which we'll use to store stringified JSON. ```json title="MyCustomSchema.json" { "name": "ApparelSize", "key": "0xcd8932f38e23d65fad0812bc71a809914f4121ede95affc39f8a43a63f660065", "keyType": "Singleton", "valueContent": "String", "valueType": "bytes" } ``` ### Step 3: Prepare Your Data Next, create the JSON object that contains the actual data for your custom key. Since we're storing the data directly on-chain, we don't need to upload it to IPFS. ```json title="apparel-sizes" { "shoeSize": "US 10", "shirtSize": "M", "jacketSize": "L" } ``` This JSON object will be stringified, encoded as a string, and stored directly in your Universal Profile's ERC725Y storage. :::caution Since the data saved to blockchain is public and permanent, please avoid storing sensitive information. ::: ### Step 4: Encode and Set the Custom Data Now, we'll write a script to put all the pieces together. It will: 1. Load your custom schema. 2. Define your JSON data object. 3. Stringify the JSON object and encode it as a string for the `ApparelSize` data key. 4. Send a transaction to your Universal Profile to store the data. Create a file named `set-custom-data.js`: ```javascript title="set-custom-data.js" const { createWalletClient, createPublicClient, http, getContract, encodeFunctionData, } = require('viem'); const { luksoTestnet } = require('viem/chains'); const { privateKeyToAccount } = require('viem/accounts'); const { ERC725 } = require('@erc725/erc725.js'); const MyCustomSchema = require('./MyCustomSchema.json'); const UniversalProfile = require('@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'); const KeyManager = require('@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'); // --- Configuration --- const PRIVATE_KEY = '0x...'; // Your EOA private key with permissions const UP_ADDRESS = '0x...'; // Your Universal Profile address // --------------------- const account = privateKeyToAccount(PRIVATE_KEY); const publicClient = createPublicClient({ chain: luksoTestnet, transport: http('https://rpc.testnet.lukso.network'), }); const walletClient = createWalletClient({ account, chain: luksoTestnet, transport: http('https://rpc.testnet.lukso.network'), }); async function setCustomData() { // 1. Get the UP contract and Key Manager address const upContract = getContract({ address: UP_ADDRESS, abi: UniversalProfile.abi, client: publicClient, }); const keyManagerAddress = await upContract.read.owner(); const keyManagerContract = getContract({ address: keyManagerAddress, abi: KeyManager.abi, client: walletClient, }); // 2. Define the JSON data to store const apparelData = { shoeSize: 'US 10', shirtSize: 'M', jacketSize: 'L', }; // 3. Encode the custom data using your schema const erc725 = new ERC725([MyCustomSchema]); const encodedData = erc725.encodeData([ { keyName: 'ApparelSize', value: JSON.stringify(apparelData), // Pass the JSON string directly }, ]); const key = encodedData.keys[0]; const value = encodedData.values[0]; // 4. Encode the `setData` call to be executed on the UP const setDataCalldata = encodeFunctionData({ abi: UniversalProfile.abi, functionName: 'setData', args: [key, value], }); // 5. Execute via the Key Manager console.log('Setting custom data on Universal Profile...'); const txHash = await keyManagerContract.write.execute([setDataCalldata], { gas: 300_000n, }); console.log('Transaction hash:', txHash); console.log( `Custom data set for profile: https://wallet.universalprofile.cloud/${UP_ADDRESS}`, ); } setCustomData().catch(console.error); ``` ```javascript title="set-custom-data.js" const { Web3 } = require('web3'); const { ERC725 } = require('@erc725/erc725.js'); const MyCustomSchema = require('./MyCustomSchema.json'); const UniversalProfile = require('@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'); const KeyManager = require('@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'); // --- Configuration --- const RPC_ENDPOINT = 'https://rpc.testnet.lukso.network'; const PRIVATE_KEY = '0x...'; // Your EOA private key with permissions const UP_ADDRESS = '0x...'; // Your Universal Profile address // --------------------- const web3 = new Web3(RPC_ENDPOINT); const myAccount = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY); web3.eth.accounts.wallet.add(myAccount); web3.eth.defaultAccount = myAccount.address; async function setCustomData() { // 1. Fetch the UP's Key Manager address const upContract = new web3.eth.Contract(UniversalProfile.abi, UP_ADDRESS); const keyManagerAddress = await upContract.methods.owner().call(); const keyManager = new web3.eth.Contract(KeyManager.abi, keyManagerAddress); // 2. Define the JSON data to store const apparelData = { shoeSize: 'US 10', shirtSize: 'M', jacketSize: 'L', }; // 3. Encode the custom data using your schema const erc725 = new ERC725([MyCustomSchema]); const encodedData = erc725.encodeData([ { keyName: 'ApparelSize', value: JSON.stringify(apparelData), // Stringify the JSON object }, ]); const key = encodedData.keys[0]; const value = encodedData.values[0]; // 4. Construct the `setData` call to be executed on the UP const setDataPayload = upContract.methods.setData(key, value).encodeABI(); // 5. Execute via the Key Manager console.log('Setting custom data on Universal Profile...'); const receipt = await keyManager.methods.execute(setDataPayload).send({ from: myAccount.address, gas: 300_000, }); console.log('Transaction successful! Receipt:', receipt); console.log( `Custom data set for profile: https://wallet.universalprofile.cloud/${UP_ADDRESS}`, ); } setCustomData().catch(console.error); ``` Before running, replace the placeholder values for `PRIVATE_KEY` and `UP_ADDRESS`. :::info Chain Configuration Note that Viem requires explicit chain definitions. We use `luksoTestnet` from `viem/chains`. For mainnet, you would use `lukso` instead. ::: Then, run the script: ```shell node set-custom-data.js ``` ### Step 5: Verify the Custom Data :::success 💡 Tips You can use the [ERC725 Inspect tool](https://erc725-inspect.lukso.tech/inspector?network=lukso+mainnet) to easily retrieve the custom metadata set on your 🆙: 1. Go to the [🔍 inspector page](https://erc725-inspect.lukso.tech/inspector?network=lukso+mainnet). 2. Paste your **Universal Profile address** in the search field 3. Paste the custom schema we defined in **[MyCustomSchema.json](#step-2-define-a-custom-schema)** (or the custom schema you created) in the Custom Key Reading section. 4. Click the **Get Data** button The tool will retrieve the decoded data for you according to the custom schema! ::: You can also verify that your custom data has been set by reading it directly from your Universal Profile. This script requires your custom schema to decode the on-chain data correctly. Create `get-custom-data.js`: ```javascript title="get-custom-data.js" const { createPublicClient, http } = require('viem'); const { luksoTestnet } = require('viem/chains'); const { ERC725 } = require('@erc725/erc725.js'); const MyCustomSchema = require('./MyCustomSchema.json'); const UP_ADDRESS = '0x...'; // Your Universal Profile address const publicClient = createPublicClient({ chain: luksoTestnet, transport: http('https://rpc.testnet.lukso.network'), }); const erc725 = new ERC725([MyCustomSchema], UP_ADDRESS, publicClient, {}); async function getCustomData() { const customData = await erc725.getData('ApparelSize'); console.log('Custom "ApparelSize" data:', customData.value); // Parse the JSON string back to an object const parsedData = JSON.parse(customData.value); console.log('Parsed JSON Content:', parsedData); } getCustomData().catch(console.error); ``` ```javascript title="get-custom-data.js" const { ERC725 } = require('@erc725/erc725.js'); const MyCustomSchema = require('./MyCustomSchema.json'); const RPC_ENDPOINT = 'https://rpc.testnet.lukso.network'; const UP_ADDRESS = '0x...'; // Your Universal Profile address const erc725 = new ERC725([MyCustomSchema], UP_ADDRESS, RPC_ENDPOINT, {}); async function getCustomData() { const customData = await erc725.getData('ApparelSize'); console.log('Custom "ApparelSize" data:', customData.value); // Parse the JSON string back to an object const parsedData = JSON.parse(customData.value); console.log('Parsed JSON Content:', parsedData); } getCustomData().catch(console.error); ``` Run this script to see the decoded `ApparelSize` data from your Universal Profile. Since we're storing the data as a string on-chain, `erc725.js` returns the stringified JSON, which we then parse back to the original object. ## Use Cases Storing custom data on Universal Profiles opens up numerous possibilities for dApps and mini-apps: - **E-commerce**: Store customer preferences, sizes, purchase history - **Gaming**: Store player stats, achievements, game preferences - **Education**: Store certifications, course progress, learning preferences Your custom data keys can be as simple or complex as needed, and you can define multiple schemas for different types of data within the same Universal Profile. The key is to design your schema thoughtfully and consistently so that your dApp and others can reliably read and interact with the data. --- --- sidebar_label: 'Edit Profile Data' sidebar_position: 2 description: Learn how to edit the LSP3Profile Metadata of a Universal Profile using viem + wagmi, ethers.js, or web3.js. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Edit a Universal Profile This guide will teach you how to **customize your Universal Profile** programmatically in JavaScript and includes: - adding a profile and cover picture to your Universal Profile, - editing your Universal Profile infos (e.g., description, badges, links), - see the updated profile details and images on [universaleverything.io](https://universaleverything.io). To achieve this goal, we will perform the following steps: 1. Create a JSON file that contains your profile details (`LSP3Profile` metadata). 2. Upload this JSON file to [IPFS](https://ipfs.io/) using our [tools-data-providers](https://github.com/lukso-network/tools-data-providers) library. 3. Encode the metadata as a [VerifiableURI](/standards/metadata/lsp2-json-schema.md#verifiableuri) using [erc725.js](/tools/dapps/erc725js/getting-started.md). 4. Set the encoded data on your Universal Profile via `setData(bytes32,bytes)`. ## Install the dependencies ```shell npm install wagmi viem@2.x @tanstack/react-query @erc725/erc725.js @lukso/lsp-smart-contracts @lukso/data-provider-ipfs-http-client ``` ```shell npm install ethers @erc725/erc725.js @lukso/lsp-smart-contracts @lukso/data-provider-ipfs-http-client ``` ```shell npm install web3 @erc725/erc725.js @lukso/lsp-smart-contracts @lukso/data-provider-ipfs-http-client ``` ## Create a new LSP3Profile JSON file
LSP3ProfileMetadata.json (example) - Complete "ready to use" JSON file ```json { "LSP3Profile": { "name": "Universal Profile - Edit Profile Data", "description": "Congratulations! You have successfully edited your profile!", "links": [ { "title": "Website", "url": "https://mywebsite.me" } ], "tags": ["Public Profile"], "profileImage": [ { "width": 640, "height": 609, "url": "ipfs://QmPCz896rcZmq8F3FuUkJinRUmPgnZGjPvZL71nAaL7Fsx", "verification": { "method": "keccak256(bytes)", "data": "0xe459e5769af85b09fb43bb8eaac561e196d58c0f5da3c5e150b6695898089402" } } ], "backgroundImage": [ { "width": 1024, "height": 576, "url": "ipfs://QmPMmEpKnmgACsWjhDUheF8TEKpspzQhAkjbY4EBbR4jgP", "verification": { "method": "keccak256(bytes)", "data": "0x1c19780d377a7b01f7dcf16e0ebffd225e29d2235625009f67cf9d86a32a79e1" } } ] } } ```
We will start by creating a **new JSON file** that will contain our [`LSP3Profile`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md#lsp3profile) metadata. ```json title="LSP3ProfileMetadata.json" { "LSP3Profile": { "name": "...", // a self chosen username "description": "...", // A description, describing the person, company, organisation or creator of the profile. "links": [ // links related to the profile { "title": "...", // a title for the link. "url": "..." // the link itself } // add more links... ], "tags": ["...", "..."], // tags related to the profile "profileImage": [ { "width": 640, // in pixels "height": 609, // in pixels "url": "ipfs://...", // IPFS image identifier (CID) "verification": { "method": "keccak256(bytes)", // do not change! "data": "0x..." // keccak256 hash of the image file } } ], "backgroundImage": [ { "width": 1024, // in pixels "height": 576, // in pixels "url": "ipfs://...", // IPFS image identifier (CID) "verification": { "method": "keccak256(bytes)", // do not change! "data": "0x..." // keccak256 hash of the image file } } ] } } ``` **Add more details to your profile:** Add more details about the Universal Profile for the entity's name, description, links, and tags. The properties `links` and `tags` accept an array of objects or strings, so you can add as many as you need! Be as creative as you want to make your Universal Profile as unique as possible! :art: :::info Recommendation The JSON file for [`LSP3Profile`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md#lsp3profile) accepts an array of images so that you have pictures of different sizes and dimensions. This way, client interfaces can know which files to pick based on the container size in their interface. ::: ## Upload data to IPFS :::info Learn More **IPFS is just one place among many** where you can store your Universal Profile metadata.
You can use other file storage options (_e.g., [Swarm](https://www.ethswarm.org/), [Storj](https://www.storj.io/index.html), Google Drive, or a private FTP server_). ::: :::tip Storage Providers The [tools-data-providers](https://github.com/lukso-network/tools-data-providers) library supports multiple providers including **local IPFS nodes**, **Pinata**, **Infura**, and more. Choose the one that best fits your setup. ::: This guide will store our Universal Profile metadata on [IPFS](https://ipfs.io/). We can edit our UP metadata by: 1. Creating a new JSON file with new or updated info (**☑️ done in the previous step**). 2. Uploading the file to IPFS. 3. Change the reference of our [LSP3Profile](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md#lsp3profile) key to point to our uploaded JSON file. ### Upload image to IPFS For the properties `profileImage` and `backgroundImage`, we will need to add the following information: - `verification.data`: the keccak256 hash of the image file - `url`: the url of the image uploaded to IPFS. Both values can be obtained from using our IPFS library. ```js import { createReadStream } from 'fs'; import { IPFSHttpClientUploader } from '@lukso/data-provider-ipfs-http-client'; const provider = new IPFSHttpClientUploader( 'https://api.pinata.cloud/pinning/pinFileToIPFS', ); // Or use a local IPFS node: 'http://127.0.0.1:5001/api/v0/add' const file = createReadStream('./test-image.png'); const { url, hash } = await provider.upload(file); ``` :::caution Image sizes should be written as numbers, not as strings. The **max image widths** supported by [universalprofile.cloud](https://universalprofile.cloud) are: `profileImage <= 800px`, `backgroundImage <= 1800px` ::: ### Upload JSON Metadata to IPFS Same as the image, we need to gather the `url` and `hash` values of the uploaded JSON Metadata. ```javascript import { IPFSHttpClientUploader } from '@lukso/data-provider-ipfs-http-client'; // reference to the previously created JSON file (LSP3Profile metadata) import jsonFile from './LSP3Metadata.json'; const ipfsProvider = new IPFSHttpClientUploader( 'https://api.pinata.cloud/pinning/pinFileToIPFS', ); // Or use a local IPFS node: 'http://127.0.0.1:5001/api/v0/add' async function editProfileInfo() { // Upload our JSON file to IPFS and retrieve url and hash values const { url: lsp3ProfileIPFSUrl, hash: lsp3ProfileIPFSHash } = await ipfsProvider.upload(jsonFile); } ``` We are now ready to apply these changes to our Universal Profile. We will see how in the next section. :arrow_down: ## Encode the LSP3Profile Metadata The next step is to **encode the data** to write it on our Universal Profile ERC725Y smart contract. We use our [erc725.js](/tools/dapps/erc725js/getting-started.md) library with the [`encodeData()`](/tools/dapps/erc725js/methods.md#encodeData) function. The library provides the LSP3 schema and handles VerifiableURI encoding automatically. :::success On-Chain vs IPFS You can store the LSP3Profile metadata on IPFS (off-chain) or on-chain as base64. On-chain base64 is convenient for smaller metadata but costs more gas. For profiles with many images, IPFS is more cost-effective. ::: There are three approaches: The simplest approach — pass the JSON object and URL, and erc725.js computes the hash for you: ```javascript import { ERC725 } from '@erc725/erc725.js'; import LSP3ProfileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; // Your LSP3Profile JSON (from step 1) import lsp3ProfileJson from './LSP3Metadata.json'; // Encode the LSP3Profile data — erc725.js computes the hash automatically const encodedData = ERC725.encodeData( [ { keyName: 'LSP3Profile', value: { json: lsp3ProfileJson, url: lsp3ProfileIPFSUrl, // from IPFS upload step }, }, ], LSP3ProfileSchema, ); console.log('Data Key:', encodedData.keys[0]); console.log('Encoded Value:', encodedData.values[0]); ``` If you already have the hash (e.g., from the IPFS upload), you can pass it directly: ```javascript import { ERC725 } from '@erc725/erc725.js'; import LSP3ProfileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; const erc725 = new ERC725(LSP3ProfileSchema); const encodedData = erc725.encodeData([ { keyName: 'LSP3Profile', value: { hashFunction: 'keccak256(utf8)', hash: lsp3ProfileIPFSHash, // from IPFS upload step url: lsp3ProfileIPFSUrl, }, }, ]); console.log('Data Key:', encodedData.keys[0]); console.log('Encoded Value:', encodedData.values[0]); ``` For smaller profiles, you can store the entire JSON on-chain using a `data:` URI with base64 encoding — no IPFS needed: ```javascript import { ERC725 } from '@erc725/erc725.js'; import LSP3ProfileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; import { keccak256, toUtf8Bytes } from 'ethers'; // Your LSP3Profile JSON (from step 1) import lsp3ProfileJson from './LSP3Metadata.json'; const erc725 = new ERC725(LSP3ProfileSchema); // Convert to base64 data URI const jsonString = JSON.stringify(lsp3ProfileJson); const base64Content = Buffer.from(jsonString).toString('base64'); const dataUri = `data:application/json;base64,${base64Content}`; // Hash the JSON string const jsonHash = keccak256(toUtf8Bytes(jsonString)); const encodedData = erc725.encodeData([ { keyName: 'LSP3Profile', value: { hashFunction: 'keccak256(utf8)', hash: jsonHash, url: dataUri, }, }, ]); console.log('Data Key:', encodedData.keys[0]); console.log('Encoded Value:', encodedData.values[0]); ``` ## Edit the Universal Profile Now that our updated data is encoded, we are ready to set it in our Universal Profile smart contract. The 🆙 [Universal Profile Extension](https://chrome.google.com/webstore/detail/universal-profiles/abpickdkkbnbcoepogfhkhennhfhehfn) handles all the transaction signing internally. ```javascript title="set-profile-viem.jsx" import { useAccount, useWriteContract, useWaitForTransactionReceipt, } from 'wagmi'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; function EditProfile() { const { address: UP_ADDRESS } = useAccount(); const { writeContract, data: txHash } = useWriteContract(); const { isSuccess } = useWaitForTransactionReceipt({ hash: txHash }); async function handleEditProfile() { // encodedData from the previous encoding step writeContract({ address: UP_ADDRESS, abi: UniversalProfile.abi, functionName: 'setData', args: [encodedData.keys[0], encodedData.values[0]], }); } return ( ); } ``` ```javascript title="set-profile-ethers.js" import { ethers } from 'ethers'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // Connect via the UP Browser Extension const provider = new ethers.BrowserProvider(window.lukso); await provider.send('eth_requestAccounts', []); const signer = await provider.getSigner(); const account = await signer.getAddress(); // Create instance of the Universal Profile const universalProfileContract = new ethers.Contract( account, // The Universal Profile address UniversalProfile.abi, signer, ); // Update LSP3Profile metadata on the Universal Profile const tx = await universalProfileContract.setData( encodedData.keys[0], encodedData.values[0], ); const receipt = await tx.wait(); console.log('✅ Profile updated! Transaction hash:', tx.hash); ``` ```javascript title="set-profile-web3.js" import Web3 from 'web3'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // Connect via the UP Browser Extension const web3 = new Web3(window.lukso); await web3.eth.requestAccounts(); const accounts = await web3.eth.getAccounts(); // Create instance of the Universal Profile const universalProfileContract = new web3.eth.Contract( UniversalProfile.abi, accounts[0], // The Universal Profile address ); // Update LSP3Profile metadata on the Universal Profile const receipt = await universalProfileContract.methods .setData(encodedData.keys[0], encodedData.values[0]) .send({ from: accounts[0] }); console.log('✅ Profile updated! Transaction hash:', receipt.transactionHash); ``` :::tip ERC725 Inspect You can validate your LSP3Profile metadata of your Universal Profile using the [ERC725 Inspect Tool](https://erc725-inspect.lukso.tech/?network=lukso+mainnet). ::: ## Visualize your updated Universal Profile You can now check your Universal Profile with its updated images and descriptions on [Universal Everything](https://universaleverything.io). `https://universaleverything.io/[UP ADDRESS]` [erc725.js]: /tools/dapps/erc725js/getting-started [ipfs]: https://ipfs.io/ [lsp-smart-contracts]: /tools/lsp-smart-contracts/getting-started.md [tools-data-providers]: https://github.com/lukso-network/tools-data-providers --- --- sidebar_label: 'Read Profile Data' sidebar_position: 1 description: Learn how to read profile data from your Universal Profile. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeSandbox from "@site/src/components/CodeSandbox"; # Read Data from your Universal Profile :::success 💡 Tips Use our [ERC725 inspect](https://erc725-inspect.lukso.tech/?network=lukso+mainnet) tool to easily retrieve data from your 🆙 with the [🔍 Data Fetcher](https://erc725-inspect.lukso.tech/data-fetcher?network=lukso+mainnet) or [🔎 Inspector](https://erc725-inspect.lukso.tech/inspector?network=lukso+mainnet). Simply paste your Universal Profile address in the search field and choose the data key from which to retrieve data. The value stored will be returned both as encoded and decoded. ::: A Universal Profile is a smart contract that uses a generic key-value store (ERC725Y) as a storage design. This structure enables to attach any information to the Universal Profile by setting any **value** to any specific **data key**. ERC725Y data keys are defined by their **ERC725Y JSON schema**. The schema is an object describing the information (= value) stored under this data key. Therefore, a list of schemas let us know which ERC725Y data keys we can set and **which information we can retrieve and edit from the Universal Profile**. :::info For more details, see: [LSP2 - ERC725Y JSON Schema](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#specification) ::: ## Install [erc725.js](https://npmjs.com/package/@erc725/erc725.js) library ```shell npm install @erc725/erc725.js ``` ## Create erc725 instance The parameters to provide to the erc725 instance are: - [Schema](https://github.com/ERC725Alliance/erc725.js/tree/develop/schemas): specifies which data keys will be used to retrieve data from the Universal Profile. - Universal Profile address: the address of the Universal Profile you want to retrieve data from. - Optional only for retrieving decoded data: RPC provider (web3, ethereum, ethers) or plain RPC url of [mainnet](/networks/mainnet/parameters.md) or [testnet](/networks/testnet/parameters.md) networks. ```js title="Creating an erc725 instance to read data from a Universal Profile" import { ERC725 } from '@erc725/erc725.js'; import profileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; const erc725js = new ERC725( profileSchema, '0x03B2689E4843ca56B2A933e7eC1E1ee6C3e6982e', // Universal Profile address 'https://rpc.testnet.lukso.network', { ipfsGateway: 'https://api.universalprofile.cloud/ipfs/', }, ); ``` ## Get all profile data Use the `await erc725js.getData()` function from _erc725.js_ without passing any parameter. ```js title="Get all profile data" import { ERC725 } from '@erc725/erc725.js'; import profileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; const erc725js = new ERC725( profileSchema, '0x03B2689E4843ca56B2A933e7eC1E1ee6C3e6982e', 'https://rpc.testnet.lukso.network', { ipfsGateway: 'https://api.universalprofile.cloud/ipfs/', }, ); const encodedProfileData = await erc725js.getData(); console.log(encodedProfileData); // [ // { // key: '0xeafec4d89fa9619884b600005ef83ad9559033e6e941db7d7c495acdce616347', // name: 'SupportedStandards:LSP3Profile', // value: '0x5ef83ad9', // }, // { // key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', // name: 'LSP3Profile', // value: { // verification: [Object], // url: 'ipfs://QmPNk4GXUDVSpkMYS9ySLj4r7WJYNBLG986GFPqfRJPL8E', // }, // }, // { // key: '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', // name: 'LSP12IssuedAssets[]', // value: [], // }, // { // key: '0x6460ee3c0aac563ccbf76d6e1d07bada78e3a9514e6382b736ed3f478ab7b90b', // name: 'LSP5ReceivedAssets[]', // value: [], // }, // { // key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', // name: 'LSP1UniversalReceiverDelegate', // value: '0x7870C5B8BC9572A8001C3f96f7ff59961B23500D', // }, // ]; ``` ## Get specific profile data :::success Tips You can find all data keys on the [ERC725Y Inspect](https://erc725-inspect.lukso.tech/data-fetcher?network=lukso+mainnet) tool or in the [erc725 repo](https://github.com/ERC725Alliance/erc725.js/tree/develop/schemas). ::: We can also retrieve any of the specific data keys below: - `SupportedStandards:LSP3Profile` used to know if the contract contains some metadata to display as a profile. [More details found here](/standards/metadata/lsp3-profile-metadata#supportedstandardslsp3profile) - `LSP3Profile` used to retrieve VerifiableURI encoded value. VerifiableURI is a reference to a JSON file that describes the Universal Profile meta data. - `LSP12IssuedAssets[]` used to retrieve assets the Universal Profile issued. - `LSP5ReceivedAssets[]` used to retrieve assets the Universal Profile received. - `LSP1UniversalReceiverDelegate` used to retrieve the [Universal Receiver Delegate](/standards/accounts/lsp1-universal-receiver/) smart contract address set on the Universal Profile. ### Get the `LSP3Profile` Metadata One of the main ERC725Y data keys of the Universal Profile is the [`LSP3Profile`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md#lsp3profile) key. It is a standardized key that refers to the **metadata of the Universal Profile**. This metadata takes the form of a reference to a JSON file. To retrieve the content of the JSON file (stored on IPFS, or in any other storage service), we need to use the `fetchData(...)` function from _erc725.js_. This will download the JSON file and verify its hash automatically. ```js title="Get all profile metadata" import { ERC725 } from '@erc725/erc725.js'; import profileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; const erc725js = new ERC725( profileSchema, '0x03B2689E4843ca56B2A933e7eC1E1ee6C3e6982e', 'https://rpc.testnet.lukso.network', { ipfsGateway: 'https://api.universalprofile.cloud/ipfs/', }, ); const decodedProfileMetadata = await erc725js.fetchData('LSP3Profile'); console.log(decodedProfileMetadata); // { // key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', // name: 'LSP3Profile', // value: { // LSP3Profile: { // name: 'testname', // description: '', // tags: ['profile'], // links: [], // profileImage: [[Object], [Object], [Object], [Object], [Object]], // backgroundImage: [], // }, // }, // }, ``` ### Get List of owned assets ```js title="Get received assets" import { ERC725 } from '@erc725/erc725.js'; import profileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; const erc725js = new ERC725( profileSchema, '0xFF7E89acaBce3ed97Ed528288D3b8F113557A8c8', 'https://rpc.testnet.lukso.network', ); const receivedAssetsValue = await erc725js.getData('LSP5ReceivedAssets[]'); console.log(receivedAssetsValue); // { // key: '0x6460ee3c0aac563ccbf76d6e1d07bada78e3a9514e6382b736ed3f478ab7b90b', // name: 'LSP5ReceivedAssets[]', // value: [ // '0xc3B1c63b598Ee41a4BfCE56ecCA802dCD5D5241F', // '0xFc4D463F888D0097f596aac83cBe70F5C2F5641d', // '0x74770d4568DBb5E466c45D128cB3A535EB7291eC', // '0x6dA30e7a8064eAbcA9220AB088514Fc8a131E719', // '0x85134C7bb2Aa2ee019e64d654B289F738344B2ee', // '0xB9dE32D8CaAcf5D2d1f30e3006553e25D46b569F', // '0xD1FBFC22B2424be1E32d3Ee1dCB5306439F0f2A9', // '0x8b08eeb9183081De7e2D4ae49fAD4afb56E31Ab4', // '0x0428AFd3F122a65D023A6863F691e49fcc7B0f44', // '0x50875607ca35c840Bc55ac6D0ce1c3C9c61D65a5', // ], // }, ``` ### Get List of Issued Assets ```js title="Get issued and received assets" import { ERC725 } from '@erc725/erc725.js'; import profileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; const erc725js = new ERC725( profileSchema, '0xFF7E89acaBce3ed97Ed528288D3b8F113557A8c8', 'https://rpc.testnet.lukso.network', ); const issuedAssetsValue = await erc725js.getData('LSP12IssuedAssets[]'); console.log(issuedAssetsValue); // { // key: '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', // name: 'LSP12IssuedAssets[]', // value: [], // }, ``` ### Get Universal Receiver address ```js title="Get issued and received assets" import { ERC725 } from '@erc725/erc725.js'; import profileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; const erc725js = new ERC725( profileSchema, '0xFF7E89acaBce3ed97Ed528288D3b8F113557A8c8', 'https://rpc.testnet.lukso.network', ); const universalReceiverDelegateValue = await erc725js.getData( 'LSP1UniversalReceiverDelegate', ); console.log(universalReceiverDelegateValue); // [ // { // key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', // name: 'LSP1UniversalReceiverDelegate', // value: '0x7870c5b8bc9572a8001c3f96f7ff59961b23500d', // }, // ]; ``` --- --- sidebar_label: 'Register Issued Assets' sidebar_position: 4 description: Learn how to register Issued Assets under an Universal Profile. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Register Issued Assets :::success Asset Authenticity Within the [LSP4 Metadata](/standards/tokens/LSP4-Digital-Asset-Metadata.md), Universal Profiles can be referenced as creators. To **authenticate the creators** of an asset, their Universal Profiles must list the asset's address under the [LSP12 Issued Assets](/standards/metadata/lsp12-issued-assets.md). Services can then validate the **on-chain cross-link** to prove authenticity. ::: In this guide you will learn how to set or update digital assets (either [LSP7 Digital Asset](/standards/tokens/LSP7-Digital-Asset.md) or [LSP8 Identifiable Digital Asset](/standards/tokens/LSP8-Identifiable-Digital-Asset.md)) within the list of LSP12 Issued Assets of a Universal Profile. :::info Code Examples The full code of this example can be found in the 👾 [lukso-playground](https://github.com/lukso-network/lukso-playground/blob/main/dapps/universal-profile/register-issued-assets-backend.ts) repository. ::: ## Setup You will need the address of an existing LSP7 or LSP8 Digital Asset in order to follow this tutorial. E.g: - LSP7 Digital Asset [`0xf7056bdE90f494F55967858F1e9E4AFB1026C5C8`](https://explorer.execution.testnet.lukso.network/address/0xf7056bdE90f494F55967858F1e9E4AFB1026C5C8?tab=read_contract). - LSP8 Digital Asset [`0xf651b88925C0B6C81Ad6f658a2F104226d837F60`](https://explorer.execution.testnet.lukso.network/address/0xf651b88925C0B6C81Ad6f658a2F104226d837F60?tab=read_contract). The following code snippets require the installation of the following libraries: - [`ethers.js`](https://github.com/ethers-io/ethers.js/) or [`web3.js`](https://www.npmjs.com/package/web3) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) - [`@erc725/erc725.js`](https://github.com/ERC725Alliance/erc725.js/) ```shell npm install ethers @lukso/lsp-smart-contracts @erc725/erc725.js ``` ```shell npm install web3 @lukso/lsp-smart-contracts @erc725/erc725.js ``` ## Imports and constants Import `web3.js`/`ethers`, the [`UniversalProfile`](/contracts/contracts/UniversalProfile) ABI from [`@lukso/lsp-smart-contracts`](/contracts/introduction.md) and create an instance of this contract with the `UNIVERSAL_PROFILE_ADDRESS`. ```javascript import { ethers } from 'ethers'; import { ERC725 } from '@erc725/erc725.js'; import LSP12Schema from '@erc725/erc725.js/schemas/LSP12IssuedAssets.json'; import UniversalProfileArtifact from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts'; // We will register the issued assets by setting the following LSP12 data keys // - LSP12IssuedAssets[] // - LSP12IssuedAssetsMap: // add the type of asset (LSP7 or LSP8) and their address in the object list below const issuedAssets = [ { interfaceId: INTERFACE_IDS.LSP7DigitalAsset, address: '0xf7056bdE90f494F55967858F1e9E4AFB1026C5C8', }, { interfaceId: INTERFACE_IDS.LSP8IdentifiableDigitalAsset, address: '0xf651b88925C0B6C81Ad6f658a2F104226d837F60', }, // { // interfaceId: LSP7 or LSP8 interface ID (or other), // address: '0xasset-address', // }, ]; const provider = new ethers.BrowserProvider(window.lukso); await provider.send('eth_requestAccounts', []); const myWallet = await provider.getSigner(); ``` ```javascript import Web3 from 'web3'; import { ERC725 } from '@erc725/erc725.js'; import LSP12Schema from '@erc725/erc725.js/schemas/LSP12IssuedAssets.json'; import UniversalProfileArtifact from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts'; // We will register the issued assets by setting the following LSP12 data keys // - LSP12IssuedAssets[] // - LSP12IssuedAssetsMap: // add the type of asset (LSP7 or LSP8) and their address in the object list below const myIssuedAssets = [ { interfaceId: INTERFACE_IDS.LSP7DigitalAsset, address: '0xf7056bdE90f494F55967858F1e9E4AFB1026C5C8', }, { interfaceId: INTERFACE_IDS.LSP8IdentifiableDigitalAsset, address: '0xf651b88925C0B6C81Ad6f658a2F104226d837F60', }, // { // interfaceId: LSP7 or LSP8 interface ID (or other), // address: '0xasset-address', // }, ]; const web3 = new Web3(window.lukso); await web3.eth.requestAccounts(); const accounts = await web3.eth.getAccounts(); ``` ## Encode the data keys After setting up the array of assets, you can use the [`erc725.js`](/tools/dapps/erc725js/getting-started.md) library to encode the [`LSP12IssuedAssets[]`](/standards/metadata/lsp12-issued-assets/) data keys. There are two ways to encode data: - **Set the full issued assets list**: If you want to initially set issued assets on a Universal Profile or re-set all elements, you can encode the data without defining optional length or index parameters. Therefore, the issued assets will only consist of the asset addresses you provide in your array of assets. - **add, update, or remove existing issued assets**: If the Universal Profile already has issued assets, and you want to add, update, or remove certain assets, you can provide the `startingIndex` and `totalArrayLength` parameters. Therefore, your prepared array only represents a subset of all the issued assets listed in your Universal Profile. :::caution Setting contract data Please be careful when updating existing issued assets. Incorrect usage of `startingIndex` and `totalArrayLength` can lead to improperly encoded data that changes the intended structure of the data field. ::: :::info You can read more about the `encodeData` function of [`erc725.js`](/tools/dapps/erc725js/getting-started.md) within the related [ERC725 Documentation](/tools/dapps/erc725js/methods#encodedata). ::: ```javascript const erc725 = new ERC725( LSP12Schema, UNIVERSAL_PROFILE_ADDRESS, RPC_ENDPOINT, { ipfsGateway: 'https://api.universalprofile.cloud/ipfs', }, ); const allAssetAddresses = myIssuedAssets.map((asset) => asset.address); const allIssuedAssetsMap = myIssuedAssets.map((asset, index) => { return { keyName: 'LSP12IssuedAssetsMap:
', dynamicKeyParts: asset.address, value: [ asset.interfaceId, // index of the issued asset as uint128 // 1 => 0x00000000000000000000000000000001 ERC725.encodeValueType('uint128', index), ], }; }); const { keys: lsp12DataKeys, values: lsp12Values } = erc725.encodeData([ { keyName: 'LSP12IssuedAssets[]', value: allAssetAddresses }, ...allIssuedAssetsMap, ]); ``` ```javascript const erc725 = new ERC725( LSP12Schema, UNIVERSAL_PROFILE_ADDRESS, RPC_ENDPOINT, { ipfsGateway: 'https://api.universalprofile.cloud/ipfs', }, ); // Get the current addresses and array length const currentIssuedAssets = await erc725.getData('LSP12IssuedAssets[]'); let currentAssetAddresses = null; let currentArrayLength = 0; if (Array.isArray(currentIssuedAssets.value)) { currentAssetAddresses = currentIssuedAssets.value; currentArrayLength = currentAssetAddresses.length; } const newAssetAddresses = myIssuedAssets.map((asset) => asset.address); const newIssuedAssetsMapElements = myIssuedAssets.map((asset, index) => { return { keyName: 'LSP12IssuedAssetsMap:
', dynamicKeyParts: asset.address, value: [ asset.interfaceId, // index of the issued asset as uint128 // 1 => 0x00000000000000000000000000000001 // Example for adding 2 new assets at the end of the existing map ERC725.encodeValueType('uint128', currentArrayLength + index), ], }; }); const { keys: lsp12DataKeys, values: lsp12Values } = erc725.encodeData([ { keyName: 'LSP12IssuedAssets[]', value: newAssetAddresses, // Example for adding 2 new assets at the end of the existing addresses startingIndex: currentArrayLength, totalArrayLength: currentArrayLength + newAssetAddresses.length, }, ...newIssuedAssetsMapElements, ]); ``` ## Set Data on the Universal Profile Create an instance of the Universal Profile contract to set the issued assets on. We use the `setDataBatch(...)` function to initially set or update multiple data keys. ```javascript const myUPContract = new ethers.Contract( UNIVERSAL_PROFILE_ADDRESS, UniversalProfileArtifact.abi, myWallet, ); await myUPContract.setDataBatch(lsp12DataKeys, lsp12Values); ``` ```javascript const myUPContract = new web3.eth.Contract( UniversalProfileArtifact.abi, UNIVERSAL_PROFILE_ADDRESS, ); ``` ## Set data batch Next, use the `setDataBatch(...)` function of the Universal Profile to initially set or update multiple data keys. ```javascript await myUPContract.setDataBatch(lsp12DataKeys, lsp12Values); ``` ```javascript await myUPContract.methods .setDataBatch(lsp12DataKeys, lsp12Values) .send({ from: myWallet.address, gas: 1_000_000 }); ``` --- --- sidebar_label: 'Get Profile Owned Assets' sidebar_position: 3 description: Learn how to retrieve the list of assets owned by a Universal Profile. --- import CodeSandbox from "@site/src/components/CodeSandbox"; # Get Profile's Owned Assets :::success Tip To see the list of assets a Universal Profile owns (Tokens and NFTs), go to [🔗 UniversalEverything.io](https://universaleverything.io/). This will list the UP's owned tokens and NFTs with their images. Simply type the name of the Universal Profile or paste its address in the search field, or use the following link, pasting its address at the end: `https://universalprofile.cloud/0x`. ::: Every Universal Profile deployed with the [**🧩 Universal Profile Browser Extension**](/install-up-browser-extension) comes with a 📢 [Universal Receiver delegate](../../../standards/accounts/lsp1-universal-receiver-delegate.md) that register automatically the list of assets it owns. This guide shows you how to easily retrieve the list of owned asset, by fetching the values stored under the [`LSP5ReceivedAssets[]`](../../../standards/metadata/lsp5-received-assets.md#lsp5receivedassets) data key. ## Using erc725.js The [erc725.js](../../../tools/dapps/erc725js/getting-started.md) enable us to do that easily. ```bash npm i @erc725/erc725.js ``` We can then simply import the JSON schema of the [LSP5ReceivedAssets](../../../standards/metadata/lsp5-received-assets.md), create an instance of the library connected to our Universal Profile and fetch the `LSP5ReceivedAssets[]` data key to retrieve all the asset addresses. ```ts import { ERC725 } from '@erc725/erc725.js'; import LSP5Schema from '@erc725/erc725.js/schemas/LSP5ReceivedAssets.json'; const erc725js = new ERC725( LSP5Schema, '0xBA1fa59e9412EB5cDB554252f5BA26Df7514Dbf5', // Address of the Universal Profile 'https://42.rpc.thirdweb.com', // LUKSO Testnet RPC ); const result = await erc725js.getData('LSP5ReceivedAssets[]'); /** { name: 'LSP5ReceivedAssets[]', key: '0x6460ee3c0aac563ccbf76d6e1d07bada78e3a9514e6382b736ed3f478ab7b90b', value: [ '0x39456Bcd4D450E55f851F97c30dF828A4e1f6C66', '0x86E817172b5c07f7036Bf8aA46e2db9063743A83', '0xd681919B63A42A57a9a129A78d1fEb81509aeeF5', '0x80D898C5A3A0B118a0c8C8aDcdBB260FC687F1ce', '0x16f371bc554C38e4bb8f5E6d2617c9AE3Dd5dCbf', ], }, */ ``` ## Using ERC725-Inspect Alternatively, our convenience UI tool ERC725-Inspect enables you to retrieve the list of **LSP5 Received Assets** easily. Simply: 1. Go to [https://erc725-inspect.lukso.tech/](https://erc725-inspect.lukso.tech/?network=lukso+mainnet) 2. Select the network at the top right. 3. Paste the address of the Universal Profile on the search field 4. Scroll down until you reach the data key **`LSP5ReceivedAssets[]`** You should see an array of addresses similar to above. Additionally, the tool can display if the asset is an LSP7 or LSP8 contract, its name, symbol and the UP's balance for this asset. [**➡️ Demo Example**](https://erc725-inspect.lukso.tech/inspector?address=0xBA1fa59e9412EB5cDB554252f5BA26Df7514Dbf5&network=mainnet) --- --- sidebar_label: 'Accept & Reject Assets' sidebar_position: 7 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Accept & Reject Assets Each user can create a **Universal Receiver Delegate** contract with some **custom logic**, which can run automatically on calls to the **[`universalReceiver(..)`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver)** function of the user's Universal Profile based on specific typeIds. ## Reject any Assets To **reject any assets** received by the Universal Profile, we need to create a Universal Receiver Delegate contract that reverts when there is an asset transfer (LSP7 & LSP8). The [`typeId`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver) parameter will give us more context on the call being made. | 📢 Type ID to notify when receiving an LSP7 token 🪙 | | :------------------------------------------------------------------- | | `TYPEID_LSP7_TOKENSRECIPIENT` | | `0x429ac7a06903dbc9c13dfcb3c9d11df8194581fa047c96d7a4171fc7402958ea` | | 📢 Type ID to notify when receiving an LSP8 NFT 🖼️ | | :------------------------------------------------------------------- | | `TYPEID_LSP8_TOKENSRECIPIENT` | | `0x20804611b3e2ea21c480dc465142210acf4a2485947541770ec1fb87dee4a55c` | :::success TypeIds available A full list of LSP1 TypeIds that can be filtered from the `UniversalReceiver` event can be found under the [**contract > Universal Receiver TypeIds**](/contracts/type-ids.md) ::: ### 1 - Deploy contract via Remix :::info Deploy using Universal Profiles To deploy your smart contract using the Universal Profile browser extension, please visit our [Remix guide](/tools/lsp-smart-contracts/working-with-remix.md#deploying-using-the-universal-profile-browser-extension) ::: 1. First go to the **[Remix's website](https://remix.ethereum.org/)**. Create a new solidity file `UniversalReceiverDelegate.sol` under the **contracts** folder. 2. Copy the code snippet below inside the file. It contains the logic for rejecting any LSP7 & LSP8 assets being transferred to the Universal Profile. ```solidity title="UniversalReceiverDelegate.sol - Solidity Code snippet of the URD that reject any assets" // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; // This code is only used for guides puprose, it is working but not verified nor audited. // modules import {LSP1UniversalReceiverDelegateUP} from "@lukso/lsp-smart-contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol"; // constants import {_TYPEID_LSP7_TOKENSRECIPIENT} from "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/LSP7Constants.sol"; import {_TYPEID_LSP8_TOKENSRECIPIENT} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol"; contract CustomUniversalReceiverDelegate is LSP1UniversalReceiverDelegateUP { /** * @param asset The address of the asset being transferred to the UniversalProfile. * @param asset The address disallowing receiving assets. */ error ReceivingAssetsNotAllowed(address asset, address recipient); /** * @dev Reverts when the typeId is relative to token receiving (LSP7 & LSP8) * @param caller The address of the asset informing the `universalReceiver(..)` function on the UniversalProfile. * @param value The amount of native tokens sent by the caller to the universalReceiver function on the UniversalProfile. * @param typeId The typeId representing the context of the call to the universalReceiver function on the UniversalProfile. * @param typeId The data sent to the universalReceiver function on the UniversalProfile. */ function universalReceiverDelegate( address caller, uint256 value, bytes32 typeId, bytes memory data ) public override returns (bytes memory result) { if (typeId == _TYPEID_LSP7_TOKENSRECIPIENT || typeId == _TYPEID_LSP8_TOKENSRECIPIENT){ revert ReceivingAssetsNotAllowed(caller, msg.sender); } } } ``` :::note Please make sure to unlock MetaMask and disable Browser Extension while doing this step. ::: 3. Go to the **Solidity Compiler** tab and press the **"Compile `UniversalReceiverDelegate.sol`"** button. 4. Then navigate to the **Deploy & Run Transactions** tab and choose _Injected Provider_ as the environment. You should be connected to LUKSO Testnet in MetaMask and Remix and have enough LYXt in the EOA used to deploy the URD. If you do not have enough LYXt, request them from the [LUKSO Testnet Faucet](/networks/testnet/parameters.md). 5. Select the **`CustomUniversalReceiverDelegate`** in the dropdown list of contracts and click on the **deploy** button. 6. You will have to confirm the transaction and wait until the transaction has been validated on the network. 7. Once the contract deployed, copy and save the contract address. This address will be used in the next section. You have successfully deployed your **CustomUniversalReceiverDelegate** contract on LUKSO Testnet! 🙌🏻 We now need to set its address under the **[LSP1-UniversalReceiverDelegate Data Key](/standards/accounts/lsp1-universal-receiver.md#extension)** inside the UP's storage. We will do that **via a custom script in step 2** using web3.js or ether.js. ### 2 - Install dependencies for script Make sure you have the following dependencies installed before beginning this tutorial: - Either [`web3.js`](https://github.com/web3/web3.js) or [`ethers.js`](https://github.com/ethers-io/ethers.js/) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) ```shell title="Install the dependencies" npm install ethers @lukso/lsp-smart-contracts ``` ```shell title="Install the dependencies" npm install web3 @lukso/lsp-smart-contracts ``` ### 3 - Create instance of the 🆙 First we need to create an instance of the [`UniversalProfile`](/contracts/contracts/UniversalProfile/UniversalProfile.md) contract. We will need: - the `UniversalProfile` ABI from the [`@lukso/lsp-smart-contracts`](/contracts/introduction.md) package. - the Universal Profile's address, retrieved by [connecting to the UP Browser Extension](/learn/universal-profile/connect-profile/connect-up.md) ```typescript title="Create instance of Universal Profile" import { ethers } from 'ethers'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // connect to the UP Browser Extension const provider = new ethers.BrowserProvider(window.lukso); // Retrieve address of the Universal Profile const accounts = await provider.send('eth_requestAccounts', []); // create an instance of the Universal Profile const universalProfile = new ethers.Contract(accounts[0], UniversalProfile.abi); ``` ```typescript title="Create instance of Universal Profile" import Web3 from 'web3'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // connect to the UP Browser Extension const provider = new Web3(window.lukso); // Retrieve address of the Universal Profile const accounts = await provider.eth.requestAccounts(); // create an instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfile.abi, accounts[0], // Universal Profile address ); ``` ### 4 - Setup the LSP1 Universal Receiver Delegate Finally, we need to send the transaction that will update the URD of the Universal Profile. ```typescript title="Update the Universal Profile's URD" import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; // code from step 2.2 ... // Update the profile data await universalProfile.setData( ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, // URD Data Key from `@lukso/lsp-smart-contracts` package '0x...', // address of the Universal Receiver Delegate contract deployed in step 1 { from: accounts[0], }, ); ``` ```typescript title="Update the Universal Profile's URD" import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; // code from step 2.2 ... // Update the profile data await universalProfile.methods .setData( ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, // URD Data Key from `@lukso/lsp-smart-contracts` package '0x...', // address of the Universal Receiver Delegate contract deployed in step 1 ) .send({ from: accounts[0], }); ``` ### Final code ```typescript title="Update the Universal Profile URD" import { ethers } from 'ethers'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts/constants.js'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // connect to the UP Browser Extension const provider = new ethers.BrowserProvider(window.lukso); // Retrieve address of the Universal Profile const accounts = await provider.send('eth_requestAccounts', []); // create an instance of the Universal Profile const universalProfile = new ethers.Contract(accounts[0], UniversalProfile.abi); // Update the profile data await universalProfile.setData( ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, // URD Data Key from `@lukso/lsp-smart-contracts` package '0x...', // address of the Universal Receiver Delegate contract deployed in step 1 { from: accounts[0], }, ); ``` ```typescript title="Update the Universal Profile URD" import Web3 from 'web3'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts/constants.js'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // connect to the UP Browser Extension const provider = new Web3(window.lukso); // Retrieve address of the Universal Profile const accounts = await provider.eth.requestAccounts(); // create an instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfile.abi, accounts[0], // Universal Profile address ); // Update the profile data await universalProfile.methods .setData( ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, // URD Data Key from `@lukso/lsp-smart-contracts` package '0x...', // address of the Universal Receiver Delegate contract deployed in step 1 ) .send({ from: accounts[0], }); ``` ## Accepting specific Assets To accept specific assets, you should differentiate between the different assets being transferred to you. One way to do it is to have a mapping inside the URD contract that states if the asset being transferred **is allowed to be received or not**. Only the owner should be allowed to add these asset addresses. For simplicity, the owner could be the EOA address deploying the contract. Repeat the deployment steps in **[Rejecting all Assets](#rejecting-all-assets)** section and replace the solidity code with the one written below. ```solidity title="Solidity Code snippet of the Custom URD that accept specific assets" // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; // This code is only used for guides and demonstration purpose // modules import {LSP1UniversalReceiverDelegateUP} from "@lukso/lsp-smart-contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol"; // constants import {_TYPEID_LSP7_TOKENSRECIPIENT} from "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/LSP7Constants.sol"; import {_TYPEID_LSP8_TOKENSRECIPIENT} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol"; contract CustomUniversalReceiverDelegate is LSP1UniversalReceiverDelegateUP { address immutable public owner; mapping (address => bool) public allowedAssets; constructor(address _owner){ owner = _owner; } modifier onlyOwner(){ require(msg.sender == owner, "CustomUniversalReceiverDelegate : Caller is not the owner"); _; } function setAllowedAssets(address assets) public onlyOwner { allowedAssets[assets] = true; } /** * @dev Reverts when the asset being transferred is not allowed. If allowed, the address of the asset * will be registered inside the storage, and removed when balance of the asset equal 0, according to * the LSP5-ReceivedAssers standard. * * @param caller The address of the asset informing the `universalReceiver(..)` function on the UniversalProfile. * @param value The amount of native tokens sent by the caller to the universalReceiver function on the UniversalProfile. * @param typeId The typeId representing the context of the call to the universalReceiver function on the UniversalProfile. * @param typeId The data sent to the universalReceiver function on the UniversalProfile. */ function universalReceiverDelegate( address caller, uint256 value, bytes32 typeId, bytes memory data ) public override returns (bytes memory result){ // checking if the asset being transferred is allowed or not. if(typeId == _TYPEID_LSP8_TOKENSRECIPIENT || typeId == _TYPEID_LSP7_TOKENSRECIPIENT){ require(allowedAssets[caller], "Asset being transferred is not allowed to be received"); } // using the default implementation code to register the address of assets received result = super.universalReceiverDelegate(caller, value, typeId, data); } } ``` The code above will register the address of the assets allowed and remove them when the UP's balance for this asset is 0. It will also reject assets that are not allowed. Since this code will need **[SUPER_SETDATA Permission](/standards/access-control/lsp6-key-manager.md#super-permissions)**, after deploying it, you will set the address of the URD in the storage using the code from the **[Set the address of the URD in the storage](./deploy-universal-receiver.md#set-the-address-of-the-urd-in-the-storage)** section. :::info A similar mapping example that list allowed assets can be found in the guide [**Create an LSP1 Forwarder**](./create-receiver-forwarder.md) ::: --- --- sidebar_label: 'Create a Token Forwarder' sidebar_position: 2 description: This smart contract tutorial guides you on how to create a LSP1 Delegate contract that forwards portion of received tokens automatically to any address. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Create a Token Forwarder This guide will teach you how to create a basic custom [Universal Receiver Delegate](/standards/accounts/lsp1-universal-receiver-delegate.md) contract for the following use-case: > **"As a Universal Profile (UP) owner, I want to transfer part of the tokens I received to another UP"**. We will this contract an **LSP1 Forwarder**. Every time our 🆙 will receive a specific [LSP7 token](/standards/tokens/LSP7-Digital-Asset.md), this contract will automatically transfer a certain percentage to another address we have defined. An example scenario could be: _"each time I receive USDT, I want to automatically transfer 20% to my wife's UP"_. ## Setup & Requirements :::success Tips If you want to follow this guide using not an existing token, but a new token that you want to create and deploy yourself, check our guide [**"Create a Custom LSP7 Token"**](/learn/digital-assets/token/create-lsp7-token.md). ::: :::info This guide is working with version above 0.14.0 of the [`@lukso/lsp-smart-contracts`](/contracts/introduction.md) package. ::: In order to follow this guide, you will need the following: 1. Download and install the [UP Browser extension](/install-up-browser-extension). 2. Fund the main EOA controller of your 🆙 (See **[Step 1](#step-1---enable-your-controller-to-add-a-universal-receiver) bullet point 3** to retrieve its address) using the [Testnet Faucet](https://faucet.testnet.lukso.network/). 3. The address of the LSP7 token that you want to use to forward of portion of the amount received. 4. The v0.14.0 [`@lukso/lsp-smart-contracts`](/contracts/introduction.md) library installed. 5. The [_erc725.js_](/tools/dapps/erc725js/getting-started.md) library installed to encode the data key / value to register our LSP1 Forwarder. 6. The [`dotenv`](https://www.npmjs.com/package/dotenv) package to load our main EOA controller private key into our script. ```bash npm i @lukso/lsp-smart-contracts@v0.14.0 @erc725/erc725.js dotenv ``` ## Step 1 - Enable your controller to Add & Edit a Universal Receiver First, we will need to enable adding a Universal Receiver for the main controller of our UP. To do that: 1. Open the UP Browser Extension in your web browser. 2. Click on the **"Controller"** tab. 3. Select **"UP Extension"** which. This will bring the controller information page that you see below. From there: 4. Scroll down to the **"Administration & Ownership"** part 5. Toggle ON the **"Add notifications & automation"** + **"Edit notifications & automation"** permission. 6. Confirm the changes and submit the transaction. ## Step 2 - Create LSP1 Forwarder contract in Solidity We can make our LSP1 Forwarder contract to perform this action in 2 different ways, via 2 different interaction flows. ### Two Design Options To re-transfer a portion of the tokens received, we can instruct the LSP1 Forwarder contract to re-call the [`transfer(...)`](/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#transfer) function on the LSP7 Token contract in 2 ways: - **method 1:** via the [**`execute(...)` function of the 🆙**](/contracts/contracts/UniversalProfile/UniversalProfile.md#execute). - **method 2:** directly on the LSP7 contract **after having authorized the LSP1 Forwarder as an operator via [`authorizeOperator(...)`](/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#authorizeoperator)**. For method 1 to work, the LSP1 Forwarder contract will need the permissions [`SUPER_CALL` + `REENTRANCY`](/standards/access-control/lsp6-key-manager.md#permissions) on the UP. For method 2 to work, the LSP1 Forwarder contract needs to be authorized as an operator at the LSP7 level (using [`authorizeOperator`](/contracts/contracts/LSP7DigitalAsset/#authorizeoperator)) with unlimited amount (`type(uint256).max`). Both methods have their advantages and disadvantages, as summarized below. | Design Method | Advantages 👍🏻 | Disadvantages 👎🏻 | | :------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | | **Method 1:** via 🆙 `execute(...)` function | Does not requires additional setup (`authorizeOperator` operation)
Can trace the transfer from your UP transactions' activity tab | Cost a bit more gas (+/- 23k) compared to method 2 on the re-transfer transaction. | | **Method 2:** via `authorizeOperator(...)` on LSP7 Token contract 🪙 | More gas efficient. | You have to authorize your URD to spend your LSP7 token for an unlimited amount | ### Solidity code Select one of the two tabs below to see the Solidity implementation of each design. The code is commented enough to be self explanatory, but let's dive a bit more into some interesting bits. :::success Tips This method leverages the [Key Manager's permissions](/learn/universal-profile/key-manager/grant-permissions.md) instead of token operator approval. It is the **recommended method**, making managing which tokens the LSP1 Forwarder can re-transfer easier. ::: ```solidity title="LSP1URDForwarder.sol" showLineNumbers // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.11; // interfaces import { IERC725X } from "@erc725/smart-contracts/contracts/interfaces/IERC725X.sol"; import { ILSP1UniversalReceiverDelegate as ILSP1Delegate } from "@lukso/lsp-smart-contracts/contracts/LSP1UniversalReceiver/ILSP1UniversalReceiverDelegate.sol"; import { ILSP7DigitalAsset } from "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol"; // modules import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; // constants import { _TYPEID_LSP7_TOKENSRECIPIENT } from "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/LSP7Constants.sol"; import "@lukso/lsp-smart-contracts/contracts/LSP1UniversalReceiver/LSP1Constants.sol"; import "@lukso/lsp-smart-contracts/contracts/LSP0ERC725Account/LSP0Constants.sol"; // errors import "@lukso/lsp-smart-contracts/contracts/LSP1UniversalReceiver/LSP1Errors.sol"; contract LSP1Forwarder is ERC165, ILSP1Delegate { // CHECK onlyOwner modifier onlyOwner { require(msg.sender == owner, "Not the owner"); _; } // Owner address owner; // Set a recipient address public recipient; // Set a percentage to send to recipient uint256 public percentage; // Set a mapping of authorized LSP7 tokens mapping (address => bool) allowlist; // we set the recipient & percentage & allowedAddresses of the deployer in the constructor for simplicity constructor(address _recipient, uint256 _percentage, address[] memory tokenAddresses) { require(_percentage < 100, "Percentage should be < 100"); recipient = _recipient; percentage = _percentage; owner = msg.sender; for (uint256 i = 0; i < tokenAddresses.length; i++) { allowlist[tokenAddresses[i]] = true; } } function addAddress(address token) public onlyOwner { allowlist[token] = true; } function setRecipient(address _recipient) public onlyOwner { recipient = _recipient; } function setPercentage(uint256 _percentage) public onlyOwner { require(_percentage < 100, "Percentage should be < 100"); percentage = _percentage; } function removeAddress(address token) public onlyOwner { allowlist[token] = false; } function getAddressStatus(address token) public view returns (bool) { return allowlist[token]; } function universalReceiverDelegate( address notifier, uint256 value, bytes32 typeId, bytes memory data ) public virtual returns (bytes memory) { // CHECK that the caller is an a UniversalProfile // by checking it supports the LSP0ERC725Account interface if ( !ERC165Checker.supportsERC165InterfaceUnchecked( msg.sender, _INTERFACEID_LSP0 ) ) { return "Caller is not a LSP0"; } // CHECK that notifier is a contract with a `balanceOf` method // and that msg.sender (the UP) has a positive balance if (notifier.code.length > 0) { try ILSP7DigitalAsset(notifier).balanceOf(msg.sender) returns ( uint256 balance ) { if (balance == 0) { return "LSP1: balance is zero"; } } catch { return "LSP1: `balanceOf(address)` function not found"; } } // CHECK that the address of the LSP7 is whitelisted if (!allowlist[notifier]) { return "Token not in allowlist"; } // extract data (we only need the amount that was transferred / minted) (, , , uint256 amount, ) = abi.decode( data, (address, address, address, uint256, bytes) ); // CHECK that amount is not too low if (amount < 100) { return "Amount is too low (< 100)"; } else { uint256 tokensToTransfer = (amount * percentage) / 100; bytes memory tokenTransferCalldata = abi.encodeCall( ILSP7DigitalAsset.transfer, msg.sender, recipient, tokensToTransfer, true, "" ); IERC725X(msg.sender).execute(0, notifier, 0, tokenTransferCalldata); return ""; } } function supportsInterface( bytes4 interfaceId ) public view virtual override returns (bool) { return interfaceId == _INTERFACEID_LSP1_DELEGATE || super.supportsInterface(interfaceId); } } ``` Let's dive in some of the details of the [`universalReceiverDelegate(...)`](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP.md#universalreceiverdelegate) function. The flow works as follow: 1. (lines 83-90) We first verify that the caller `msg.sender` is a Universal Profile. 2. (lines 94-103) We checked that we are being notified by a smart contract. If we manage to call the `balanceOf(address)` function, we assume it is an LSP7 Token contract. 3. (lines 107-109) We then ensure that this token is in our list of tokens to transfer some percentage of to another address. 4. (lines 112-121) The LSP7 Token contract sent us in the notification `data` (function param line 79) the amount of tokens that were transferred. 1. (line 112) We extract **only** this `amount` from the `data` received . The other infos in the data are not necessary so not used. 2. (line 121) We calculate the proportion to re-transfer (local variable `tokensToTransfer`,) according to the `percentage` set (state variable line 37). 5. (line 123-129) We encode a call to the [`transfer(...)`](/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#transfer) function on the LSP7 Token contract, using the Solidity built-in function `encodeCall`. The 4 parameters being encoded for the function call are: - `from`: (`msg.sender`) = this UP that received the tokens. - `to`: (`recipient`) = the address that will receives the percentage of tokens. - `amount`: (`tokensToTransfer`) = the calculated percentage of the total amount received. - `allowNonLSP1Recipient`: indicates if we can transfer to any address (`true`), or if it must be an LSP1 enabled one (`false`). - `data`: no additional data 6. (line 131) After having saved this abi-encoded calldata, we execute this call via the UP. This is done by using the [`execute(...)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#execute) function on the 🆙 (**a generic execution function**). We know from step 1 that the `msg.sender` is a Universal Profile. So we can safely explicitly cast `msg.sender` to an `ERC725X` contract to use the [`execute(...)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#execute) function. The parameters passed are: - `operationType`: 0 = CALL operation - `target`: the `notifier` (function parameter, line 76) = our LSP7 contract - `value`: 0 = no LYX are sent - `data`: the `tokenTransferCalldata` variable. This is our encoded call to the [`transfer(...)`](/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#transfer) function on the LSP7 token, generated in step 5. :::info Notice For this method to work, the LSP1 Forwarder needs to be authorized as an operator (via [`authorizeOperator(...)`](/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#authorizeoperator)) to spend tokens on behalf of the 🆙. It can be cumbersome to manage, as the `LSP1Forwarder` contract would need to be approved as an operator for every single token we want to allow to re-transfer. This would require multiple `authorizeOperator(...)` calls to multiple token contracts, creating more transactions that can be gas-expensive. (can be mitigated by grouping these in an [`executeBatch(...)`](/contracts/contracts/UniversalProfile/UniversalProfile.md#executebatch)). In comparison, the first design (via `UP.execute(...)` call) is easier to manage, as the LSP1Forwarder can be [granted permission once](/learn/universal-profile/key-manager/grant-permissions.md) for multiple tokens via one single `setData(...)` call. ::: ```solidity title="LSP1URDForwarder.sol" showLineNumbers // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.11; // interfaces import { IERC725X } from "@erc725/smart-contracts/contracts/interfaces/IERC725X.sol"; import { ILSP1UniversalReceiverDelegate as ILSP1Delegate } from "@lukso/lsp-smart-contracts/contracts/LSP1UniversalReceiver/ILSP1UniversalReceiverDelegate.sol"; import { ILSP7DigitalAsset } from "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol"; // modules import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; // constants import { _TYPEID_LSP7_TOKENSRECIPIENT } from "@lukso/lsp-smart-contracts/contracts/LSP7DigitalAsset/LSP7Constants.sol"; import "@lukso/lsp-smart-contracts/contracts/LSP1UniversalReceiver/LSP1Constants.sol"; import "@lukso/lsp-smart-contracts/contracts/LSP0ERC725Account/LSP0Constants.sol"; // errors import "@lukso/lsp-smart-contracts/contracts/LSP1UniversalReceiver/LSP1Errors.sol"; contract LSP1Forwarder is ERC165, ILSP1Delegate { // CHECK onlyOwner modifier onlyOwner { require(msg.sender == owner, "Not the owner"); _; } // Owner address owner; // Set a recipient address public recipient; // Set a percentage to send to recipient uint256 public percentage; // Set a mapping of authorized LSP7 tokens mapping (address => bool) allowlist; // we set the recipient & percentage & allowedAddresses of the deployer in the constructor for simplicity constructor(address _recipient, uint256 _percentage, address[] memory tokenAddresses) { require(_percentage < 100, "Percentage should be < 100"); recipient = _recipient; percentage = _percentage; owner = msg.sender; for (uint256 i = 0; i < tokenAddresses.length; i++) { allowlist[tokenAddresses[i]] = true; } } function addAddress(address token) public onlyOwner { allowlist[token] = true; } function setRecipient(address _recipient) public onlyOwner { recipient = _recipient; } function setPercentage(uint256 _percentage) public onlyOwner { require(_percentage < 100, "Percentage should be < 100"); percentage = _percentage; } function removeAddress(address token) public onlyOwner { allowlist[token] = false; } function getAddressStatus(address token) public view returns (bool) { return allowlist[token]; } function universalReceiverDelegate( address notifier, uint256 value, bytes32 typeId, bytes memory data ) public virtual returns (bytes memory) { // CHECK that the caller is an ERC725Account (e.g: a UniversalProfile) // by checking it supports the LSP0 interface if ( !ERC165Checker.supportsERC165InterfaceUnchecked( msg.sender, _INTERFACEID_LSP0 ) ) { return "Caller is not a LSP0"; } // CHECK that notifier is a contract with a `balanceOf` method // and that msg.sender (the UP) has a positive balance if (notifier.code.length > 0) { try ILSP7DigitalAsset(notifier).balanceOf(msg.sender) returns ( uint256 balance ) { if (balance == 0) { return "LSP1: balance is zero"; } } catch { return "LSP1: `balanceOf(address)` function not found"; } } // CHECK that the address of the LSP7 is whitelisted if (!allowlist[notifier]) { return "Token not in allowlist"; } // extract data (we only need the amount that was transferred / minted) (, , , uint256 amount, ) = abi.decode( data, (address, address, address, uint256, bytes) ); // CHECK if amount is not too low if (amount < 100) { return "Amount is too low (< 100)"; } else { uint256 tokensToTransfer = (amount * percentage) / 100; ILSP7DigitalAsset(notifier).transfer(msg.sender, recipient, tokensToTransfer, true, ""); return ""; } } function supportsInterface( bytes4 interfaceId ) public view virtual override returns (bool) { return interfaceId == _INTERFACEID_LSP1_DELEGATE || super.supportsInterface(interfaceId); } } ``` :::info Notice See our notice above the code snippet for the [**main drawbacks of the method**](#solidity-code) ::: Let's dive in some of the details of the [`universalReceiverDelegate(...)`](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP.md#universalreceiverdelegate) function. The flow works as follow: 1. (lines 83-90) We first verify that the caller `msg.sender` is a Universal Profile. 2. (lines 94-103) We checked that we are being notified by a smart contract. If we manage to call the `balanceOf(address)` function, we assume it is an LSP7 Token contract. 3. (lines 107-109) We then ensure that this token is in our list of tokens to transfer some percentage of to another address. 4. (lines 112-121) The LSP7 Token contract sent us in the notification `data` (function param line 79) the amount of tokens that were transferred. 1. (line 112) We extract **only** this `amount` from the `data` received . The other infos in the data are not necessary so not used. 2. (line 121) We calculate the proportion to re-transfer (local variable `tokensToTransfer`,) according to the `percentage` set (state variable line 37). 5. (line 123) Since we allowed the LSP1 Forwarder as an operator, we directly call the `transfer(...)` function on the LSP7 token contract (the `notifier`, passed as function parameter in line 76). ## Step 3 - Deploy our LSP1 Forwarder Now that we have created our custom LSP1 Delegate Forwarder contract, we will deploy it on LUKSO Testnet. Let's first compile our contract to generate its ABI and bytecode. ```bash hardhat compile ``` Setup the [LUKSO Testnet network](/networks/testnet/parameters.md) in your `hardhat.config.ts`. ```ts title="hardhat.config.ts" // ... const config: HardhatUserConfig = { // ... networks: { luksoTestnet: { live: true, url: '**https**://rpc.testnet.lukso.network', chainId: 4201, saveDeployments: true, }, }, // ... }; // ... export default config; ``` We will use a Hardhat script to deploy our LSP1 Forwarder contract. We will use our main controller address by exporting its private key from the UP Browser Extension. Create the following `.env` file and add the main controller private key exported from the 🆙 Browser Extension: ```txt title=".env" PRIVATE_KEY="" ``` Create the following file under the `scripts/` folder in your Hardhat project. ```ts title="scripts/deployLSP1Forwarder.ts" import hre from 'hardhat'; import { ethers } from 'hardhat'; import * as dotenv from 'dotenv'; import LSP1URDForwarder from "../artifacts/contracts/Tokens/LSP1URDForwarder.sol/LSP1URDForwarder.json';"; // load env vars dotenv.config(); // setup provider const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); // You can update the value of the allowed LSP7 token const MY_USDC_TOKEN = '0x63890ea231c6e966142288d805b9f9de7e0e5927'; // setup signer (the browser extension main controller) const signer = new ethers.Wallet(process.env.PRIVATE_KEY as string, provider); console.log('Main 🆙 Controller address (EOA 🔑): ', signer.address); // ----------------------------- // DEPLOY LSP1 Delegate contract // ----------------------------- const lsp1ForwarderFactory = new ethers.ContractFactory( LSP1URDForwarder.abi, LSP1URDForwarder.bytecode, signer, ); const lsp1Forwarder = await lsp1ForwarderFactory.deploy( '0xd33D2Cd7035e508043983283CD8E870dfAbEA844', // Token recipient '20', // Percentage % of token to re-transfer to Token Recipient [MY_USDC_TOKEN], ); console.log( '✅ Custom URD successfully deployed at address: ', lsp1Forwarder.address, ); ``` Run the command below to deploy our custom LSP1 Forwarder contract on LUKSO Testnet: ```bash npx hardhat run scripts/deployLSP1Forwarder.ts --network luksoTestnet ``` ## Step 4 - Setup our LSP1 Forwarder Now that we have deployed our custom LSP1 Forwarder contract, we will register it and set it up on our Universal Profile. ### 4.1 - Register on the UP We will register this LSP1 Forwarder for the LSP1 Type Id [`LSP7Tokens_RecipientNotification`](/contracts/type-ids.md#lsp7tokens_recipientnotification). This type Id is used to notify the Universal Profile that it received some new tokens. To do that, use the [`LSP1UniversalReceiverDelegate:`](/standards/accounts/lsp1-universal-receiver-delegate.md#lsp1universalreceiverdelegate-mapping) Mapping data key, where the `` part will be the type Id. The _erc725.js_ library will enable us to do that easily. ```ts import ethers from 'ethers'; import ERC725 from '@erc725/erc725.js'; import LSP1Schema from '@erc725/erc725js/schemas/LSP1UniversalReceiver.json'; import LSP6Schema from '@erc725/erc725js/schemas/LSP6KeyManager.json'; import { LSP1_TYPE_IDS } from '@lukso/lsp-smart-contracts'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // code from previous steps here... // including the instance of the `lsp1Forwarder` contract. const lsp1Forwarder = await lsp1ForwarderFactory.deploy( '0xd33D2Cd7035e508043983283CD8E870dfAbEA844', // Token recipient '20', // Percentage % of token to re-transfer to Token Recipient [MY_USDC_TOKEN], ); const erc725 = new ERC725(LSP1Schema); const { keys, values } = erc725.encodeData([ { keyName: 'LSP1UniversalReceiverDelegate:', dynamicKeyPart: LSP1_TYPE_IDS.LSP7Tokens_RecipientNotification, value: lsp1Forwarder.address, }, ]); const universalProfile = new ethers.Contract( '0x...', // Universal Profile address UniversalProfile.abi, signer, ); // register the LSP1 Forwarder for the notification type when we receive new LSP7 tokens const setDataTx = await universalProfile.setData(keys[0], values[0]); await setDataTx.wait(); console.log('✅ Custom LSP1 Delegate has been correctly registered on the UP'); ``` ### 4.2 - Setup permissions / operator Depending on the design / method selected in [step 2](#step-2---create-lsp1-forwarder-contract-in-solidity), we will have to setup our LSP1 Forwarder contract differently: | Method | Setup Required | | :------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Method 1:** via 🆙 `execute(...)` function | **Grant the permissions `SUPER_CALL` + `REENTRANCY`** to the LSP1 Forwarder contract so that it can re-call the 🆙. | | **Method 2:** via `authorizeOperator(...)` on LSP7 Token contract 🪙 | **Authorize the address of the LSP1 Forwarder contract as an operator**, to spend tokens on behalf of the UP. This using the [`authorizeOperator()`](/contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#authorizeoperator) function on the LSP7 token contract. | With this method, we will set the permission `SUPER_CALL` and `REENTRANCY` on our 🆙 for the LSP1 Forwarder. ```ts import ERC725 from '@erc725/erc725.js'; import LSP6Schema from '@erc725/erc725js/schemas/LSP6KeyManager.json'; import { PERMISSIONS } from '@lukso/lsp-smart-contracts'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // code from previous step here... // including the instance of the `lsp1Forwarder` contract. const lsp1Forwarder = await lsp1ForwarderFactory.deploy( '0xd33D2Cd7035e508043983283CD8E870dfAbEA844', // Token recipient '20', // Percentage % of token to re-transfer to Token Recipient [MY_USDC_TOKEN], ); const erc725 = new ERC725(LSP1Schema); const { keys, values } = erc725.encodeData([ { keyName: 'AddressPermissions:Permissions:
', value: ERC725.encodePermissions({ SUPER_CALL: true, REENTRANCY: true, }), }, ]); // Create an instance of our Universal Profile const universalProfile = new ethers.Contract( '0x...', // Universal Profile address UniversalProfile.abi, signer, ); // Set the permissions of the LSP1 Forwarder on our UP const setPermissionsTx = await universalProfile.setData(keys[0], values[0]); await setPermissionsTx.wait(); console.log('✅ Custom LSP1 Forwarder permissions have been set successfully'); ``` ```ts import ethers from 'ethers'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP7DigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; // code from previous steps here... // including the instance of the `lsp1Forwarder` and the address of the LSP7 Token contract. const MY_USDC_TOKEN = '0x63890ea231c6e966142288d805b9f9de7e0e5927'; const lsp1Forwarder = await lsp1ForwarderFactory.deploy( '0xd33D2Cd7035e508043983283CD8E870dfAbEA844', // Token recipient '20', // Percentage % of token to re-transfer to Token Recipient [MY_USDC_TOKEN], ); // Create an instance of our Universal Profile const universalProfile = new ethers.Contract( '0x...', // Universal Profile address UniversalProfile.abi, signer, ); console.log('⏳ Authorizing Custom LSP1 Delegate contract on Custom Token'); const lsp7Interface = new ethers.Interface(LSP7DigitalAsset.abi); const authorizeOperatorCalldata = const authBytes = lsp7Interface.encodeFunctionData( 'authorizeOperator', [lsp1Forwarder.address, ethers.MaxUint256, '0x'], // we authorize the LSP1 Forwarder to spend an unlimited amount of the UP's USDC Tokens ); // Execute the function call as the UP const authTxWithBytes = await universalProfile.execute( OPERATION_TYPES.CALL, MY_USDC_TOKEN, 0, authBytes, ); await authTxWithBytes.wait(); console.log('✅ LSP1 Forwarder contract authorized on My USDC Token for UP 🫡'); ``` ## 🧪 Testing our LSP1 Forwarder Now that all the pieces are connected, we can try it out! The expected behaviour is that **every time the UP on which the custom LSP1 Forwarder contract has been set receives an allowed token (either through `transfer` or `mint`), it will automatically send a percentage to the specified recipient.** Here are the test data: - I set up the custom LSP1 Delegate contract on a test UP (neo: `0xD62940E95A7A4a760c96B1Ec1434092Ac2C4855E`) - I created a custom LSP7 token named "My USDC" with symbol "MUSDC" (LSP7: `0x63890ea231c6e966142288d805b9f9de7e0e5927` / owner neo / 20k pre-minted to neo) - The custom LSP1 Delegate contract will send 20% of the received (transfer or mint) MUSDC - The recipient will be another test UP (karasu: `0xe5B9B2C3f72bA13fF43A6CfC6205b5147F0BEe84`) - The custom LSP1 Delegate contract is deployed at address `0x4f614ebd07b81b42373b136259915b74565fedf5` Let's go to [the test dapp](https://up-test-dapp.lukso.tech/) and connect with neo's profile.
Click on "Refresh tokens" to see our `MUSDC` balance.
Use the "Mint" box to mint an additional 10k `MUSDC` to ourself (to neo's UP). This should trigger the custom LSP1 Delegate forwarder and send 20% of 10k (= 2k) to karasu.
We will then disconnect neo's profile from the test dapp. :::note There is a bug currently on the test dapp where the `disconnect` button doesn't work properly. In order to disconnect from the dapp, we need to remove the connection from the "connections" tab by clicking the ❌ icon on the right. :::
We connect karasu's profile to the test dapp
... click on "Refresh tokens" and ...
... Success 🎉 ! Our custom LSP1 Delegate forwarder worked as expected! ## Congratulations 🥳 You now have a fully functional custom LSP1 Delegate contract that will automatically forward a certain amount of the allowed received tokens to another UP! --- --- sidebar_label: 'Create & Deploy Universal Receiver' sidebar_position: 1 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Universal Receiver This guide will teach you how to deploy and set the default implementation of the **[Universal Receiver Delegate](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP)** (URD) used by the Universal Profile. The URD will register the addresses of the **[received assets](/standards/metadata/lsp5-received-assets.md)** and **[vaults](/standards/metadata/lsp10-received-vaults.md)** and remove them on a balance equal to 0. It requires the [**`SUPER_SETDATA` and `REENTRANCY` permissions**](/standards/access-control/lsp6-key-manager.md#super-permissions) to interact with the 🆙.
:::warning If you created your UP with [my.universalprofile.cloud/create](https://my.universalprofile.cloud/create), the Universal Receiver Delegate contract is already set to our default [`LSP1UniversalReceiverDelegateUP`](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP). Setting a new default Universal Receiver Delegate (URD) contract will replace this default one and might affect the behaviour of your UP (for instance, not register your newly received assets). This guide is more intended for any generic ERC725Y contract that is looking to implement solely the [LSP1 Delegate extension functionality](/standards/accounts/lsp1-universal-receiver-delegate.md#lsp1---universal-receiver-delegate). ::: ### Advantages The [Universal Receiver](/standards/accounts/lsp1-universal-receiver.md) is a powerful tool that enables any smart contract or dApp to identify specific incoming transactions and automatically initiate customized responses. This provides several advantages. - **Flexibility**: The Universal Receiver offers flexibility in assigning customized responses to external contracts. - **Customization**: These responses can be assigned to external contracts, known as [Universal Receiver Delegate](/standards/accounts/lsp1-universal-receiver-delegate.md), which can have their own unique mechanisms for various purposes. A contract implementing LSP1 can host multiple Universal Receiver Delegate (URD) smart contracts. This enables one to manage how to respond to specific interactions based on your own predefined rules. To delegate incoming Universal Receiver notifications to a specific smart contract, set an [ERC725Y](/standards/accounts/lsp0-erc725account#erc725y---generic-key-value-store) data key on your Universal Profile. This will instruct your profile to forward notifications to the designated contract. You can a Universal Receiver Delegate contracts using one of the following _data keys_: - `LSP1UniversalReceiverDelegate` to set the **default** one. - `LSP1UniversalReceiverDelegate:` to set a specific one related to the mapped ` typeId`. This way, you can assign your contract different Universal Receiver Delegate contracts, depending on which specific [type IDs](/contracts/type-ids.md) (bytes32) it received when its [`universalReceiver(...)`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver) function was called. This allows to host multiple Universal Receiver Delegate contracts. ## Setup Make sure you have the following dependencies installed before beginning this tutorial: - Either [`web3.js`](https://github.com/web3/web3.js) or [`ethers.js`](https://github.com/ethers-io/ethers.js/) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) ```shell title="Install the dependencies" npm install ethers @lukso/lsp-smart-contracts @erc725/erc725.js ``` ```shell title="Install the dependencies" npm install web3 @lukso/lsp-smart-contracts @erc725/erc725.js ``` ## Step 1 - Imports, constants and EOA We need to; 1. Get the _ABIs_ of the contracts that we will use and the _bytecode_ of the `LSP1UniversalReceiverDelegateUP`. 2. Store the address of our Universal Profile. 3. Initialize the EOA that we will further use. ```typescript title="Imports, Constants & EOA" import LSP1UniversalReceiverDelegateUP from '@lukso/lsp-smart-contracts/artifacts/LSP1UniversalReceiverDelegateUP.json'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { ERC725YDataKeys, PERMISSIONS, } from '@lukso/lsp-smart-contracts/constants.js'; import { ethers } from 'ethers'; // constants const provider = new ethers.providers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const URD_DATA_KEY = ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate; const universalProfileAddress = '0x...'; // setup your EOA const privateKey = '0x...'; // your EOA private key (controller address) const EOA = new ethers.Wallet(privateKey).connect(provider); ``` ```typescript title="Imports, Constants & EOA" import LSP1UniversalReceiverDelegateUP from '@lukso/lsp-smart-contracts/artifacts/LSP1UniversalReceiverDelegateUP.json'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { ERC725YDataKeys, PERMISSIONS, } from '@lukso/lsp-smart-contracts/constants.js'; import Web3 from 'web3'; // constants const web3 = new Web3('https://rpc.testnet.lukso.network'); const URD_DATA_KEY = ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate; const universalProfileAddress = '0x...'; // setup your EOA const privateKey = '0x...'; const EOA = web3.eth.accounts.wallet.add(privateKey); ``` ## Step 2 - Deploy the default Universal Receiver Delegate contract :::info The **Universal Profile** and the **Vault** don't use the same implementation of the Universal Receiver Delegate. ::: ### Create a contract instance At this step we will create an instance of the Universal profile URD that we will further be used to deploy one. ```typescript title="Contract instance of the Universal Profile URD" // create a LSP1UniversalReceiverDelegateUP Contract Factory let universalProfileURDFactory = new ethers.ContractFactory( LSP1UniversalReceiverDelegateUP.abi, LSP1UniversalReceiverDelegateUP.bytecode, ); ``` ```typescript title="Contract instance of the Universal Profile URD" // create an instance of the LSP1UniversalReceiverDelegateUP let universalProfileURD = new web3.eth.Contract( LSP1UniversalReceiverDelegateUP.abi, ); ``` ### Send the contract deployment transaction Send the deployment transaction to get a newly deployed URD. ```typescript title="Send the transaction for deploying a new Universal Profile URD" // deploy the Universal Receiver Delegate UP contract const universalProfileURD = await universalProfileURDFactory .connect(EOA) .deploy(); ``` ```typescript title="Send the transaction for deploying a new Universal Profile URD" // deploy the Universal Receiver Delegate UP contract await universalProfileURD .deploy({ data: LSP1UniversalReceiverDelegateUP.bytecode, }) .send({ from: EOA.address, gas: 5_000_000, gasPrice: '1000000000', }); ``` ### Final code ```typescript title="Deploy a Universal Receiver Delegate for the Universal Profile" const deployUniversalProfileURD = async () => { // create a LSP1UniversalReceiverDelegateUP Contract Factory let universalProfileURDFactory = new ethers.ContractFactory( LSP1UniversalReceiverDelegateUP.abi, LSP1UniversalReceiverDelegateUP.bytecode, ); // deploy the Universal Receiver Delegate UP contract const universalProfileURD = await universalProfileURDFactory .connect(EOA) .deploy(); return testnetuniversalProfileURD.address; }; // deploy a new Universal Profile URD and retrieve its address const universalProfileURDAddress = await deployUniversalProfileURD(); ``` ```typescript title="Deploy a Universal Receiver Delegate for the Universal Profile" const deployUniversalProfileURD = async () => { // create an instance of the LSP1UniversalReceiverDelegateUP const universalProfileURD = new web3.eth.Contract( LSP1UniversalReceiverDelegateUP.abi, ); let universalProfileURDAddress; // deploy the Universal Receiver Delegate UP contract await universalProfileURD .deploy({ data: LSP1UniversalReceiverDelegateUP.bytecode, }) .send({ from: EOA.address, gas: 5_000_000, gasPrice: '1000000000', }) .on('receipt', (receipt) => { universalProfileURDAddress = receipt.contractAddress; }); return universalProfileURDAddress; }; // deploy a new Universal Profile URD and retrieve its address const universalProfileURDAddress = await deployUniversalProfileURD(); ``` ## Step 3 - Set the address of the URD in the storage After deploying the contract, we need to set its address under the **[LSP1-UniversalReceiverDelegate Data Key](/standards/accounts/lsp1-universal-receiver.md#extension)** and grant it the **[SUPER_SETDATA](/standards/access-control/lsp6-key-manager.md#super-permissions)** permission. ### Create an UP contract instance Firstly we need to create an instance for the [**Universal Profile**](/standards/accounts/lsp0-erc725account.md) contract. ```typescript title="Contract instance for the Universal Profile" // create an instance of the Universal Profile const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); ``` ```typescript title="Contract instance for the Universal Profile" // create an instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); ``` ### Register URD on the UP + set the URD permissions Generate _Data Keys & Values_ for [**adding a URD**](/standards/accounts/lsp1-universal-receiver-delegate.md#how-delegation-works) to the Universal Profile and for granting [**SUPER_SETDATA**](/standards/access-control/lsp6-key-manager.md#super-permissions) permission to the **URD**. ```typescript title="Encode Data Keys & Values for updating the URD and its permissions" import { ERC725 } from '@erc725/erc725.js'; const addressPermissionsOldArrayLengthHex = await universalProfile[ 'getData(bytes32)' ](ERC725YDataKeys.LSP6['AddressPermissions[]'].length); const addressPermissionsNewArrayLength = ethers.toBigInt(addressPermissionsOldArrayLengthHex) + ethers.toBigInt(1); const addressPermissionsNewArrayLengthHex = '0x' + addressPermissionsNewArrayLength.toString(16).padStart(32, '0'); // create bytes32 permission value for the LSP1 Delegate const lsp1DelegatePermissions = ERC725.encodePermissions({ SUPER_SETDATA: true, REENTRANCY: true, }); // bytes16 index `addressPermissionsOldArrayLengthHex` will serve as index const newElementIndexInArrayHex = addressPermissionsOldArrayLengthHex.substring(2); const dataKeys = [ URD_DATA_KEY, ERC725YDataKeys.LSP6['AddressPermissions[]'].length, ERC725YDataKeys.LSP6['AddressPermissions[]'].index + newElementIndexInArrayHex, ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + universalProfileURDAddress.substring(2), ]; const dataValues = [ universalProfileURDAddress, addressPermissionsNewArrayLengthHex, universalProfileURDAddress, lsp1DelegatePermissions, ]; ``` ```typescript title="Encode Data Keys & Values for updating the URD and its permissions" import { ERC725 } from '@erc725/erc725.js'; const addressPermissionsOldArrayLengthHex = await universalProfile.methods[ 'getData(bytes32)' ](ERC725YDataKeys.LSP6['AddressPermissions[]'].length).call(); const addressPermissionsNewArrayLength = web3.utils.hexToNumber(addressPermissionsOldArrayLengthHex) + 1; const addressPermissionsNewArrayLengthHex = web3.utils.padLeft( web3.utils.numberToHex(addressPermissionsNewArrayLength), 32, ); // create bytes32 permission value for the LSP1 Delegate const lsp1DelegatePermissions = ERC725.encodePermissions({ SUPER_SETDATA: true, REENTRANCY: true, }); // bytes16 index `addressPermissionsOldArrayLengthHex` will serve as index const newElementIndexInArrayHex = addressPermissionsOldArrayLengthHex.substring(2); const dataKeys = [ URD_DATA_KEY, ERC725YDataKeys.LSP6['AddressPermissions[]'].length, ERC725YDataKeys.LSP6['AddressPermissions[]'].index + newElementIndexInArrayHex, ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + universalProfileURDAddress.substring(2), ]; const dataValues = [ universalProfileURDAddress, addressPermissionsNewArrayLengthHex, universalProfileURDAddress, lsp1DelegatePermissions, ]; ``` ### Set the URD and its permissions Lastly, we need to send the transaction that will update the URD and its permissions on the Universal Profile. ```typescript title="Update the data on the Universal Profile" // update the Universal Profile data await universalProfile.connect(EOA).setDataBatch(dataKeys, dataValues); ``` ```typescript title="Update the data on the Universal Profile" // update the Universal Profile data await universalProfile.methods.setDataBatch(dataKeys, dataValues).send({ from: EOA.address, gasLimit: 600_000, }); ``` ### Final code ```typescript title="Update the URD of the Universal Profile and its permissions" import { ERC725 } from '@erc725/erc725.js'; const updateUniversalProfileURD = async (universalProfileURDAddress) => { // create an instance of the Universal Profile const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); const addressPermissionsOldArrayLengthHex = await universalProfile[ 'getData(bytes32)' ](ERC725YDataKeys.LSP6['AddressPermissions[]'].length); const addressPermissionsNewArrayLength = ethers.toBigInt(addressPermissionsOldArrayLengthHex) + ethers.toBigInt(1); const addressPermissionsNewArrayLengthHex = '0x' + addressPermissionsNewArrayLength.toString(16).padStart(32, '0'); // create bytes32 permission value for the LSP1 Delegate const lsp1DelegatePermissions = ERC725.encodePermissions({ SUPER_SETDATA: true, REENTRANCY: true, }); // bytes16 index `addressPermissionsOldArrayLengthHex` will serve as index const newElementIndexInArrayHex = addressPermissionsOldArrayLengthHex.substring(2); const dataKeys = [ URD_DATA_KEY, ERC725YDataKeys.LSP6['AddressPermissions[]'].length, ERC725YDataKeys.LSP6['AddressPermissions[]'].index + newElementIndexInArrayHex, ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + universalProfileURDAddress.substring(2), ]; const dataValues = [ universalProfileURDAddress, addressPermissionsNewArrayLengthHex, universalProfileURDAddress, lsp1DelegatePermissions, ]; // update the Universal Profile data await universalProfile.connect(EOA).setDataBatch(dataKeys, dataValues); }; // update the URD of the Universal profile await updateUniversalProfileURD(universalProfileURDAddress); ``` ```typescript title="Update the URD of the Universal Profile and its permissions" import { ERC725 } from '@erc725/erc725.js'; const updateUniversalProfileURD = async (universalProfileURDAddress) => { // create an instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); const addressPermissionsOldArrayLengthHex = await universalProfile.methods[ 'getData(bytes32)' ](ERC725YDataKeys.LSP6['AddressPermissions[]'].length).call(); const addressPermissionsNewArrayLength = web3.utils.hexToNumber(addressPermissionsOldArrayLengthHex) + 1; const addressPermissionsNewArrayLengthHex = web3.utils.padLeft( web3.utils.numberToHex(addressPermissionsNewArrayLength), 32, ); // create bytes32 permission value for the LSP1 Delegate const lsp1DelegatePermissions = ERC725.encodePermissions({ SUPER_SETDATA: true, REENTRANCY: true, }); // bytes16 index `addressPermissionsOldArrayLengthHex` will serve as index const newElementIndexInArrayHex = addressPermissionsOldArrayLengthHex.substring(2); const dataKeys = [ URD_DATA_KEY, ERC725YDataKeys.LSP6['AddressPermissions[]'].length, ERC725YDataKeys.LSP6['AddressPermissions[]'].index + newElementIndexInArrayHex, ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + universalProfileURDAddress.substring(2), ]; const dataValues = [ universalProfileURDAddress, addressPermissionsNewArrayLengthHex, universalProfileURDAddress, lsp1DelegatePermissions, ]; // update the Universal Profile data await universalProfile.methods.setDataBatch(dataKeys, dataValues).send({ from: EOA.address, gasLimit: 600_000, }); }; // update the URD of the Universal profile await updateUniversalProfileURD(universalProfileURDAddress); ``` ## Final code - Deploy & Update ```typescript title="Deploy a Universal Profile URD, update its permissions and add it to the Universal Profile" import LSP1UniversalReceiverDelegateUP from '@lukso/lsp-smart-contracts/artifacts/LSP1UniversalReceiverDelegateUP.json'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { ERC725YDataKeys, PERMISSIONS, } from '@lukso/lsp-smart-contracts/constants.js'; import { ethers } from 'ethers'; import { ERC725 } from '@erc725/erc725.js'; // constants const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const URD_DATA_KEY = ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate; const universalProfileAddress = '0x...'; // setup your EOA const privateKey = '0x...'; // your EOA private key (controller address) const EOA = new ethers.Wallet(privateKey).connect(provider); const deployUniversalProfileURD = async () => { // create a LSP1UniversalReceiverDelegateUP Contract Factory let universalProfileURDFactory = new ethers.ContractFactory( LSP1UniversalReceiverDelegateUP.abi, LSP1UniversalReceiverDelegateUP.bytecode, ); // deploy the Universal Receiver Delegate UP contract const universalProfileURD = await universalProfileURDFactory .connect(EOA) .deploy(); return testnetuniversalProfileURD.address; }; const updateUniversalProfileURD = async (universalProfileURDAddress) => { // create an instance of the Universal Profile const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); const addressPermissionsOldArrayLengthHex = await universalProfile[ 'getData(bytes32)' ](ERC725YDataKeys.LSP6['AddressPermissions[]'].length); const addressPermissionsNewArrayLength = ethers.toBigInt(addressPermissionsOldArrayLengthHex) + ethers.toBigInt(1); const addressPermissionsNewArrayLengthHex = '0x' + addressPermissionsNewArrayLength.toString(16).padStart(64, '0'); // create bytes32 permission value for the LSP1 Delegate const lsp1DelegatePermissions = ERC725.encodePermissions({ SUPER_SETDATA: true, REENTRANCY: true, }); // bytes16 index `addressPermissionsOldArrayLengthHex` will serve as index const newElementIndexInArrayHex = addressPermissionsOldArrayLengthHex.substring(2); const dataKeys = [ URD_DATA_KEY, ERC725YDataKeys.LSP6['AddressPermissions[]'].length, ERC725YDataKeys.LSP6['AddressPermissions[]'].index + newElementIndexInArrayHex, ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + universalProfileURDAddress.substring(2), ]; const dataValues = [ universalProfileURDAddress, addressPermissionsNewArrayLengthHex, universalProfileURDAddress, lsp1DelegatePermissions, ]; // update the Universal Profile data await universalProfile.connect(EOA).setDataBatch(dataKeys, dataValues); }; // deploy a new Universal Profile URD and retrieve its address const universalProfileURDAddress = await deployUniversalProfileURD(); // update the URD of the Universal profile await updateUniversalProfileURD(universalProfileURDAddress); ``` ```typescript title="Deploy a Universal Profile URD, update its permissions and add it to the Universal Profile" import LSP1UniversalReceiverDelegateUP from '@lukso/lsp-smart-contracts/artifacts/LSP1UniversalReceiverDelegateUP.json'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { ERC725YDataKeys, PERMISSIONS, } from '@lukso/lsp-smart-contracts/constants.js'; import Web3 from 'web3'; import { ERC725 } from '@erc725/erc725.js'; // constants const web3 = new Web3('https://rpc.testnet.lukso.network'); const URD_DATA_KEY = ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate; const universalProfileAddress = '0x...'; // setup your EOA const privateKey = '0x...'; const EOA = web3.eth.accounts.wallet.add(privateKey); const deployUniversalProfileURD = async () => { // create an instance of the LSP1UniversalReceiverDelegateUP const universalProfileURD = new web3.eth.Contract( LSP1UniversalReceiverDelegateUP.abi, ); let universalProfileURDAddress; // deploy the Universal Receiver Delegate UP contract await universalProfileURD .deploy({ data: LSP1UniversalReceiverDelegateUP.bytecode, }) .send({ from: EOA.address, gas: 5_000_000, gasPrice: '1000000000', }) .on('receipt', (receipt) => { universalProfileURDAddress = receipt.contractAddress; }); return universalProfileURDAddress; }; const updateUniversalProfileURD = async (universalProfileURDAddress) => { // create an instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); const addressPermissionsOldArrayLengthHex = await universalProfile.methods[ 'getData(bytes32)' ](ERC725YDataKeys.LSP6['AddressPermissions[]'].length).call(); const addressPermissionsNewArrayLength = web3.utils.hexToNumber(addressPermissionsOldArrayLengthHex) + 1; const addressPermissionsNewArrayLengthHex = web3.utils.padLeft( web3.utils.numberToHex(addressPermissionsNewArrayLength), 32, ); // create bytes32 permission value for the LSP1 Delegate const lsp1DelegatePermissions = ERC725.encodePermissions({ SUPER_SETDATA: true, REENTRANCY: true, }); // bytes16 index `addressPermissionsOldArrayLengthHex` will serve as index const newElementIndexInArrayHex = addressPermissionsOldArrayLengthHex.substring(2); const dataKeys = [ URD_DATA_KEY, ERC725YDataKeys.LSP6['AddressPermissions[]'].length, ERC725YDataKeys.LSP6['AddressPermissions[]'].index + newElementIndexInArrayHex, ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + universalProfileURDAddress.substring(2), ]; const dataValues = [ universalProfileURDAddress, addressPermissionsNewArrayLengthHex, universalProfileURDAddress, lsp1DelegatePermissions, ]; // update the Universal Profile data await universalProfile.methods.setDataBatch(dataKeys, dataValues).send({ from: EOA.address, gasLimit: 600_000, }); }; // deploy a new Universal Profile URD and retrieve its address const universalProfileURDAddress = await deployUniversalProfileURD(); // update the URD of the Universal profile await updateUniversalProfileURD(universalProfileURDAddress); ``` --- --- sidebar_label: 'Create a Vault' sidebar_position: 2 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Create a Vault :::caution Disclaimer This guide might contain outdated information and will be updated soon. ::: This guide will teach you how to deploy an **[LSP9Vault](../../contracts/contracts/LSP9Vault/LSP9Vault.md)** contract. This contract can be used to **hold assets** such as tokens and NFTs. Also can be used with a [UniversalProfile](../../standards/accounts/introduction.md) and a [KeyManager](../../standards/access-control/lsp6-key-manager.md) to **restrict some addresses** (protocols, friends, etc..) to execute and setData on it, instead of setting or executing directly on the profile. ## Deploy an LSP9Vault contract To start with this guide you will need the following things: - The _private key_ of your account, in order to send the transaction. - The address of a [**Universal Profile**](../../standards/accounts/lsp0-erc725account.md) Make sure you have the following dependencies installed before beginning this tutorial: - Either [`web3.js`](https://github.com/web3/web3.js) or [`ethers.js`](https://github.com/ethers-io/ethers.js/) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) ```shell title="Install the dependencies" npm install web3 @lukso/lsp-smart-contracts ``` ```shell title="Install the dependencies" npm install ethers @lukso/lsp-smart-contracts ``` ## Step 1 - Setup imports and constants​ For the imports, we will need the `LSP9vault` contract **ABI** and **bytecode** in order to deploy a LSP9 Vault. For the constants we will need the _private key_ and _the address of the vault receiver_. ```typescript title="Imports & Constants" import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import Web3 from 'web3'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const vaultOwner = '0x...'; // The address that will be the vault owner // initialize your EOA const privateKey = '0x...'; const myEOA = web3.eth.accounts.wallet.add(privateKey); ``` ```typescript title="Imports & Constants" import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import { ethers } from 'ethers'; const provider = new ethers.providers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const vaultOwner = '0x...'; // The address that will be the vault owner // setup your EOA const privateKey = '0x...'; const myEOA = new ethers.Wallet(privateKey).connect(provider); ``` ## Step 2 - Instantiate contracts Create instance for `LSP9Vault`, that is needed in order to deploy the contract. ```typescript title="Contract instance" // create an instance of the LSP9Vault contract let myVault = new web3.eth.Contract(LSP9Vault.abi); ``` ```typescript title="Contract instance" // create an factory for the LSP9Vault contract let vaultFactory = new ethers.ContractFactory( LSP9Vault.abi, LSP9Vault.bytecode, ); ``` ## Step 3 - Send transaction Finally send the **contract deployment** transaction. ```typescript title="Sending contract deployment transaction" // deploy the vault contract await myVault .deploy({ data: LSP9Vault.bytecode, arguments: [vaultOwner], }) .send({ from: myEOA.address, gas: 5_000_000, gasPrice: '1000000000', }); ``` ```typescript title="Sending contract deployment transaction" // deploy the vault contract const myVault = await vaultFactory.connect(myEOA).deploy(vaultOwner); ``` ## Final Code :::caution You need to have LYXt in your EOA in order to pay for the transaction fees. Visit the :arrow_right: **[LUKSO Testnet Faucet Website](https://faucet.testnet.lukso.network/)** to get some LYXt. ::: ```typescript title="Deploying the vault" import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import Web3 from 'web3'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const vaultOwner = '0x...'; // The address that will be the vault owner // initialize your EOA const privateKey = '0x...'; const myEOA = web3.eth.accounts.wallet.add(privateKey); // create an instance of the LSP9Vault contract let myVault = new web3.eth.Contract(LSP9Vault.abi); // deploy the vault contract await myVault .deploy({ data: LSP9Vault.bytecode, arguments: [vaultOwner], }) .send({ from: myEOA.address, gas: 5_000_000, gasPrice: '1000000000', }); ``` ```typescript title="Deploying the vault" import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import { ethers } from 'ethers'; const provider = new ethers.providers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const vaultOwner = '0x...'; // The address that will be the vault owner // setup your EOA const privateKey = '0x...'; const myEOA = new ethers.Wallet(privateKey).connect(provider); // create an factory for the LSP9Vault contract let vaultFactory = new ethers.ContractFactory( LSP9Vault.abi, LSP9Vault.bytecode, ); // deploy the vault contract const myVault = await vaultFactory.connect(myEOA).deploy(vaultOwner); ``` --- --- sidebar_label: 'Edit Vault Data' sidebar_position: 3 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Edit Vault Data :::caution Disclaimer This guide might contain outdated information and will be updated soon. ::: This guide will teach you how to set data to an **[LSP9Vault](/contracts/contracts/LSP9Vault/LSP9Vault.md)** contract through a UniversalProfile owned by an LSP6KeyManager. Any data can be attached to the vault, and since it supports the **[LSP1-UniversalReceiver](/standards/accounts/lsp1-universal-receiver.md)** standard, we will set the [**Universal Receiver Delegate**](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateVault) address inside the storage. ## Setting Data (Universal Receiver Delegate) The default implementation of the **Universal Receiver Delegate** of the Vault that we will deploy will register the assets received to the storage and and will remove them when their balance equals 0. ## Setup Make sure you have the following dependencies installed before beginning this tutorial: - Either [`web3.js`](https://github.com/web3/web3.js) or [`ethers.js`](https://github.com/ethers-io/ethers.js/) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) ```shell npm install web3 @lukso/lsp-smart-contracts ``` ```shell npm install ethers @lukso/lsp-smart-contracts ``` ## Step 1 - Imports, constants and EOA For starters we need to get the _ABIs_ for the contracts that we will use and the _bytecode_ for the `LSP1UniversalReceiverDelegateVault`. After that we need to store the address of our LSP9 Vault and our Universal Profile. Then we will initialize the EOA that we will further use. ```typescript import LSP1UniversalReceiverDelegateVault from '@lukso/lsp-smart-contracts/artifacts/LSP1UniversalReceiverDelegateVault.json'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; import Web3 from 'web3'; // constants const web3 = new Web3('https://rpc.testnet.lukso.network'); const vaultAddress = '0x...'; const universalProfileAddress = '0x...'; // setup your EOA const privateKey = '0x...'; const myEOA = web3.eth.accounts.wallet.add(privateKey); ``` ```typescript import LSP1UniversalReceiverDelegateVault from '@lukso/lsp-smart-contracts/artifacts/LSP1UniversalReceiverDelegateVault.json'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; import { ethers } from 'ethers'; // constants const provider = new ethers.providers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const vaultAddress = '0x...'; const universalProfileAddress = '0x...'; // setup your EOA const privateKey = '0x...'; // your EOA private key (controller address) const myEOA = new ethers.Wallet(privateKey).connect(provider); ``` ## Step 2 - Deploying Universal Receiver Delegate (URD) :::info The **Universal Profile** and the **Vault** don't use the same implementation of the Universal Receiver Delegate. ::: ### Create a contract instance At this step we will create an instance of the Vault URD that we will further be used to deploy one. ```typescript // create an instance of the LSP1UniversalReceiverDelegateVault const vaultURD = new web3.eth.Contract(LSP1UniversalReceiverDelegateVault.abi); ``` ```typescript // create a LSP1UniversalReceiverDelegateVault Contract Factory const vaultURDFactory = new ethers.ContractFactory( LSP1UniversalReceiverDelegateVault.abi, LSP1UniversalReceiverDelegateVault.bytecode, ); ``` ### Send the contract deployment transaction Send the deployment transaction and in a few seconds you will get a new deployed Vault URD. ```typescript // deploy the Universal Receiver Delegate Vault contract await vaultURD .deploy({ data: LSP1UniversalReceiverDelegateVault.bytecode, }) .send({ from: myEOA.address, gas: '5000000', gasPrice: '1000000000', }); ``` ```typescript // deploy the Universal Receiver Delegate Vault contract const vaultURD = await vaultURDFactory.connect(myEOA).deploy(); ``` ### Final code ```typescript const deployVaultURD = async () => { // create an instance of the LSP1UniversalReceiverDelegateVault const vaultURD = new web3.eth.Contract( LSP1UniversalReceiverDelegateVault.abi, ); let vaultURDAddress; // deploy the Universal Receiver Delegate Vault contract await vaultURD .deploy({ data: LSP1UniversalReceiverDelegateVault.bytecode, }) .send({ from: myEOA.address, gas: '5000000', gasPrice: '1000000000', }) .on('receipt', (receipt) => (vaultURDAddress = receipt.contractAddress)); return vaultURDAddress; }; // deploy a new Vault URD and retrieve its address const vaultURDAddress = await deployVaultURD(); ``` ```typescript const deployVaultURD = async () => { // create a LSP1UniversalReceiverDelegateVault Contract Factory const vaultURDFactory = new ethers.ContractFactory( LSP1UniversalReceiverDelegateVault.abi, LSP1UniversalReceiverDelegateVault.bytecode, ); // deploy the Universal Receiver Delegate Vault contract const vaultURD = await vaultURDFactory.connect(myEOA).deploy(); // get back the transaction data when deployed const transactionReceipt = await vaultURD.deployTransaction.wait(); // return the address of the Vault URD return transactionReceipt.contractAddress; }; // deploy a new Vault URD and retrieve its address const vaultURDAddress = await deployVaultURD(); ``` ## Step 3 - Setting the URD address in the storage The Vault's owner could be an **EOA**, or any **other smart contract**. In our case, we will suppose that the Vault's owner is a [Universal Profile](/standards/accounts/introduction.md) that is controlled by a Key Manager. ### Create the contract instances Firstly we need to create instances for the following contracts: - [**Vault**](/standards/accounts/lsp9-vault.md) - [**Universal Profile**](/standards/accounts/lsp0-erc725account.md) ```typescript // create an instance of the LSP9Vault const vault = new web3.eth.Contract(LSP9Vault.abi, vaultAddress); // create an instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); ``` ```typescript // create an instance of the LSP9Vault const vault = new ethers.Contract(vaultAddress, LSP9Vault.abi); // create an instance of the Universal Profile const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); ``` ### Encode `setData(..)` calldata Secondly, we need to encode a calldata that will update the address of the Vault URD. ```typescript // encode setData Calldata on the Vault const setDataCalldata = await vault.methods .setData(ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, vaultURDAddress) .encodeABI(); // Any other information can be stored here ``` ```typescript // encode setData Calldata on the Vault const setDataCalldata = vault.interface.encodeFunctionData('setData', [ ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, vaultURDAddress, ]); // Any other information can be stored here ``` ### Update the Vault data Lastly, we need to send the transaction that will update the Vault data through the Universal Profile's `execute(..)`. ```typescript // execute the `setData(bytes32,bytes)` calldata that updates the Vault data await universalProfile.methods .execute( 0, // OPERATION CALL vaultAddress, 0, // value to transfer setDataCalldata, ) .send({ from: myEOA.address, gasLimit: 600_000, }); ``` ```typescript // execute the `setData(bytes32,bytes)` calldata that updates the Vault data await universalProfile.connect(myEOA).execute( 0, // OPERATION CALL vaultAddress, 0, // value to transfer setDataCalldata, ); ``` ### Final code ```typescript const updateVaultURD = async (vaultURDAddress) => { // create an instance of the LSP9Vault const vault = new web3.eth.Contract(LSP9Vault.abi, vaultAddress); // create an instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); // encode setData Calldata on the Vault const setDataCalldata = await vault.methods .setData( ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, vaultURDAddress, ) .encodeABI(); // Any other information can be stored here // execute the `setDataCalldata` that updates the Vault data await universalProfile.methods .execute( 0, // OPERATION CALL vaultAddress, 0, // value to transfer setDataCalldata, ) .send({ from: myEOA.address, gasLimit: 600_000, }); }; // update the current Vault's URD await updateVaultURD(vaultURDAddress); ``` ```typescript const updateVaultURD = async (vaultURDAddress) => { // create an instance of the LSP9Vault const vault = new ethers.Contract(vaultAddress, LSP9Vault.abi); // create an instance of the Universal Profile const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); // encode setData Calldata on the Vault const setDataCalldata = vault.interface.encodeFunctionData('setData', [ ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, vaultURDAddress, ]); // Any other information can be stored here // execute the `setDataCalldata` that updates the Vault data await universalProfile.connect(myEOA).execute( 0, // OPERATION CALL vaultAddress, 0, // value to transfer setDataCalldata, ); }; // update the current Vault's URD await updateVaultURD(vaultURDAddress); ``` ## Final code - Deploy & Update ```typescript title="Deploy new Vault URD and update Vault's URD" import LSP1UniversalReceiverDelegateVault from '@lukso/lsp-smart-contracts/artifacts/LSP1UniversalReceiverDelegateVault.json'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; import Web3 from 'web3'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const vaultAddress = '0x...'; const universalProfileAddress = '0x...'; // setup your EOA const privateKey = '0x...'; const myEOA = web3.eth.accounts.wallet.add(privateKey); const deployVaultURD = async () => { // create an instance of the LSP1UniversalReceiverDelegateVault const vaultURD = new web3.eth.Contract( LSP1UniversalReceiverDelegateVault.abi, ); let vaultURDAddress; // deploy the Universal Receiver Delegate Vault contract await vaultURD .deploy({ data: LSP1UniversalReceiverDelegateVault.bytecode, }) .send({ from: myEOA.address, gas: '5000000', gasPrice: '1000000000', }) .on('receipt', (receipt) => (vaultURDAddress = receipt.contractAddress)); return vaultURDAddress; }; const updateVaultURD = async (vaultURDAddress) => { // create an instance of the LSP9Vault const vault = new web3.eth.Contract(LSP9Vault.abi, vaultAddress); // create an instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); // encode setData Calldata on the Vault const setDataCalldata = await vault.methods .setData( ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, vaultURDAddress, ) .encodeABI(); // Any other information can be stored here // execute the `setDataCalldata` that updates the Vault data await universalProfile.methods .execute( 0, // OPERATION CALL vaultAddress, 0, // value to transfer setDataCalldata, ) .send({ from: myEOA.address, gasLimit: 600_000, }); }; // deploy a new Vault URD and retrieve its address const vaultURDAddress = await deployVaultURD(); // update the current Vault's URD await updateVaultURD(vaultURDAddress); ``` ```typescript import LSP1UniversalReceiverDelegateVault from '@lukso/lsp-smart-contracts/artifacts/LSP1UniversalReceiverDelegateVault.json'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; import { ethers } from 'ethers'; const provider = new ethers.providers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const vaultAddress = '0x...'; const universalProfileAddress = '0x...'; // setup your EOA const privateKey = '0x...'; // your EOA private key (controller address) const myEOA = new ethers.Wallet(privateKey).connect(provider); const deployVaultURD = async () => { // create a LSP1UniversalReceiverDelegateVault Contract Factory const vaultURDFactory = new ethers.ContractFactory( LSP1UniversalReceiverDelegateVault.abi, LSP1UniversalReceiverDelegateVault.bytecode, ); // deploy the Universal Receiver Delegate Vault contract const vaultURD = await vaultURDFactory.connect(myEOA).deploy(); return vaultURD.address; }; const updateVaultURD = async (vaultURDAddress) => { // create an instance of the LSP9Vault const vault = new web3.eth.Contract(LSP9Vault.abi, vaultAddress); // create an instance of the Universal Profile const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); // encode setData Calldata on the Vault const setDataCalldata = await vault.methods .setData( ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, vaultURDAddress, ) .encodeABI(); // Any other information can be stored here // execute the `setDataCalldata` that updates the Vault data await universalProfile.connect(myEOA).execute( 0, // OPERATION CALL vaultAddress, 0, // value to transfer setDataCalldata, ); }; // deploy a new Vault URD and retrieve its address const vaultURDAddress = await deployVaultURD(); // update the current Vault's URD await updateVaultURD(vaultURDAddress); ``` ## Reading Data The **LSP9Vault** contract is an **ERC725** contract, so it shares the same way to read data as Universal Profiles and other ERC725 contracts by using **[erc725.js](/tools/dapps/erc725js/getting-started.md)**. You can refer to the **[Read Profile Data Guide](/learn/universal-profile/metadata/read-profile-data)** to learn how to **fetch data** like received or issued assets from [ERC725Y Storage](/standards/erc725#erc725y-generic-data-keyvalue-store). However, please note that the **Universal Profile** address has to be exchanged with the **Vault's** address. --- --- sidebar_label: 'Grant Vault Permissions' sidebar_position: 2 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Grant Vault Permissions :::caution Disclaimer This guide might contain outdated information and will be updated soon. ::: As mentioned in the [first Vault guide](./create-a-vault.md), the **Vault** can be used to restrict different addresses (protocols, other devices, etc..) to execute and set data on it instead of doing it directly on the Universal Profile. This way, when **granting a third party permissions** to execute through your profile, this third party will only be able to interact with the Vault, and all the other assets will be safe. ## Granting Permission to 3rd Parties :::note Make sure not to grant the 3rd party address the **SUPER Permissions**. Otherwise, the **AllowedCalls restriction** will not work. ::: Check the guide of **[granting permissions to 3rd Parties](../universal-profile/key-manager/grant-permissions.md)**, and make sure to grant the 3rd party address the **CALL Permission**. ## Use AllowedCalls permission for the 3rd Parties In this guide, after granting the 3rd party the permission **CALL**, we will need to **allow the address of the 3rd party** to interact with the **Vault address**. We will be using the [AllowedCalls permission](../../standards/access-control/lsp6-key-manager.md#allowed-calls) from the Key Manager. ## Setup Make sure you have the following dependencies installed before beginning this tutorial. - You can use either [`web3.js`](https://github.com/web3/web3.js) or [`ethers.js`](https://github.com/ethers-io/ethers.js/) - You MUST install [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) - You SHOULD install [`@erc725/erc725.js`](https://github.com/ERC725Alliance/erc725.js) ```shell title="Install the dependencies" npm install web3 @lukso/lsp-smart-contracts @erc725/erc725.js ``` ```shell title="Install the dependencies" npm install ethers @lukso/lsp-smart-contracts @erc725/erc725.js ``` ## Step 1 - Imports, Constants & EOA For this guide we will firstly need and import the _ABIs_ for the Universal Profile & Key Manager contracts. Also we will import the `ERC725YDataKeys` to retrieve the data key for [AllowedCalls permission](../../standards/access-control/lsp6-key-manager.md#allowed-calls). As constants we will need to store the addresses for the Universal Profile, Vault & the restricted third party. Finally, we will need a private key with the proper _permissions_, in our case [**ADDCONTROLLER permission**](../../standards/access-control/lsp6-key-manager.md#permissions). ```typescript title="Imports, Constants & EOA initialization" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts/constants.js'; import { encodeKey } from '@erc725/erc725.js/build/main/src/lib/utils.js'; import Web3 from 'web3'; // constants const web3 = new Web3('https://rpc.testnet.lukso.network'); const universalProfileAddress = '0x..'; // address of the UP const vaultAddress = '0x..'; // address of the Vault const thirdPartyAddress = '0x..'; // address of the third party you want to restrict // setup your EOA const privateKey = '0x...'; const myEOA = web3.eth.accounts.wallet.add(privateKey); ``` ```typescript title="Imports, Constants & EOA initialization" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts/constants.js'; import { encodeKey } from '@erc725/erc725.js/build/main/src/lib/utils.js'; import { ethers } from 'ethers'; // constants const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const universalProfileAddress = '0x..'; // address of the UP const vaultAddress = '0x..'; // address of the Vault const thirdPartyAddress = '0x..'; // address of the third party you want to restrict // setup your EOA const privateKey = '0x...'; // your EOA private key (controller address) const myEOA = new ethers.Wallet(privateKey).connect(provider); ``` ## Step 2 - Create UP contract instance At this point we will create instance for the [**Universal Profile**](../../standards/accounts/lsp0-erc725account.md) contract. ```typescript title="Universal Profile contract instance" // create an instance of the UP const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); ``` ```typescript title="Universal Profile contract instance" // create an instance of the UP const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); ``` ## Step 3 - Generate the data key-value pair for [`AllowedCalls`](../../standards/access-control/lsp6-key-manager.md#allowed-calls) Now we need to generate a data key & a data value for the **Allowed Calls** that we want for the _Third Party address_. After we do that, we will update the _Allowed Calls data key_ with the encoded **Allowed Calls** ```typescript title="Data key & value for updating the Allowed Calls of a Controller address" const allowedCallsDataKey = // constructing the data key of allowed addresses ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + thirdPartyAddress.substring(2); // of the 3rd party const allowedCallsSchema = { name: 'AddressPermissions:AllowedCalls:
', key: '0x4b80742de2bf393a64c70000
', keyType: 'MappingWithGrouping', valueType: '(bytes4,address,bytes4)[CompactBytesArray]', valueContent: '(Bytes4,Address,Bytes4)', }; const allowedCallsDataValue = encodeKey(allowedCallsSchema, [ '0xffffffff', vaultAddress, '0xffffffff', ]); ``` ```typescript title="Data key & value for updating the Allowed Calls of a Controller address" const allowedCallsDataKey = // constructing the data key of allowed addresses ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + thirdPartyAddress.substring(2); // of the 3rd party const allowedCallsSchema = { name: 'AddressPermissions:AllowedCalls:
', key: '0x4b80742de2bf393a64c70000
', keyType: 'MappingWithGrouping', valueType: '(bytes4,address,bytes4)[CompactBytesArray]', valueContent: '(Bytes4,Address,Bytes4)', }; const allowedCallsDataValue = encodeKey(allowedCallsSchema, [ '0xffffffff', vaultAddress, '0xffffffff', ]); ``` ## Step 4 - Update the Universal profile data Finally we will send a transaction that will update the Universal Profile AllowedCalls data key with the newly generated AllowedCalls. ```typescript title="Set the data key on the Universal Profile" // Set the AllowedCalls data key on the Universal Profile await universalProfile.methods.setData( allowedCallsDataKey, allowedCallsDataValue, ).send({ from: myEOA.address, gasLimit: 600_000, }); ``` ```typescript title="Set the data key on the Universal Profile" // Set the AllowedCalls data key on the Universal Profile await universalProfile .connect(myEOA) .setData(allowedCallsDataKey, allowedCallsDataValue); ``` ## Final code ```typescript title="Setting Allowed Addresses for the 3rd party address" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts/constants.js'; import { encodeKey } from '@erc725/erc725.js/build/main/src/lib/utils.js'; import Web3 from 'web3'; // constants const web3 = new Web3('https://rpc.testnet.lukso.network'); const universalProfileAddress = '0x..'; // address of the UP const vaultAddress = '0x..'; // address of the Vault const thirdPartyAddress = '0x..'; // address of the third party you want to restrict // setup your EOA const privateKey = '0x...'; const myEOA = web3.eth.accounts.wallet.add(privateKey); // create an instance of the UP const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); const allowedCallsDataKey = // constructing the data key of allowed addresses ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + thirdPartyAddress.substring(2); // of the 3rd party const allowedCallsSchema = { name: 'AddressPermissions:AllowedCalls:
', key: '0x4b80742de2bf393a64c70000
', keyType: 'MappingWithGrouping', valueType: '(bytes4,address,bytes4)[CompactBytesArray]', valueContent: '(Bytes4,Address,Bytes4)', }; const allowedCallsDataValue = encodeKey(allowedCallsSchema, [ '0xffffffff', vaultAddress, '0xffffffff', ]); // Set the AllowedCalls data key on the Universal Profile await universalProfile.methods.setData( allowedCallsDataKey, allowedCallsDataValue, ).send({ from: myEOA.address, gasLimit: 600_000, }); ``` ```typescript title="Setting Allowed Addresses for the 3rd party address" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts/constants.js'; import { encodeKey } from '@erc725/erc725.js/build/main/src/lib/utils.js'; import { ethers } from 'ethers'; // constants const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const universalProfileAddress = '0x..'; // address of the UP const vaultAddress = '0x..'; // address of the Vault const thirdPartyAddress = '0x..'; // address of the third party you want to restrict // setup your EOA const privateKey = '0x...'; // your EOA private key (controller address) const myEOA = new ethers.Wallet(privateKey).connect(provider); // create an instance of the UP const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); const allowedCallsDataKey = // constructing the data key of allowed addresses ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + thirdPartyAddress.substring(2); // of the 3rd party const allowedCallsSchema = { name: 'AddressPermissions:AllowedCalls:
', key: '0x4b80742de2bf393a64c70000
', keyType: 'MappingWithGrouping', valueType: '(bytes4,address,bytes4)[CompactBytesArray]', valueContent: '(Bytes4,Address,Bytes4)', }; const allowedCallsDataValue = encodeKey(allowedCallsSchema, [ '0xffffffff', vaultAddress, '0xffffffff', ]); // Set the AllowedCalls data key on the Universal Profile await universalProfile .connect(myEOA) .setData(allowedCallsDataKey, allowedCallsDataValue); ``` --- --- sidebar_label: 'Vault Execution' sidebar_position: 4 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Interact With Contracts :::caution Disclaimer This guide might contain outdated information and will be updated soon. ::: Similar to our **[previous guide](./edit-vault-data.md)** on setting data on the Vault, in this guide, we will be learning how to **interact with other contracts** through the Vault's execute function. :::info This guide is also very similar to the guide: [**Interact with contract using a Universal Profile**](./interact-with-contracts.md). ::: **Interaction flow**: ## Setup To complete this mini-guide, we will need: - an EOA with some LYX for gas fees and the required [**permissions**](../../standards/access-control/lsp6-key-manager.md#permissions) for the interaction. - the `UniversalProfile` and `LSP9Vault` contracts ABIs from the [`@lukso/lsp-smart-contracts`](https://www.npmjs.com/package/@lukso/lsp-smart-contracts) npm package. - the address of the Universal Profile. - the address of the LSP9 Vault. - the `targetContract` ABI. - the address of the Target Contract. :::info The chosen EOA needs to have [**CALL Permission**](../../standards/access-control/lsp6-key-manager.md#permissions) together with [**AllowedCalls**](../../standards/access-control/lsp6-key-manager.md#allowed-calls) or [**SUPER_CALL Pemrission**](../../standards/access-control/lsp6-key-manager.md#super-permissions) ::: Make sure you have the following dependencies installed before beginning this tutorial. - Either [`web3.js`](https://github.com/web3/web3.js) or [`ethers.js`](https://github.com/ethers-io/ethers.js/) - [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) ```shell title="Install the dependencies" npm install web3 @lukso/lsp-smart-contracts ``` ```shell title="Install the dependencies" npm install ethers @lukso/lsp-smart-contracts ``` ## Step 1 - Setup imports & constants At this step we will import the needed **contract ABIs** and we will save all the **required addresses** in constants. Also we will initialize our **EOA** for further use. :::caution Save the Target Contract ABI in a separate json and import it in the main file. You can quickly compile and get a contract's ABI in [**Remix IDO**](https://remix.ethereum.org/) ::: ```typescript title="Imports & Constants" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import TargetContractABI from './TargetContractABI.json'; import Web3 from 'web3'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const universalProfileAddress = '0x...'; const vaultAddress = '0x...'; const targetContractAddress = '0x...'; // setup EOA const privateKey = '0x...'; // your EOA private key (controller address) const myEOA = web3.eth.accounts.wallet.add(privateKey); ``` ```typescript title="Imports & Constants" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import TargetContractABI from './TargetContractABI.json'; import { ethers } from 'ethers'; const provider = new ethers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const universalProfileAddress = '0x...'; const vaultAddress = '0x...'; const targetContractAddress = '0x...'; // setup EOA const privateKey = '0x...'; // your EOA private key (controller address) const myEOA = new ethers.Wallet(privateKey).connect(provider); ``` ## Step 2 - Create the contracts instances Further we will create instances for our contracts - Create a Universal Profile contract instance from `universalProfileAddress`. - Create a Target Contract instance from the `targetContractAddress`. ```typescript title="Contracts instances" // Create Universal Profile contract instance const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); // Create LSP9 Vault contract instance const vault = new web3.eth.Contract(LSP9Vault.abi, vaultAddress); // Create Target Contract contract instance const targetContract = new web3.eth.Contract( TargetContractABI, targetContractAddress, ); ``` ```typescript title="Contracts instances" // Create Universal Profile contract instance const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); // Create LSP9 Vault contract instance const vault = new ethers.Contract(vaultAddress, LSP9Vault.abi); // Create Target Contract contract instance const targetContract = new ethers.Contract( targetContractAddress, TargetContractABI, ); ``` ## Step 3 - Encode the calldatas This is the easy part, we need to create 2 calldatas: - The _first calldata_ will be executed on the Target Contract. - The _second calldata_ will be executed on the Vault and will trigger the _first calldata_. ### Encode Target Contract calldata Encoding the calldata that will be be executed on the Target Contract. ```typescript title="Target calldata" // 1. encode the calldata to be run at the targetContract // assuming targetContract is a Contract instance const targetCalldata = targetContract.methods .myCoolfunction('dummyParameter') .encodeABI(); ``` ```typescript title="Target calldata" // 1. encode the calldata to be run at the targetContract // assuming targetContract is a Contract instance const targetCalldata = targetContract.interface.encodeFunctionData( 'myCoolfunction', ['dummyParameter'], ); ``` ### Encode Vault calldata Encoding the calldata that will be be executed on the Vault. This calldata will also trigger the calldata that will be executed on the Target Contract. ```typescript title="Vault calldata" // 2. encode the calldata to be run on the Vault, // passing the calldata to be run at the targetContract as 4th parameter const vaultCalldata = await vault.methods .execute(0, targetContract.address, 0, targetCalldata) .encodeABI(); ``` ```typescript title="Vault calldata" // 2. encode the calldata to be run on the Vault, // passing the calldata to be run at the targetContract as 4th parameter const vaultCalldata = vault.interface.encodeFunctionData('execute', [ 0, targetContract.address, 0, targetCalldata, ]); ``` ## Step 4 - Execute the calldata through the UP The final step is to execute the encoded calldata through the Universal Profile. Since we are calling from a UP's controller address (with proper [**permissions**](../../standards/access-control/lsp6-key-manager.md#permissions)), the Key Manager will authorize the transaction. ```typescript title="Send transaction" // Execute the calldata through the Universal Profile await universalProfile.methods.execute(0, vaultAddress, 0, vaultCalldata).send({ from: myEOA.address, gasLimit: 600_000, }); ``` ```typescript title="Send transaction" // Execute the calldata through the Universal Profile await universalProfile .connect(myEOA) .execute(0, vaultAddress, 0, vaultCalldata); ``` ## Final code ```typescript title="Interacting with other contracts through the vault" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import TargetContractABI from './TargetContractABI.json'; import Web3 from 'web3'; const web3 = new Web3('https://rpc.testnet.lukso.network'); const universalProfileAddress = '0x...'; const vaultAddress = '0x...'; const targetContractAddress = '0x...'; // setup EOA const privateKey = '0x...'; // your EOA private key (controller address) const myEOA = web3.eth.accounts.wallet.add(privateKey); // Create Universal Profile contract instance const universalProfile = new web3.eth.Contract( UniversalProfile.abi, universalProfileAddress, ); // Create LSP9 Vault contract instance const vault = new web3.eth.Contract(LSP9Vault.abi, vaultAddress); // Create Target Contract contract instance const targetContract = new web3.eth.Contract( TargetContractABI, targetContractAddress, ); // 1. encode the calldata to be run at the targetContract // assuming targetContract is a Contract instance const targetCalldata = targetContract.methods .myCoolfunction('dummyParameter') .encodeABI(); // 2. encode the calldata to be run on the Vault, // passing the calldata to be run at the targetContract as 4th parameter const vaultCalldata = await vault.methods .execute(0, targetContract.address, 0, targetCalldata) .encodeABI(); // Execute the calldata through the Universal Profile await universalProfile.methods.execute(0, vaultAddress, 0, vaultCalldata).send({ from: myEOA.address, gasLimit: 600_000, }); ``` ```typescript title="Interacting with other contracts through the vault" import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; import TargetContractABI from './TargetContractABI.json'; import { ethers } from 'ethers'; const provider = new ethers.providers.JsonRpcProvider( 'https://rpc.testnet.lukso.network', ); const universalProfileAddress = '0x...'; const vaultAddress = '0x...'; const targetContractAddress = '0x...'; // setup EOA const privateKey = '0x...'; // your EOA private key (controller address) const myEOA = new ethers.Wallet(privateKey).connect(provider); // Create Universal Profile contract instance const universalProfile = new ethers.Contract( universalProfileAddress, UniversalProfile.abi, ); // Create LSP9 Vault contract instance const vault = new ethers.Contract(vaultAddress, LSP9Vault.abi); // Create Target Contract contract instance const targetContract = new ethers.Contract( targetContractAddress, TargetContractABI, ); // 1. encode the calldata to be run at the targetContract // assuming targetContract is a Contract instance const targetCalldata = targetContract.interface.encodeFunctionData( 'myCoolfunction', ['dummyParameter'], ); // 2. encode the calldata to be run on the Vault, // passing the calldata to be run at the targetContract as 4th parameter const vaultCalldata = vault.interface.encodeFunctionData('execute', [ 0, targetContractAddress, 0, targetCalldata, ]); // Execute the calldata through the Universal Profile await universalProfile .connect(myEOA) .execute(0, vaultAddress, 0, vaultCalldata); ``` In the code snippet above, we interacted with `myCoolfunction(..)` function on the **targetContract** contract through the Vault's [execute](../../contracts/contracts/LSP9Vault/LSP9Vault.md#execute) function. The call was encoded and executed through the Universal Profile. --- --- sidebar_label: 'LSP14 - Ownable 2-Step' sidebar_position: 2 description: "LUKSO's LSP14 - Ownable2Step: an extended version of EIP173 - Contract Ownership Standard for transferring and renouncing ownership." --- # LSP14 - Ownable 2-Step :::info Standard Specification [LSP14 - Ownable 2-Step](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-14-Ownable2Step.md) ::: > **Goals:** > > - Secures owner management > - Enables ownable 2-Step verification LSP14 - Ownable2Step simplifies ownership management in smart contracts through a two-step process, enhancing security and preventing accidental loss of control. Unlike instant ownership transfer, LSP14 ensures deliberate actions by requiring the new owner's acceptance, thereby minimizing risks associated with wrong addresses or lost keys. It also incorporates LSP1's universalReceiver function, enabling notifications during ownership changes, fostering transparency and communication between the previous and new owners. This standard is crucial for maintaining control over contracts, especially in scenarios where ownership carries significant power and access to sensitive functions. Through LSP14, LUKSO enhances the safety and reliability of contract ownership transitions, supporting a more secure and user-friendly blockchain ecosystem. ## Introduction In the current [EIP173 - Contract Ownership Standard](https://eips.ethereum.org/EIPS/eip-173) standard (EIP173), ownership of a contract is transferred directly in one transaction via `transferOwnership(...)`. This presents some risks. For instance if the new owner: - is an EOA that lost its private key. - is an `address` entered incorrectly. Renouncing ownership of the contract in [EIP173 - Contract Ownership Standard](https://eips.ethereum.org/EIPS/eip-173) is also done in one transaction. If the owner accidentally calls `renounceOwnership()`, this leads to losing access to the contract. What is needed is a safer mechanism for managing contract ownership. ## What does this standard represent ? **LSP14 - Ownable2Step** is an extended version of [EIP173 - Contract Ownership Standard](https://eips.ethereum.org/EIPS/eip-173) that uses a 2-step process for transferring and renouncing ownership. **LSP14 - Ownable2Step** modifies the processes of _tranferring and renouncing ownership_ in the following way: 1. For _transferring ownership_ the method `transferOwnership(...)` is modified in a way so the **address** passed as parameter will not be the owner directly but a pending owner. A new method is introduced, `acceptOwnership()`, which should be called by the **pending owner** in order for the process of _transferring ownership_ to be complete. 2. For _renouncing ownership_ the method `renounceOwnership()` is modified in the following way. The **owner** of the contract need to firstly initiate the process of _renouncing ownership_ which starts a countdown of **200 blocks** which are broken into two _distinct periods_. The **first 100 blocks** are meant to be waited, a period when one can reflect upon the desire of renouncing ownership of the contract. The **second 100 blocks** are meant for confirming the ownership renouncement process. After a total of **200 blocks** pass from the initiation, the process is restarted. In addition, this standard defines hooks that call the **[universalReceiver(...)](../../contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver)** function of the current owner and new owner, if these addresses are contracts that implement LSP1. ## Specification ### Transferring the contract ownership The control of the contract is fully transferred _once the new owner has accepted the new ownership_. The 2 steps of ownership transfer are described below: 1. The previous owner transfers ownership to a new owner via the [`transferOwnership(...)`](../../contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md#transferownership) function. 2. The new owner claims ownership of the contract by calling the [`acceptOwnership()`](../../contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md #acceptownership)` function. By making the new owner accept ownership explicitly, **LSP14 - Ownable2Step** ensures that the new owner has access to his address. #### Transfer Ownership Hook This hook is designed to _notify the new owner_ of the contract that he should accept ownership. The hook is executed whenever the owner _initiates the process of transferring ownership_ and only if the new owner is a contract that **implements LSP1**. #### Accept Ownership Hooks These hooks are designed to _notify the previous and new owner_ when ownership of the contract has been fully transferred. One hook notifies the previous owner and the second one notifies the new owner. Each hook is executed whenever the _new owner confirms the process of transferring ownership_. - The hook that notifies the previous owner is only executed if the previous owner is a contract that **implements LSP1**. - The hook that notifies the new owner is only executed if the new owner is a contract that **implements LSP1**. ### Renouncing the contract ownership The control of the contract is refully renounced _once the owner of the contract confirmes the ownership renouncement_. The 2 steps of ownership renouncement are described below: 1. The owner initiates the process of ownership renouncement via the ['renounceOwnership()'](../../contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md#renounceownership) function. 2. After waiting for 200 blocks to pass from the initiation of the ownership renouncement process the owner has a window of 200 block for confirming the renouncement via ['renounceOwnership()'](../../contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md#renounceownership). If the owner doesn't confirm in that window of time, the process cannot be confirmed and the owner must start again if it was intended to renounce ownership. --- --- sidebar_label: 'LSP6 - Key Manager' sidebar_position: 1 description: LUKSO's LSP6 - Key Manager for controlling a LUKSO LSP0ERC725Account. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # LSP6 - Key Manager :::info Standard Specification [LSP6 - Key Manager](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md) ::: > **Goal:** allow multiple permissioned addresses to control and interact with a smart contract. LSP6 - Key Manager, acts as the brain behind Universal Profiles, enabling sophisticated access control and interactions. Imagine having a digital identity that can interact with other contracts, manage assets, or even delegate actions without exposing your main account. This is where the Key Manager shines, serving as a permissioned gateway. Here's how it works: You have a Universal Profile, essentially a smart contract account on the blockchain. This account can hold assets, manage permissions, and interact with other contracts. However, by itself, it's like a locked treasure chest. The Key Manager is the key to this chest, allowing specific actions to be performed by those you trust. For instance, you can set permissions for different addresses, allowing them to perform specific actions such as sending transactions, managing assets, or setting data within your Universal Profile. This flexibility means you can have secure, controlled interactions on the blockchain, paving the way for more complex and secure applications. ## Introduction An [LSP0ERC725Account](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md) on its own comes with limited usability. Since it is an **owned contract**, only the account's owner can write data into it or use it to interact with other smart contracts. Here comes the Key Manager. A smart contract that controls a LSP0ERC725Account, acting as its new owner. It functions as a gateway for the **account** contract and allows not only one main contract owner but multiple **controllers** to interact with the LSP0ERC725Account. > **What is a _"controller"_?** > > in the LSP6 Key Manager, the term _"controller"_ refers to a **permissioned address**. These addresses **have [permissions](#permissions) that allow them to perform certain actions on the LSP0ERC725Account** linked with the Key Manager (e.g., setting data or transferring LYX from the account). > > Controllers can be Externally Owned Accounts (EOA) or smart contracts. The Key Manager will allow or restrict access based on the permissions set for the calling `address`. Controllers can interact directly with the Key Manager or [sign messages that can then be executed by any other parties](#relay-execution) (such as users or relay services). :x:   **Without a Key Manager**, only the LSP0ERC725Account's owner can use its Account. :white_check_mark:   **With a Key Manager** attached to an LSP0ERC725Account, other addresses (EOAs or contracts) can use an Account on behalf of its owner. Permissions for addresses are not stored on the Key Manager. Instead, they are **stored inside the data key-value store of the LSP0ERC725Account** linked to the Key Manager. This way, it is possible to easily **upgrade** the Key Manager without resetting all the permissions again. --- ## Permissions :::tip You can use the [`encodePermissions(...)`](/tools/dapps/erc725js/methods#encodepermissions) and [`decodePermissions(...)`](/tools/dapps/erc725js/methods#decodepermissions) functions from the [_erc725.js_](/tools/dapps/erc725js/getting-started) tool to easily **encode and decode permissions values** or **combine multiple permissions together**. ::: :::info Best Practices While the Key Manager allows for a very fine-grained control over the Universal Profile (_eg: `CALL` permission combined with [`AllowedCalls`](#allowed-calls), `SETDATA` permission combined with [`AllowedERC725YDataKeys`](#allowed-erc725y-data-keys)_), it also allows for a very coarse-grained control over the Universal Profile, due to the [`SUPER`](#super-permissions) permissions. This makes the Key Manager very flexible, but that flexibility comes with a slightly higher responsibility from the users. **Good practices:** 1. Split the permissions over the Universal Profile across different devices, hardware wallets or a combination of both. 2. Make sure to double or triple check when granting permissions to 3rd parties (other Universal Profiles, DApps, etc.). ::: Click on the toggles below to **learn more about the features enabled by each permission**.
CHANGEOWNER - Allows changing the owner of the controlled contract

value = 0x0000000000000000000000000000000000000000000000000000000000000001

The `CHANGEOWNER` permission enables to change the owner of the linked ERC725Account. Using this permission, you can easily upgrade the [`LSP6KeyManager`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md) attached to the Account by transferring ownership to a new Key Manager.
ADDCONTROLLER - Allows giving permissions to new controller addresses.

value = 0x0000000000000000000000000000000000000000000000000000000000000002

The `ADDCONTROLLER` permission enables to grant permissions to new addresses that did not have any permissions before. This allows to add new permissioned addresses (controllers) that can then interact with or use the linked ERC725Account. The `ADDCONTROLLER` permission is needed to: - Give a new address some permission(s) by setting its permissions under `AddressPermissions:Permissions:` (this is also referred to _"adding a new controller"_) - Add a new controller address in the list of `AddressPermissions[index]` at a specific `index`. - Increase the length of the `AddressPermissions[]` Array length (to describe that a new controller has been added).
EDITPERMISSIONS - Allows changing existing permissions of controllers.

value = 0x0000000000000000000000000000000000000000000000000000000000000004

:::caution Caution: Be aware that a controller with `EDITPERMISSIONS` can also edit its own permissions! ::: This permission allows for **editing permissions** of any controller (permissioned address) that has some permissions already set on the ERC725Account (including itself, see warning above). The `EDITPERMISSIONS` is also needed to: - 🗑️ **Remove** a controller from the list of `AddressPermissions[]`, meaning: - removing the controller `address` at a specific index in `AddressPermissions[index]` - decreasing the `AddressPermissions[]` Array length (to describe that a controller has been removed). - 🖊️ **Edit** an entry in the `AddressPermissions[index]` Array, meaning changing the address stored at a specific index. Bear in mind that the behavior of `EDITPERMISSIONS` slightly varies depending on the new permissions value being set (see figure below).
ADDEXTENSIONS - Allows adding new extension contracts on the linked ERC725Account.

value = 0x0000000000000000000000000000000000000000000000000000000000000008

The `ADDEXTENSIONS` permission enables the addition of new LSP17 extension contracts for specific function selectors to be called when the account is called with a function that does not exist natively in its public interface. The `fallback` function of the linked ERC725Account will handle the call to the extension set for the function selector being called.
CHANGEEXTENSIONS - Allows editing the address for an extension contract on the linked ERC725Account.

value = 0x0000000000000000000000000000000000000000000000000000000000000010

The `CHANGEEXTENSIONS` permission enables editing LSP17 extension contract addresses for function selectors already set in the account. The LSP17 extension will be called when the account is called with a function that does not exist natively in its public interface. The `fallback` function of the linked ERC725Account will handle the call to the extension set for the function selector being called.
ADDUNIVERSALRECEIVERDELEGATE - Allows adding new LSP1UniversalReceiverDelegate contracts addresses.

value = 0x0000000000000000000000000000000000000000000000000000000000000020

The `ADDUNIVERSALRECEIVERDELEGATE` permission enables to add new LSP1UniversalReceiverDelegate extension contracts for specific [Type IDs](/standards/accounts/lsp1-universal-receiver#what-does-this-standard-represent) when no contracts extension was initially set up for a specific Type ID. See [**LSP1 Universal Receiver > extension**](/standards/accounts/lsp1-universal-receiver#extension) for more details. > **NB** this permission also enables to set the address of the default LSP1UniversalReceiverDelegate contract under the `LSP1UniversalReceiverDelegate` data key if no address was set in the first place.
CHANGEUNIVERSALRECEIVERDELEGATE - Allows editing LSP1UniversalReceiverDelegate contracts addresses.

value = 0x0000000000000000000000000000000000000000000000000000000000000040

The `CHANGEUNIVERSALRECEIVERDELEGATE` permission enables two things: 1. edit the address of the default LSP1UniversalReceiverDelegate contract (linked under the `LSP1UniversalReceiverDelegate` data key). 2. edit the addresses of the LSP1UniversalReceiverDelegate extension contracts linked to specific Type IDs. See [**LSP1 Universal Receiver > extension**](/standards/accounts/lsp1-universal-receiver#extension) for more details.
REENTRANCY - Allows reentering during an execution

value = 0x0000000000000000000000000000000000000000000000000000000000000080

The permission `REENTRANCY` enables a controller to execute a payload during the execution of another payload. Depending on if the controller is an EOA or a contract: - A contract would reenter by using `execute(..)` - an EOA would do that through `executeRelayCall(..)`. _Example:_ One of the best uses for this permission is the following scenario: 1. The ERC725Acccount linked to the Key Manager makes an external call to a _contract A_. 2. _Contract A_ will make some internal updates using the received data. 3. The _contract A_ will then call back the ERC725Account **(via the Key Manager)** with another payload that will update the account storage. In order for that interaction to happen the contract A must have the `REENTRANCY` permission.
TRANSFERVALUE - Allows to transfer native tokens from the linked ERC725Account's balance with restrictions.

value = 0x0000000000000000000000000000000000000000000000000000000000000200

The `TRANSFERVALUE` permission enables to transfer the native tokens from the linked ERC725Account's balance **with restrictions**. 1. to specific addresses (EOAs or contracts). 2. to contracts implementing specific type of _interfaces standards_, that can be detected using ERC165 interfaces IDs. Such restrictions can be applied using the LSP6 data `AddressPermissions:AllowedCalls:
`, where `
` is the address of the controller that has the `TRANSFERVALUE` permission.
> **Note:** For simple native token transfers, no data (`""`) should be passed to the fourth parameter of the [`execute`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#execute) function of the Account contract. For instance: `account.execute(operationCall, recipient, amount, "")` > > The caller will need the permission `CALL` to send any data along the LYX transfer.
CALL - Allows to use the linked ERC725Account to interact with contracts with restrictions.

value = 0x0000000000000000000000000000000000000000000000000000000000000800

The `CALL` permission enables to use the linked ERC725Account to call functions on contracts deployed on the network **with restrictions**. 1. to specific contract addresses (contracts). 2. to contracts implementing specific type of _interfaces standards_, that can be detected using ERC165 interfaces IDs. It uses the `CALL` opcode, which allows to change states on the called contract.
STATICCALL - Allows calling other contracts through the controlled contract with restrictions

value = 0x0000000000000000000000000000000000000000000000000000000000002000

This permission enables the ERC725Account linked to Key Manager to make external calls to contracts while disallowing state changes at the address being called. It uses the [STATICCALL](https://eips.ethereum.org/EIPS/eip-214) opcode when performing the external call. > **NB:** If any state is changed at a target contract through a `STATICCALL`, the call will **revert silently**.
DELEGATECALL - Allows delegate calling other contracts through the controlled contract with restrictions

value = 0x0000000000000000000000000000000000000000000000000000000000008000

This permission allows executing code and functions from other contracts in the UP context. :::danger **`DELEGATECALL`** is currently disallowed (even if set on the KeyManager) because of its dangerous nature, as vicious developers can execute some malicious code in the linked Account contract. :::
DEPLOY - Allows deploying other contracts through the controlled contract

value = 0x0000000000000000000000000000000000000000000000000000000000010000

The permission `DEPLOY` enables the controller to use the linked ERC725Account to deploy new smart contracts (the linked account will act as the deployer of the new contract). Developers should provide the contract's bytecode to be deployed in the payload (ABI-encoded) passed to the Key Manager. > Both the `CREATE` or [`CREATE2`](https://eips.ethereum.org/EIPS/eip-1014) opcodes can be used to deploy a contract.
SETDATA - Allows setting data on the controlled contract with restrictions

value = 0x0000000000000000000000000000000000000000000000000000000000040000

The permission `SETDATA` allows a controller to write any form of data in the [ERC725Y](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y) data key-value store of the linked `ERC725Account`. However, this permission restricts the controller to set data for only specific data keys set via **[allowed ERC725Y Data Keys](#allowed-erc725y-keys)** :::info A controller with permission `SETDATA` cannot set or edit data keys related to: - permissions: requires the permission of `ADDCONTROLLER` or `EDITPERMISSIONS`. - LSP1 data keys: requires the permission of `ADDUNIVERSALRECEIVERDELEGATE` or `CHANGEUNIVERSALRECEIVERDELEGATE`. - LSP17 data keys: requires the permission of `ADDEXTENSIONS` or `CHANGEEXTENSIONS`. :::
ENCRYPT: Allows encrypting data or messages on behalf of the controlled account

value = 0x0000000000000000000000000000000000000000000000000000000000080000

Developers can use the `ENCRYPT` permission to encrypt data or messages, for instance for private messaging.
DECRYPT: Allows decrypting data or messages on behalf of the controlled account

value = 0x0000000000000000000000000000000000000000000000000000000000100000

Developers can use the `DECRYPT` permission to decrypt data or messages, for instance for private messaging.
SIGN: Allows signing on behalf of the controlled account, for example for login purposes

value = 0x0000000000000000000000000000000000000000000000000000000000200000

The permission `SIGN` enables a controller to authenticate on behalf of the UP. It can be used primarily in Web 2.0 apps to [sign login messages](/learn/universal-profile/connect-profile/siwe.md).
EXECUTE_RELAY_CALL: Enables a controller's signed relay calls to be executable

value = 0x0000000000000000000000000000000000000000000000000000000000400000

The permission `EXECUTE_RELAY_CALL` enables a controller's signed relay calls to be executable. This permission will be checked against the controller that signed the relay call.
### SUPER Permissions The super permissions grant the same permissions as their non-super counterparts, with the difference being that the checks on restrictions for [**Allowed Calls**](#allowed-calls) and [**Allowed ERC725Y Data Keys**](#allowed-erc725y-data-keys) are _skipped_. The skip allows for cheaper transactions, whether these restrictions are set or not.
SUPER_TRANSFERVALUE

value = 0x0000000000000000000000000000000000000000000000000000000000000100

Same as `TRANSFERVALUE`, but allowing to send native tokens to any `address` (EOA or contract). This will also not check for [**Allowed Calls**](#allowed-calls) when transferring value to contracts.
SUPER_CALL

value = 0x0000000000000000000000000000000000000000000000000000000000000400

Same as `CALL`, but it allows interacting with any contract. This will not check if the controller has any [**Allowed Calls**](#allowed-calls) restrictions set.
SUPER_STATICCALL

value = 0x0000000000000000000000000000000000000000000000000000000000001000

Same as `STATICCALL`, but it allows interacting with any contract. This will not check if the controller has any [**Allowed Calls**](#allowed-calls) restrictions set.
SUPER_DELEGATECALL

value = 0x0000000000000000000000000000000000000000000000000000000000004000

Same as `DELEGATECALL`, but allows interacting with any contract. This will not check if the controller has any [**Allowed Calls**](#allowed-calls) restrictions set.
SUPER_SETDATA

value = 0x0000000000000000000000000000000000000000000000000000000000020000

Same as `SETDATA`, but allowing to set any ERC725Y data keys. This will not check for [**Allowed ERC725Y Data Keys**](#allowed-erc725y-data-keys) if caller has any restrictions.
:::caution Use with caution: If the controller address has [**Allowed Calls**](#allowed-calls) or [**Allowed ERC725Y Data Keys**](#allowed-erc725y-data-keys) restrictions set, they will be ignored. ::: ### Combining Permissions Permissions can be combined if a controller needs more than one permission. To do so: 1. calculate the sum of the decimal value of each permission. 2. convert the result back into hexadecimal.
Example ```solidity permissions: CALL + TRANSFERVALUE 0x0000000000000000000000000000000000000000000000000000000000000800 (2048 in decimal) + 0x0000000000000000000000000000000000000000000000000000000000000200 (512) --------------------------------------------------------------------- = 0x0000000000000000000000000000000000000000000000000000000000000a00 (= 2560) ``` ```solidity permissions: EDITPERMISSIONS + SETDATA 0x0000000000000000000000000000000000000000000000000000000000000004 (4 in decimal) + 0x0000000000000000000000000000000000000000000000000000000000040000 (262144) --------------------------------------------------------------------- = 0x0000000000000000000000000000000000000000000000000000000000040004 (= 262148) ```
--- ### Retrieving list of controllers :::tip The convenience function [`getData(...)`](/tools/dapps/erc725js/methods.md#getdata) from [_erc725.js_](/tools/dapps/erc725js/getting-started) will return you the whole list of controllers when providing the `AddressPermission[]` array data key as a parameter. ::: You can obtain the list of controllers that have some permissions on the linked ERC725Account by reading the `AddressPermission[]` data key via [`getData(...)`](/contracts/contracts/ERC725/ERC725.md#getdata). - **key:** `0xdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e3` - **value return:** the total number of address that have some permissions set (= array length) Each controller can be retrieved by accessing each index in the array (see [LSP2 > Array docs](/standards/metadata/lsp2-json-schema#array) and [LSP2 > Array Standard specs](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#array) for more detailed instructions). ```json { "name": "AddressPermissions[]", "key": "0xdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e3", "keyType": "Array", "valueType": "address", "valueContent": "Address" } ``` _example:_ _if the `AddressPermission[]` array data key returns `0x0000000000000000000000000000000000000000000000000000000000000004` (array length = 4), each controller can be obtained by reading the value under the following data keys:_ - _`0xdf30dba06db6a30e65354d9a64c6098600000000000000000000000000000000`: 1st controller (array index 0 = `AddressPermissions[0]`)_ - _`0xdf30dba06db6a30e65354d9a64c6098600000000000000000000000000000001`: 2nd controller (array index 1 = `AddressPermissions[1]`)_ - _`0xdf30dba06db6a30e65354d9a64c6098600000000000000000000000000000002`: 3rd controller (array index 2 = `AddressPermissions[2]`)_ - _`0xdf30dba06db6a30e65354d9a64c6098600000000000000000000000000000003`: 4th controller (array index 3 = `AddressPermissions[3]`)_ ## Types of permissions | Permission Type | Description | `bytes32` data key | | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | | [**Address Permissions**](#address-permissions) | defines a set of [**permissions**](#permissions) for a controller. | `0x4b80742de2bf82acb3630000
` | | [**Allowed Calls**](#allowed-calls) | defines a set of interactions (action + address + function + standard) allowed for a controller. | `0x4b80742de2bf393a64c70000
` | | [**Allowed ERC725Y Data Keys**](#allowed-erc725y-keys) | defines a list of ERC725Y Data Keys a controller is only allowed to set via [`setData(...)`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#setdata-array) on the linked ERC725Account. | `0x4b80742de2bf866c29110000
` | > [See LSP6 for more details](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#erc725y-data-keys) The values set under these permission data keys **MUST be of the following format** to ensure correct behavior of these functionalities. - **Address Permissions**: a `bytes32` value. - **Allowed Calls**: a [CompactBytesArray](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#bytescompactbytesarray) of the tuple `(bytes4,address,bytes4,bytes4)`. - **Allowed ERC725Y Data Keys**: a [CompactBytesArray](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#bytescompactbytesarray) of bytes, containing values from `bytes1` to `bytes32`. :::caution To **add or remove entries in the list of allowed calls or ERC725Y Data Keys**, the **whole compact bytes array** should be encoded again and reset. Each update **overrides the entire previous state**. Note that this process can be expensive in gas, depending on the total number of allowed calls. ::: ### Address Permissions A controller can hold one (or more) permissions, enabling it to perform multiple _"actions"_ on an ERC725Account. Such _"actions"_ include **setting data**, **calling other contracts**, **transferring native tokens**, etc. To grant permission(s) to a controller, set the following data key-value pair in the [ERC725Y](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y) storage of the ERC725Account linked to the Key Manager. - **key:** `0x4b80742de2bf82acb3630000
` - **value:** one of the available permission below. To give multiple permission, see the Combining permissions section. > **NB:** remember to remove the `0x` prefix in the `
` field above. ```json { "name": "AddressPermissions:Permissions:
", "key": "0x4b80742de2bf82acb3630000
", "keyType": "MappingWithGrouping", "valueType": "bytes32", "valueContent": "BitArray" } ``` :::danger **Granting permissions to the linked ERC725Account itself is dangerous! ** A caller can craft a payload via `ERC725X.execute(...)` to be sent back to the KeyManager, leading to potential re-entrancy attacks. Such transaction flow can lead an initial caller to use more permissions than allowed initially by reusing the permissions granted to the linked ERC725Account's address. ::: :::caution Each permission MUST be **exactly 32 bytes long** and **zero left-padded**: - `0x0000000000000000000000000000000000000000000000000000000000000008` ✅ - `0x0800000000000000000000000000000000000000000000000000000000000000` ❌ For instance, if you try to set the permission TRANSFERVALUE for an address as `0x08`, this will be stored internally as `0x0800000000000000000000000000000000000000000000000000000000000000`. Ensure the `bytes32` value set under the permissions are correct according to these rules, to prevent incorrect or unexpected behaviour and errors. ::: --- ### Allowed Calls You can restrict a controller permission (`CALL`/`TRANSFERVALUE`/etc..) to be valid with specific:
Call Types Below is the list of Call Types and their possible combination. | call type | value | | --------------- | ------------ | | `TRANSFERVALUE` | `0x00000001` | | `CALL` | `0x00000002` | | `STATICCALL` | `0x00000004` | | `DELEGATECALL` | `0x00000008` |
Addresses | Address | Meaning | | :------------------------------------------: | :---------------------------------------------: | | `0xffffffffffffffffffffffffffffffffffffffff` | Interaction with any address is allowed. | | Other addresses | Interaction with a specific address is allowed. |
Standards These contracts MUST implement the [ERC165](https://eips.ethereum.org/EIPS/eip-165) standard to be able to detect their interfaces. | Interface ID | Meaning | | :-----------------: | :----------------------------------------------: | | `0xffffffff` | Interaction with any standard is allowed. | | Specific interfaces | Interaction with a specific standard is allowed. |
Functions | Function Selector | Meaning | | :----------------------: | :----------------------------------------------: | | `0xffffffff` | Interaction with any function is allowed. | | Other function selectors | Interaction with a specific function is allowed. |
To restrict a controller to a specific set of calls, set the following data key-value pair in the [ERC725Y](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y) storage of the ERC725Account linked to the Key Manager. - **key:** `0x4b80742de2bf393a64c70000` - where `
` is the controller `address` - **possible values:** - `(bytes4,address,bytes4,bytes4)[CompactBytesArray]`: a [**CompactBytesArray**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#bytescompactbytesarray) of tuple which described the allowed call (_call type_ + _address_ + _standard_ + _function_). **See details below for each element of the tuple**. - `0x` (empty): if the value is an **empty byte** (= `0x`), the controller is not allowed to interact with any functions, address or standards (**= all calls are disallowed**). Each entry in the CompactBytesArray is an **Allowed Call**. An Allowed Call is represented by a tuple of `(bytes4,address,bytes4,bytes4)`, where each value in the tuple corresponds to the following: 1. `bytes4` (**call type**) = the call type(s) allowed for this allowed call (`TRANSFERVALUE`, `CALL`, `STATICCALL` and `DELEGATECALL`). 2. `address` (**address**) = the address of an EOA or a contract. Can be used to restrict only to interact with a specific address. 3. `bytes4` (**standard**) = the ERC165 interface ID of a standard interface. Can be used to specify the _"type of contract"_ allowed to interact with. 4. `bytes4` (**function**) = a bytes4 function selector. Can be used to restrict a controller to call only a specific function on a contract. If you want to have multiple different interactions, you MUST add each of the desired interaction in the [**CompactBytesArray**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#bytescompactbytesarray) of AllowedCalls. Keep in mind that the length for each element in the [**CompactBytesArray**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#bytescompactbytesarray) must be **32** = **`0x0020`**, because the tuple `(bytes4,address,bytes4,bytes4)` makes up 32 bytes in total.
Example 1: allow only to CALL a specific LSP0 at a specific address To allow a controller to only do `CALL` to any function on a LSP0ERC725Account (interface ID `0x3e89ad98`) deployed at address `0xCA41e4ea94c8fA99889c8EA2c8948768cBaf4bc0`, the following value for the CompactBYytesArray of allowed calls will be used: `0x002000000002CA41e4ea94c8fA99889c8EA2c8948768cBaf4bc03e89ad98ffffffff` Where: - _element length_: `0x0020` (= 32 bytes) - _Call Type_: **CALL**, **0x00000002**; - _Address_: **`0xCA41e4ea94c8fA99889c8EA2c8948768cBaf4bc0`**; - _Standard_: **LSP0 interface ID = `0x3e89ad98`**; - _Function_: **any = `0xffffffff`**;
Example 2: allow multiple interactions of different types Consider the scenario where you want to give the following permissions to a controller: - allow to `CALL` any functions (as well as transferring value `TRANSFERVALUE`) to a LSP0 contract deployed at address `0xCA41e4ea94c8fA99889c8EA2c8948768cBaf4bc0`. - allow to `CALL` only the `transfer(address,address,uint256,bool,bytes)` function on the contract deployed at address `0xF70Ce3b58f275A4c28d06C98615760dDe774DE57`. - allow to `TRANSFERVALUE`s while calling any functions on the contract deployed at address `0xd3236aa1B8A4dDe5eA375fd1F2Fb5c354e686c9f`. The CompactBytesArray of allowed calls for this controller will be composed of the following entries: - `AllowedCalls[0]` = the 1st value in the CompactBytesArray will be **`0x002000000002CA41e4ea94c8fA99889c8EA2c8948768cBaf4bc03e89ad98ffffffff`**. - _Call Type_: **CALL and TRANSFERVALUE**, **0x00000003**; - _Address_: **`0xCA41e4ea94c8fA99889c8EA2c8948768cBaf4bc0`**; - _Standard_: **LSP0 interface ID = `0x3e89ad98`**; - _Function_: **any = `0xffffffff`**; - AllowedCalls[1] = the 2nd value in the CompactBytesArray will be **`0x002000000003F70Ce3b58f275A4c28d06C98615760dDe774DE57ffffffff760d9bba`**. - _Call Type_: **CALL**, **0x00000002**; - _Address_: **`0xF70Ce3b58f275A4c28d06C98615760dDe774DE57`**; - _Standard_: **any = `0xffffffff`**; - _Function_: **transfer(address,address,uint256,bool,bytes), `0x760d9bba`**; - AllowedCalls[2] = the 3rd value in the CompactBytesArray will be **`0x002000000004d3236aa1B8A4dDe5eA375fd1F2Fb5c354e686c9fffffffffffffffff`** - _Call Type_: **TRANSFERVALUE**, **0x00000001**; - _Address_: **`0xd3236aa1B8A4dDe5eA375fd1F2Fb5c354e686c9f`**; - _Standard_: **any = `0xffffffff`**; - _Function_: **any = `0xffffffff`**; A _CompactBytesArray_ for these 3 interactions would look like this: `0x`**`0020`**`00000003CA41e4ea94c8fA99889c8EA2c8948768cBaf4bc03e89ad98ffffffff`**`0020`**`00000002F70Ce3b58f275A4c28d06C98615760dDe774DE57ffffffff760d9bba`**`0020`**`00000001d3236aa1B8A4dDe5eA375fd1F2Fb5c354e686c9fffffffffffffffff`
```json { "name": "AddressPermissions:AllowedCalls:
", "key": "0x4b80742de2bf393a64c70000
", "keyType": "MappingWithGrouping", "valueType": "(bytes4,address,bytes4,bytes4)[CompactBytesArray]", "valueContent": "(BitArray,Address,Bytes4,Bytes4)" } ``` :::warning Allowing a specific standard does not offer security over the inner workings or the correctness of a smart contract. It should be used more as a "mistake prevention" mechanism than a security measure. ::: :::info **If no Allowed Calls are set (`0x`), a controller cannot interact with any address nor transfer any value (Contract or EOA).** ::: --- ### Allowed ERC725Y Data Keys If a controller is allowed to [`SETDATA`](#permissions) on an ERC725Account, it is possible to restrict which data keys this address can set or update. To restrict a controller to only be allowed to set the key `LSP3Profile` (`0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5`), the following data key-value pair can be set in the ERC725Y contract storage. Encode data as a [**CompactBytesArray**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#bytescompactbytesarray). - **key:** `0x4b80742de2bf866c29110000
` - **value(s):** `0x00205ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5`
ERC725Y Data Keys: fixed-size vs dynamic-size Introduction (summary) You can set 2 types of **ERC725Y Data Keys**: - _Fixed-size Data Keys_ A **fixed-size Data Key** is a data key with a fixed length of 32 bytes. If a _controller address_ has a fixed-size allowed ERC725Y data key set, then that _controller_ can only change the value of that specific fixed-size data key. - _Dynamic-size Data Keys_ A **dynamic-size Data Key** is a data key with a variable length from 1 byte up to 31 bytes. If a _controller_ has a dynamic-size allowed ERC725Y data key set, then that _controller_ can change any data key that starts with the _dynamic-size data key_. _**Examples:**_ - _Fixed-size Data Keys_ Let's imagine the following situation, you set an **Allowed ERC725Y fixed-size Data Key** (e.g. `0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5`) for a controller (e.g. Alice). With that setup you allowed Alice to update only the value of the **Allowed ERC725Y Data Key**. - _Dynamic-size Data Keys_ Let's imagine the following situation: You set an **Allowed ERC725Y dynamic-size Data Key** (e.g., `0xbeefbeefbeefbeef`) for a controller (e.g., Bob). With that setup you allowed Bob to set any **Data Key** that starts with `0xbeefbeefbeefbeef`. E.g: - `0xbeefbeefbeefbeefcafecafecafecafecafecafecafecafecafecafecafecafe` - `0xbeefbeefbeefbeef0000000000000000000000000000000000000000c629dfa8` - `0xbeefbeefbeefbeef000000000000000000000000000000000000000000001253`
Combining multiple ERC725Y Data Keys If you want to have multiple different ERC725Y data keys allowed, you MUST add each of the desired data keys to a [**CompactBytesArray**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#bytescompactbytesarray). E.g.: - `0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5` (**length: 32 bytes** = `0x0020`) - `0x5ef83ad9559033e6e941db7d7c495acd` (**length: 16 bytes** = `0x0010`) - `0xbeefbeef` (**length: 4 bytes** = `0x0004`) A CompactBytesArray for these 3 different ERC725Y Data Keys would look like this: `0x`**`0020`**`5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5`**`0010`**`5ef83ad9559033e6e941db7d7c495acd`**`0004`**`beefbeef`
```json { "name": "AddressPermissions:AllowedERC725YDataKeys:
", "key": "0x4b80742de2bf866c29110000
", "keyType": "MappingWithGrouping", "valueType": "bytes[CompactBytesArray]", "valueContent": "Bytes" } ``` Below is an example use case. An ERC725Account can allow some applications to add/edit information on its storage via `setData(...)`. The account can restrict such Dapps and protocols to edit the data keys that are only relevant to the logic of their applications. As a result, this provide context for the Dapp on which data they can operate on the account, while preventing them to edit other information, such as the account metadata, or data relevant to other dapps. :::info **If no Allowed ERC725Y Data Keys are set, the controller cannot set any value for any key.** ::: --- ## Types of Execution Since the LSP6 Key Manager incorporate the [LSP20 Call Verification](/standards/accounts/lsp20-call-verification) and the [LSP25 Execute Relay Call](/standards/accounts/lsp25-execute-relay-call) standards, it allows to interact with the linked target contract in multiple ways. Let's give some context to understand the different types of execution flow and the roles of each actor based on that. - **Alice**: an **end user** who want to interact with a smart contract on-chain (or any dApp). - **Bob**: an entity that act as a **relayer**, to send transactions of other users on their behalf and pay for their gas fees. > **Note:** _"relayer"_ is a generic term that can refer to either Bob acting as: > > - an individual (dispatching transactions to the network using its own private key) > - a business through a relayer service that he runs (where he might hold multiple private keys within its infrastructure that all dispatch transactions). There are 3 ways to interact with the contract linked with the Key Manager. | Interaction type | Description | Characteristics | | :----------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Direct execution**
_via Key Manager_ | The end user (Alice) sends the **payload** directly to the Key Manager via [`execute(...)`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#execute) | Caller = end user (Alice).
**👎🏻 Alice pays for the gas fees.** | | **Relay execution**
_via Key Manager_ | The end user (Alice) signs a **payload** using the LSP25 signature format.
A relayer (Bob) dispatches the transaction for the user to the Key Manager via [`executeRelayCall(...)`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#executerelaycall). | Caller = relayer (Bob).
The signer is the end user (Alice).
**👍🏻 Alice does not pay for the gas fees (this method allows Alice to offload her gas fees to Bob).** | | **Direct execution**
_on the target contract (e.g: a 🆙)_

**verified via LSP20-CallVerification** | The end user (Alice) interacts directly with the target contract (_e.g., a Universal Profile_) by calling any of its public functions. This bypasses the Key Manager, sending the call directly to the contract. The contract will forward the call to the Key Manager’s [`lsp20VerifyCall`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#lsp20verifycall) function for permission verification. | Caller = end user (Alice).
**👎🏻 Alice pays for the gas fees.**
**👍🏻 User can call the function directly on the contract without going through the Key Manager.**
**👌🏻 Simplifies interaction. No need to abi-encode function call first and send the encoded payload to the Key Manager.** | > **Note:** the **payload** corresponds to the abi-encoded function call on the contract linked to the Key Manager. > > _Example: if the contract linked to the Key Manager is a Universal Profile, the payload can be the abi-encoded function call of `setData`, `setDataBatch`, `execute`, `executeBatch`, `transferOwnership` or `acceptOwnership`_ In all cases, whether the end user interacts directly or via relayer, it must have the right permissions on the contract linked to the Key Manager for the action it is trying to perform (_e.g: permission `SETDATA` + relevant Allowed Data Keys if doing `setData` or `setDataBatch`, permission `SUPER_TRANSFERVALUE` if trying to send native tokens out of the contract, etc..._). ### Direct & Relay execution via the Key Manager :::info When signing relay calls with the LSP25 signature format, make sure to use the Key Manager's address as the 3rd parameter (_LSP25 Implementation address_) of the data to sign. See [**Standards > LSP25 > Parameters to generate a LSP25 signature**](/standards/accounts/lsp25-execute-relay-call#parameters-to-generate-a-lsp25-signature) for more details. ::: :::success See our Learn section for a Key Manager guide on [**How to sign and execute relay transactions**](/learn/universal-profile/key-manager/execute-relay-transactions.md) ::: In the case of direct execution, the user (being a permissioned address) is the caller (`msg.sender`) and call the `execute(...)` function on the Key Manager. In the case of relay execution, the permissioned address **A** signs a payload and the relay service **B** executes the payload on behalf of the signer via [`executeRelayCall(...)`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#executerelaycall). ### Direct execution to the target contract thanks to LSP20 Since the LSP6 Key Manager supports the LSP20 standard, interaction with the linked contract (like an ERC725Account owned by a Key Manager in the case of the UP Browser Extension) can be done directly, in accordance with the LSP20-CallVerification standard. The call will be forwarded to the LSP20 functions of the Key Manager and the LSP20 functions will verify the necessary permissions and emit the relevant event. ## References - [LUKSO Standards Proposals: LSP6 - Key Manager (Standard Specification, GitHub)](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md) - [LSP6 KeyManager: Solidity implementations (GitHub)](https://github.com/lukso-network/lsp-smart-contracts/tree/develop/packages/lsp6-contracts/contracts) --- --- sidebar_label: 'Introduction' sidebar_position: 1 description: Introduction to LUKSO's Universal Profiles. --- # Universal Profiles :::success Useful Tip The [Learn Section](../../learn/overview.mdx) will take you through the process of creating a Universal Profile and deploying it on the [LUKSO Testnet](../../networks/testnet/parameters.md). You can also browse the already deployed Universal Profiles on [universalprofile.cloud](https://universalprofile.cloud/). ::: ## Introduction Building an identity on top of keys is almost impossible because keys are likely to be leaked or lost forever. Holding assets and building a reputation on these keys makes it worse. A better representation of identity would be with blockchain-based accounts. Blockchain-based accounts can change the way of interacting on-chain, allowing the usage of multiple components together. Used in combination with a Controller (see **[LSP6 - Key Manager](../access-control/lsp6-key-manager.md)**), they could allow any entity to execute or set some data on your profile directly or via relay execution. Finally, developers could use contracts for social recovery if keys are lost. All these components together can enhance the blockchain experience.
## Universal Profile Architecture The diagram below shows the standard architecture used by LUKSO for Universal Profile. The architecture is based on the combination of multiple standards and smart contracts to provide extensive and extensible functionality. This modularity allows for logic updates without altering the code of the main contract. This provides flexibility and facilitates the development and maintenance of this complex system, as changes or improvements can be made independently in each module without affecting others. ## Universal Profiles Standards | Standard | Description | | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | **[LSP0 - ERC725Account](./lsp0-erc725account.md)**: This standard represents the core account contract. It consists of [ERC725X](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x), allowing a contract to interact with any address or smart contract on the blockchain, and [ERC725Y](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y), a generic key-value store that allows storing an unlimited amount of data in the smart contract. It also contains [ERC1271](https://eips.ethereum.org/EIPS/eip-1271) to verify if messages were signed by the ERC725Account's owner. If the owner is a Key Manager supporting ERC1271, it will delegate the call to the KeyManager. Lastly, it contains the [LSP1 - UniversalReceiver](../accounts/lsp1-universal-receiver.md), which allows this contract to be notified of any incoming asset. Using the [LSP1 - UniversalReceiverDelegate](../accounts/lsp1-universal-receiver-delegate.md) logic, you can delegate the universal receiver call that an asset will do to an external contract, customizing the behaviour you want towards the asset. More on that below. | | | **[LSP6 - KeyManager](../access-control/lsp6-key-manager.md)**: A standard representing a smart contract that can act as the owner of an [LSP0 - ERC725Account](./lsp0-erc725account.md). It reads permissions of addresses from the ERC725Account's key-value store, and restricts access based on these permissions. Transactions can be executed directly by permissioned users or by anyone with the help of a signed message by permissioned users. | | | **[LSP1 - UniversalReceiverDelegate](/standards/accounts/lsp1-universal-receiver-delegate.md)**: By setting the **[`LSP1 - UniversalReceiverDelegate`](/standards/accounts/lsp1-universal-receiver#extension)** data key in your ERC725Account to a contract address, you can delegate any call to the `universalReceiver(...)` function of the account to this contract, which allows you to revert on certain incoming assets or add other logic. The [standard **LSP1 - UniversalReceiverDelegate** implementation](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP) will write every [LSP7 and LSP8](/standards/tokens/introduction.md) asset you receive into your ERC725Account using the [LSP5 - ReceivedAsset](/standards/metadata/lsp5-received-assets.md) standard. This allows any interface to list all token contracts that hold a balance of your account, right from the smart contract. | :::note An LSP0-ERC725Account can work standalone and doesn't require a Key Manager or a Universal Receiver Delegate, but this will limit the user experience. ::: ## Adding profile information :::info How is data stored on a Universal Profile? Each data on a Universal Profile is stored into a generic key-value [ERC725Y](../erc725.md#erc725y-data-representation) store which allows storing an unlimited amount of data in the smart contract. ERC725Y standardizes a mapping of data keys to data values in order 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. On the smart contract, data keys are represented as bytes32 values and data values under these keys are stored as bytes. ::: [LSP2 - ERC725YJSONSchema](../../../standards/metadata/lsp2-json-schema) is the standard used by the LSPs to organize how the data should be represented as `bytes32 => bytes` data key / value pairs. The **[LSP0 - ERC725Account](./lsp0-erc725account.md)** standard represents a blockchain-based account that does not contain any metadata describing the account. It's important to standardize specific data keys to give the account a unique character and look like a typical **Web2 profile**. **[LSP3 - Profile Metadata](../metadata/lsp3-profile-metadata.md)** is a standard used to add profile information by setting its defined data keys in the account storage. The combination of these two standards forms a **Universal Profile**. :::tip The guide [Edit Profile Data](../../learn/universal-profile/metadata/edit-profile.md) may interest you. ::: ## References - [LUKSO Standards Proposals: LSP0 - ERC725 Account (Standard Specification, GitHub)](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md) - [LUKSO Standards Proposals: LSP3 - Profile Metadata (Standard Specification, GitHub)](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md) - [LUKSO Standards Proposals: LSP6 - Key Manager (Standard Specification, GitHub)](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md) - [LSP1 Universal Receiver: Solidity implementations (GitHub)](https://github.com/lukso-network/lsp-smart-contracts/tree/develop/packages/lsp1-contracts/contracts) --- --- sidebar_label: 'LSP0 - ERC725 Account' sidebar_position: 2 description: LUKSO's LSP0 - ERC725 Account. --- # LSP0 - ERC725 Account :::info Standard Specification [LSP0 - ERC725Account](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md) ::: LSP0, the ERC725 Account standard, is at the heart of creating digital identities on the LUKSO blockchain. Think of it as a digital passport that represents you, your organization, or even your smart devices in the digital world. It is built on a combination of LUKSO standards, allowing for a wide array of functionalities — from executing transactions and storing diverse data to verifying digital signatures. An ERC725 Account overcomes the limitations of traditional blockchain accounts by enabling more secure, flexible, and user-friendly identities. Whether it is about holding assets, interacting with decentralized apps, or participating in digital governance, LSP 0 empowers users to do it all under one roof, with full control and enhanced security. It is not just an account; it is a comprehensive digital identity system designed for the future of Web3. ## Introduction [Externally Owned Accounts (EOAs)](https://ethereum.org/en/developers/docs/accounts/#externally-owned-accounts-and-key-pairs) 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](https://www.evm.codes/#f1)** opcode and create contracts using the **[CREATE](https://www.evm.codes/#f0)** opcode. These issues can be addressed by the **[ERC725](../erc725.md)** 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](https://eips.ethereum.org/EIPS/eip-165)** allows to register and detect the standard interfaces and standards that the contract implements, or will implement in the future. - **[ERC725X](../erc725.md#erc725x---generic-executor)** is a generic executor that enables calling external contracts with different operations such as [**CALL**](https://www.evm.codes/#f1), [**STATICCALL**](https://eips.ethereum.org/EIPS/eip-214) and [**DELEGATECALL**](https://eips.ethereum.org/EIPS/eip-7). It also allows deploying new contracts with [**CREATE**](https://www.evm.codes/#f0) or [**CREATE2**](https://eips.ethereum.org/EIPS/eip-1014), or transferring value to any address (EOA or smart contracts). - **[ERC725Y](../erc725.md#erc725y---generic-data-keyvalue-store)** is a generic key-value store that enables it to **attach any information** to the smart contract even after it's been deployed. - **[ERC1271](https://eips.ethereum.org/EIPS/eip-1271)** helps to **verify the validity** of a message and signature. - **[LSP1-UniversalReceiver](../accounts/lsp1-universal-receiver.md)** enables **notifications about incoming or outgoing transactions** and adds custom handling and behavior based on these transactions. - **[LSP14-Ownable2Step](../access-control/lsp14-ownable-2-step.md)** enables a **secure ownership management** system. - **[LSP17-ContractExtension](../accounts/lsp17-contract-extension.md)** enables the contract to be **extended after deployment** to support new standard and functionalities. - **[LSP20-CallVerification](/standards/accounts/lsp20-call-verification.md)** provides a unified and standard way for all addresses to **interact directly with the account**. This streamlines the interaction process considering the ownership setup, and enhancing accessibility and developer experience. ## Specification ### ERC725X - Generic Executor :::tip See the **[ERC725](../erc725.md)** standard for more information. Check the [**execute functions**](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#execute) provided by **ERC725X** that allows the contract to execute multiple operations. Check the **javascript** guides to know [**How to Send native tokens**](/learn/universal-profile/interactions/transfer-lyx.md) or [**How to Call other contract's function**](/learn/universal-profile/interactions/interact-with-contracts.md) 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 number | Operation type | Description | | :--------------: | :----------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------ | | 0 | [`CALL`](https://www.evm.codes/#f1) | Transfer native tokens or calls smart contract functions. | | 1 | [`CREATE`](https://www.evm.codes/#f0) | Create a new smart contract based on the contract address and nonce. | | 2 | [`CREATE2`](https://eips.ethereum.org/EIPS/eip-1014) | Create a new smart contract based on the contract address, bytecode and the salt. The address can be predetermined. | | 3 | [`STATICCALL`](https://eips.ethereum.org/EIPS/eip-214) | Calls another smart contract while disallowing any modification to the state during the call. | | 4 | [`DELEGATECALL`](https://eips.ethereum.org/EIPS/eip-7) | Runs the function from another contract, but use the context of the current contract. | #### Operation 0 - CALL # #### Operation 1 - CREATE # #### Operation 2 - CREATE2 # #### Operation 3 - STATICCALL # #### Operation 4 - DELEGATECALL # ### ERC725Y - Generic Key-Value Store :::tip See the **[ERC725](../erc725.md)** standard for more information. Check the [**setData functions**](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#setdata) provided by **ERC725Y** that allows attaching data to the contract. Check the **javascript** guides to know [**How to Edit a Profile (setData)**](/learn/universal-profile/metadata/edit-profile.md) or [**How to Read from a Profile (getData)**](/learn/universal-profile/metadata/read-profile-data). ::: 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`. 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(...)`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#getdata) and [`setData(...)`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#setdata). ### ERC1271 :::tip See the **[ERC1271](https://eips.ethereum.org/EIPS/eip-1271)** standard for more information. Check the [**isValidSignature**](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#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](../accounts/lsp1-universal-receiver.md)** standard for more information. Check the [**universalReceiver functions**](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver) provided by **LSP1** that allows notifying about incoming/ outgoing transactions. Check the **javascript** guides to know [**How to set a UniversalReceiverDelegate built by LUKSO**](/learn/universal-profile/universal-receiver/deploy-universal-receiver.md) or [**How to set your own UniversalReceiverDelegate**](/learn/universal-profile/universal-receiver/accept-reject-assets.md). ::: 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](/standards/accounts/lsp0-erc725account.md)** implements the `universalReceiver(..)` function that: Emits an [`UniversalReceiver`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver-1) 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. # 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. # 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. # 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](../access-control/lsp14-ownable-2-step.md)** standard for more information. Check the [**LSP14 functions**](/contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md) allowing 2 step ownership transfers. ::: 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](../access-control/lsp6-key-manager.md)**) 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](#lsp1---universalreceiver)** standard. #### Initiate the transfer #### Accept ownership #### Transfer Finalized 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. ### LSP17 - Contract Extension :::tip See the **[LSP17 - ContractExtension](./lsp17-contract-extension.md)** standard for more information. Check the **JavaScript** guides to know [**How to extend the functionalities and interfaceIds of an account**](/learn/universal-profile/advanced-guides/extend-profile-functionalities.md) Check the [**fallback function**](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#fallback) 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](./lsp17-contract-extension.md)** 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. 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. 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: 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. ### LSP20 - Call Verification :::tip See the **[LSP20 - CallVerification](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-20-CallVerification.md)** standard for more information. Check the **[LSP0 functions](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md)** to see how verification of allowed calls to the account happens. ::: The **LSP0ERC725Account** is an ownable contract that can be owned by different types of addresses, including EOAs, contracts like multi-sig wallets, KeyManagers, etc. These owner contracts may have various functions and behaviors, which can create challenges in figuring out how the interaction with the account works. Previously, when a Key Manager owns the account, only addresses allowed by the Key Manager should interact with the account via the Key Manager. However, they cannot directly interact with the account functions because only the Key Manager can call them as the owner. A similar issue arises when a voting contract owns the account, as voters must interact with the voting contract rather than the account directly. To ensure a unified and standard way to interact with the account, the **LSP20-CallVerification** standard was proposed. This standard aims to streamline the interaction with the account, considering the ownership setup. Currently, when the owner calls a function on the account contract, they are allowed to execute it directly. However, if a different address calls a function on the LSP0, the function will forward the call to the account owner for verification. The owner must then determine if the caller is allowed to execute the specific function. If the caller is allowed, the owner should return a specific value. If the caller is not allowed, the owner can either revert the transaction or return an invalid value. This verification process occurs before and possibly after the execution of the function. The primary benefit of this approach is that it ensures a unified way for all addresses to interact directly with the account functions, even if they are not the owner but are allowed by the owner's logic. By implementing the **LSP20-CallVerification** standard, the account becomes more accessible and versatile, accommodating various ownership structures and simplifying the user experience for those interacting with it. --- --- sidebar_label: 'LSP1 - Universal Receiver Delegate' sidebar_position: 4 description: LUKSO LSP1 Universal Receiver for notifying upon incoming transactions. --- # LSP1 - Universal Receiver Delegate :::info Standard Specification [LSP1 - Universal Receiver Delegate](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md#specification-of-the-universalreceiverdelegate) ::: :::success Recommendation To better understand this standard, it is well-advised first to check the origin standard **[LSP1-UniversalReceiver](../accounts/lsp1-universal-receiver.md)**. ::: ## Introduction Once deployed, the code of a smart contract **can not be changed**. However, builders can decide how their smart contracts implement the [`universalReceiver(...)`](/contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver) function. Therefore, it is advised not to hardcode how the smart contract should handle and react to specific calls inside the `universalReceiver(...)` function. Instead, it should delegate this functionality to another external contract. Developers could then customize such contracts to implement a specific logic, that is **changeable anytime** by updating the reference to a new contract in the `universalReceiver(..)` function. ## What does this standard represent ? ### Specification :::success recommendation Smart contracts implementing the [LSP1-UniversalReceiverDelegate](/standards/accounts/lsp1-universal-receiver-delegate.md) standard SHOULD **register** the **[LSP1UniversalReceiverDelegate InterfaceId](../../contracts/interface-ids.md) using ERC165**. This way, other contracts can be aware that the contract supports the LSP1-UniversalReceiverDelegate standard. ::: This standard defines a contract called **UniversalReceiverDelegate** containing a single function named `universalReceiverDelegate(...)` that should be called by the `universalReceiver(..)` function with: - address `caller` is the address calling the `universalReceiver` function. - uint256 `value` is the amount of value sent to the `universalReceiver` function. - bytes32 `typeId`: the typeId passed to the `universalReceiver(...)` function. - bytes `data`: the data passed to the `universalReceiver(...)` function. ### How Delegation works Delegation in the context of smart contracts implementing the `universalReceiver(...)` function allows for flexibility in handling specific calls without hardcoding the logic within the primary contract. While the exact implementation of delegation is up to the individual contract, there are some common steps involved in the process. 1- Query the **UniversalReceiverDelegate** address: Typically, the address of the **UniversalReceiverDelegate** contract is stored in the primary contract's storage. When the `universalReceiver(...)` function is called, the address is retrieved to facilitate delegation. 2- Check for LSP1Delegate support: Before making any calls to the UniversalReceiverDelegate contract, it's essential to ensure that the contract supports the LSP1Delegate standard. This can be done by checking for the **LSP1UniversalReceiverDelegate InterfaceId** using ERC165. 3- Call the UniversalReceiverDelegate's `universalReceiverDelegate(..)` function: Once LSP1Delegate support is confirmed, the primary contract's `universalReceiver(...)` function can delegate the call to the UniversalReceiverDelegate's `universalReceiverDelegate(...)` function. This allows the primary contract to utilize the logic implemented in the delegate contract. Delegation can be implemented in various ways, depending on the developer's requirements. Some possible delegation strategies include: - Single delegation: The primary contract delegates all calls to a single UniversalReceiverDelegate contract. - Multiple delegation: Different calls are delegated to different UniversalReceiverDelegate contracts based on specific conditions, such as the typeId. - Mixed delegation: A combination of single and multiple delegation strategies can be used, where some calls are delegated to a single contract, while others are delegated to different contracts based on specific conditions. In summary, delegation provides a flexible way for smart contracts to handle and react to specific calls, allowing developers to update the logic without altering the primary contract's code. This approach is particularly useful when working with the universalReceiver(...) function and implementing the LSP1 standard. ## Implementations There are several implementations of the standard. The **[LSP1UniversalReceiverDelegateUP](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/)** contract is one of them and is used as a delegate to the `universalReceiver(...)` function of **UniversalProfile** contract. At the moment, this contract allows to: - receive and send tokens & vaults - register the data keys representing them according to **[LSP5-ReceivedAssets](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-5-ReceivedAssets.md)** and **[LSP10-ReceivedVaults](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-10-ReceivedVaults.md)** Standards. ### Token transfer scenario One of the possible scenarios is a token transfer between Alice and Bob. Alice wants to transfer a token owned by her Universal Profile to the Universal Profile of her friend Bob. **1.** It calls the **`transfer(...)`** function on the token contract. **2.** The `transfer(...)` function on the token contract will directly **trigger a hook** that will call the `universalReceiver(...)` function on both sender and recipient Universal Profiles. **3.** 3. If the **UniversalReceiverDelegate** contract is set, it will be called by the `universalReceiver(...)` function and will execute its custom logic. **4.** The **UniversalReceiverDelegate** of **Universal Profile** allows the transfer and set **[LSP5-ReceivedAssets](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-5-ReceivedAssets.md)** data keys on both Profiles. > For the UniversalReceiverDelegate to be able to call setData function on the UniversalProfile, it should be allowed by the logic of the owner through LSP20. ## Data Keys ### LSP1UniversalReceiverDelegate Singleton ```json { "name": "LSP1UniversalReceiverDelegate", "key": "0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47", "keyType": "Singleton", "valueType": "address", "valueContent": "Address" } ``` ### LSP1UniversalReceiverDelegate Mapping ```json { "name": "LSP1UniversalReceiverDelegate:", "key": "0x0cfc51aec37c55a4d0b10000", "keyType": "Mapping", "valueType": "address", "valueContent": "Address" } ``` ## References - [LUKSO Standards Proposals: LSP1 - Universal Receiver (Standard Specification, GitHub)](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md) - [LSP1 Universal Receiver: Solidity implementations (GitHub)](https://github.com/lukso-network/lsp-smart-contracts/tree/main/packages/lsp1-contracts/contracts) --- --- sidebar_label: 'LSP1 - Universal Receiver' sidebar_position: 3 description: LUKSO LSP1 Universal Receiver Delegate. --- # LSP1 - Universal Receiver :::info Standard Specification [LSP1 - Universal Receiver](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-1-UniversalReceiver.md) ::: > **Goal:** Handling incoming or outgoing transactions/transfers and contract interactions. LSP1, introduces the Universal Receiver, a unique feature that revolutionizes how transactions, transfers, and contract interactions are handled on the blockchain. Imagine a world where every incoming action to your blockchain identity or asset is not just received but also intelligently responded to. That's what the Universal Receiver does. By implementing LSP1, any smart contract or wallet can detect incoming transactions and automatically trigger customized responses. This could range from accepting certain types of assets, rejecting unwanted tokens, or even executing specific actions when receiving a message (e.g: store automatically certain received assets in a digital vault). The beauty of the Universal Receiver lies in its flexibility and the ability to delegate these responses to external contracts called Universal Receiver Delegates, which can have their own custom mechanisms for different purposes. This ensures that your digital presence on the blockchain is not just passive but active, by managing and responding to interactions according to your own predefined rules. Whether it is for personal wallets, digital identities, or complex decentralized applications, the Universal Receiver provides a foundational layer for more secure, efficient, and user-friendly blockchain interactions. ## Introduction There is often the need for smart contracts to **be aware of incoming transactions**, especially receiving tokens. A good example is **[ERC20](https://eips.ethereum.org/EIPS/eip-20)** token transfers. When a smart contract receives a token, it has no generic way **to be notified** about it. During the token transfer, the sender's balance decreases, and the recipient's balance increases. There are **no further interactions**, and the ERC20 token contract just acts as a registry. One solution to this problem could be to listen to all the ERC20 token transfer events on the network. However, this requires using a trusted third party to listen to the events. Such a method limits smart contracts autonomy and introduces a single point of failure. Standards like **[ERC223](https://eips.ethereum.org/EIPS/eip-223)**, **[ERC721](https://eips.ethereum.org/EIPS/eip-712)**, and **[ERC1155](https://eips.ethereum.org/EIPS/eip-1155)** require having specific functions in order to receive and be notified about the token such as `tokenReceived(..)`, `onERC721Received(..)`, and `onERC1155Received(..)` respectively. These functions have different contexts, parameters, and events that make the smart contract not interoperable. If later in the future, a token standard **ERCXXXX** gets adopted, the smart contract (account, DEXs) will not be able to receive these kinds of tokens because it was already deployed on the network and **does not support** `onERCXXXXReceived(..)` function. One way to solve this problem is by creating a **standard and unified function** that any smart contract can implement. DEXs, Wallets, or profiles could use this function to be notified about an incoming asset, information, followers, etc. ## What does this standard represent? ### Specification :::success recommendation Smart contracts implementing the [LSP1-UniversalReceiver](../../standards/accounts/lsp1-universal-receiver-delegate.md) standard SHOULD **register** the **[LSP1UniversalReceiver InterfaceId](../../contracts/interface-ids.md) using ERC165**. This way, other contracts can be aware that the contract supports the LSP1 standard. ::: This standard defines a single function named `universalReceiver(...)` that could receive **any arbitrary information**. It takes two parameters: - bytes32 `typeId`: Hash or Hook of a specific standard. - bytes `data`: Any arbitrary data. > Receiving contracts should consider the `typeId` parameter to **decode the data correctly**. The `universalReceiver(...)` function **emits an event with the data passed to it and some additional data**. For example, **to notify the recipient that he is about to receive tokens**, during a token transfer, the token contract can call the `universalReceiver(..)` function of the recipient with: - bytes32 `typeId`: **Hash**('ERCXXXXTokenReceived') - bytes `data`: **packedData**(amount of token sent, the sender address, the block timestamp) In this way, instead of **listening to all the events of the token contrats on the network**, and checking which one of these transfers is relative to the recipient, users can listen to the **[UniversalReceiver](../../contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver-1)** event on the contract implementing the `universalReceiver(..)` and know the token transfer details. As well as emitting an event, the `universalReceiver(...)` function can implement **custom logic** to make the contract behave differently based on the data received. Some ideas include: - Reverting on calls to completely disallow the smart contract from receiving assets, information, etc. :x: - Registering the received assets inside the contract storage (see [LSP5 - Received Assets](../metadata/lsp5-received-assets.md)). :heavy_plus_sign: - Disallowing receiving specific tokens from specific token contract addresses, for instance (e.g: spam tokens). - Forwarding all the received assets to an external vault or a staking contract. - Forwarding specific tokens in a contract behind a protocol or dApp (e.g: liquidity or lending pool to earn interest). - Depending on the typeId, save a percentage % of tokens received (native tokens or not), by placing them in a vault for instance. ## Extension :::info See the **[LSP1-UniversalReceiverDelegate](../accounts/lsp1-universal-receiver-delegate.md)** standard for more details. ::: Overriding and customizing the `universalReceiver(..)` function is an option for users to allow **different behaviours depending on the data received**. However, it's not advised to hardcode the logic of reacting to specific actions inside the function because **this logic may need to change in the future** depending on several factors (eg. the vault where the tokens are forwarded gets compromised, a new staking contract is deployed, decided to revert on specific tokens later). **[LSP1-UniversalReceiverDelegate](../accounts/lsp1-universal-receiver-delegate.md)** is an **optional extension** to the **[LSP1-UniversalReceiver](../../standards/accounts/lsp1-universal-receiver.md)** standard. As well as notifying a contract about the incoming and outgoing transactions by emitting an event, it can delegate the call to an external contract that can **handle and react to specific calls** with its custom logic. The address of the **external contract** can be stored and changed inside the contract storage. This way, users can customize such contracts to implement a specific logic that is changeable at any time. --- --- title: LSP15 - Transaction Relayer API sidebar_position: 6 description: LUKSO's Transaction Relay Service API Standard. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # LSP15 - Transaction Relay Service API :::info Standard Specification [LSP15 - Transaction Relayer API](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-15-TransactionRelayServiceAPI.md) :::
:::success Relayer API Want to easily deploy a Universal Profile using our Developer Relayer API? See the [**Relayer Developer Access**](/tools/apis/relayer-api.md) page. ::: This standard is the off-chain API that any transaction relay service can implement to be compatible with the [Universal Profile controller apps](/install-up-browser-extension). See [the `up_addTransactionRelayer` RPC endpoint](/tools/apis/up-rpc-api#up_addTransactionRelayer) for more. To learn how to sign a transaction relay message see [LSP25 Execute Relay Call](./lsp25-execute-relay-call.md). ## POST `/execute` Executes a signed transaction on behalf of a Universal Profile using [`executeRelayCall()`](/contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#executerelaycall). - Use signed message provided in request for authentication. - Calculate and return the transaction hash in response. ```json title="Request body" { "address": "0xBB645D97B0c7D101ca0d73131e521fe89B463BFD", // Address of the Universal Profile "transaction": { "abi": "0x7f23690c5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000596f357c6aa5a21984a83b7eef4cb0720ac1fcf5a45e9d84c653d97b71bbe89b7a728c386a697066733a2f2f516d624b43744b4d7573376741524470617744687a32506a4e36616f64346b69794e436851726d3451437858454b00000000000000", "signature": "0x43c958b1729586749169599d7e776f18afc6223c7da21107161477d291d497973b4fc50a724b1b2ab98f3f8cf1d5cdbbbdf3512e4fbfbdc39732229a15beb14a1b", "nonce": 1 // KeyManager nonce } } ``` ```json title="Response" { "transactionHash": "0xBB645D97B0c7D101ca0d73131e521fe89B463BFD" } ``` ## POST `/quota` Returns the available quota left for a registered Universal Profile. - `signature` is the message value signed by a controller key with the [`SIGN` permission](/standards/access-control/lsp6-key-manager#permissions) of the Universal Profile. The hash to sign should be calculated as [EIP-712](https://eips.ethereum.org/EIPS/eip-712) hash where the message is `keccack256(address, timestamp)`. Make sure that no matter the language or platform timestamp is of type `int`, `int256`, `uint` or `uint256`. In the backend the message is reconstructed using [soliditysha3()](https://web3js.readthedocs.io/en/v1.7.4/web3-utils.html#soliditysha3) to verify the signature. [Web3.js](https://web3js.readthedocs.io/en/v1.8.0/web3-eth-accounts.html?#sign) and [ethers.js](https://docs.ethers.io/v5/api/signer/#Signer-signMessage) both automatically hash when using their native sign functions. This may need to be done manually if using a different library. - `timestamp` in **seconds**. Must be now +/- 5 seconds.
How to generate and verify the signature. ```js import { soliditySha3 } from 'web3-utils'; import Web3 from 'web3'; const address = '0x1234...'; // The Universal Profile address const timestamp = Math.round(Date.now() / 1000); const message = soliditySha3(address, timestamp); /** * Generate the signature - client side */ const web3 = new Web3(); const privateKey = '0x123...'; // The private key of the EOA which has SIGN permission over the Universal Profile defined in address. const signature = web3.eth.accounts.sign(message, privateKey).signature; // 👉 This signature is used in the request payload. /** * Verify the signature - relayer side */ const signer = web3.eth.accounts.recover(message, signature.signature); // Signer will be the EOA that has signed the message. // You need to verify if this EOA has a SIGN permission on the Universal Profile defined in address. ``` ```js // ... const address = '0x1234...'; // The Universal Profile address const timestamp = Math.round(Date.now() / 1000); const message = ethers.utils.solidityKeccak256( ['address', 'uint'], [address, timestamp], ); /** * Generate the signature - client side */ // [... ethers signer setup...] const signature = await ethersSigner.signMessage(arrayify(message)); // 👉 This signature is used in the request payload. /** * Verify the signature - relayer side */ const signer = ethers.utils.verifyMessage(arrayify(message), signature); // Signer will be the EOA that has signed the message. // You need to verify if this EOA has a SIGN permission on the Universal Profile defined in address. ``` To verify if the signature was signed by an authorized EOA, please refer to the [Sign-In With Ethereum](/learn/universal-profile/connect-profile/siwe.md) guide.
```json title="Request body" { "address": "0xBB645D97B0c7D101ca0d73131e521fe89B463BFD", "timestamp": 1656408193, "signature": "0xf480c87a352d42e49112257cc6afab0ff8365bb769424bb42e79e78cd11debf24fd5665b03407d8c2ce994cf5d718031a51a657d4308f146740e17e15b9747ef1b" } ``` ```json title="Response" { "quota": 1543091, // You have YYY left "unit": "gas", // could be "lyx", "transactionCount" "totalQuota": 5000000, // total gas for the month "resetDate": 1656408193 } ``` - `quota` shows available balance left in units defined by `unit`. - `unit` could be `gas`, `lyx` or `transactionCount` depending on the business model. - `totalQuota` reflects total limit. i.e. available + used quota since reset. - `resetDate` gives date that available quota will reset, e.g. a monthly allowance. Quota systems could also use a Pay As You Go model, in which case totalQuota and resetData can be omitted. ## Resources - [Mock relayer repository (GitHub)](https://github.com/lukso-network/tools-mock-relayer) --- --- sidebar_label: 'LSP17 - Contract Extension' sidebar_position: 7 description: LUKSO's LSP17 - Contract Extension for enabling smart contracts to support new functions through extensions. --- # LSP17 - Contract Extension :::info Standard Specification [LSP17 - Contract Extension](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-17-ContractExtension.md) ::: > **Goal:** Flexible way to enhance and evolve smart contracts over time // System of extensions LSP17 revolutionizes smart contract flexibility and upgradeability on the LUKSO blockchain. At its core, LSP 17 introduces a dynamic mechanism for enhancing existing contracts post-deployment, utilizing two key components: Extendable Contracts and Extension Contracts. Extendable Contracts serve as the base, open to new functionalities, while Extension Contracts hold the additional features ready to be integrated. The capability of LSP 17 lies in its forwarding strategy. Should an Extendable Contract receive a call for an undefined function, it smartly reroutes this to the appropriate Extension Contract. This routing is made possible through a specialized fallback function, ensuring that Extension Contracts can access the original call details, including the initiator and the transaction value, seamlessly appended to the calldata. This standard not only boosts a contract's capability over time but also emphasizes modularity and reusability. By avoiding the redundant deployment of similar logic across multiple contracts, LSP 17 aims to reduce network congestion and optimize gas costs. It's a testament to LUKSO's commitment to sustainable and scalable blockchain development, ensuring that smart contracts can evolve alongside the ever-changing landscape of blockchain technology and user needs. ## Introduction Once a contract 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 smart contracts, particularly those that may need to adapt to new use cases and standards over time. What is required is a method to extend the functionalities of a smart contract even after it has been deployed, allowing it to continue to support new features over time. A possible solution to this problem is to establish a system of extensions that can be added to a smart contract, enabling it to **acquire new functionalities** without the need for redeployment. ## What does this standard represent ? This standard defines a mechanism for extending a contract to support new functions through the use of **extensions**. The **_smart contract A_** implements 4 functions natively. Once this smart contract is deployed, no new functions can be added or changes made to the existing ones. In contrast, the **_smart contract B_**, which supports the **[LSP17 standard](../../contracts/contracts/LSP17Extensions/Extension4337.md)**, does not implement any native functions but rather relies on extensions for the functionality that is needed and can add more extensions in the future. Thus, smart contract B has the ability **to support an unlimited number of functionalities** and can add new functions in the future if desired. As shown in the figure above, smart contract B **changed the extension** of the `execute(..)` function to a newer version, removed the `depositToken(..)` extension, and added new extension for `socialRecover(..)` function. This system of extensions allows for a smart contract to evolve and adapt to changes that may arise in the future. By implementing this system, smart contracts can become more versatile and capable of supporting a broader range of functionalities, even after deployment. ## Specification ### Extendable vs Extension contracts This standard defines two types of contracts: - The **extendable contract**, which is the contract whose functionality we want to extend. - The **extension contract**, which is the contract providing the functionality to be added to the extendable contract. When the extendable contract is called with a function that is not natively implemented, it checks the address of the extension mapped to that function. If no extension is set for the function being called, the call **MUST revert**. But if an extension is set, the extendable contract will make a call to that extension using the **CALL** opcode, along with an additional calldata of 52 bytes containing the address of the caller (20 bytes) and the value sent along calling the function by the caller (32 bytes). The 52 bytes of additional calldata appended to the call to the extension contract provides context about the caller and the value sent in the call, allowing the extension to validate the call based on these factors if desired. > This standard does not dictate a specific method for mapping function selectors to extensions or for setting or changing these extensions in the extendable contract, developers can choose their preferred approach. ### Extension Re-usability While contracts can deploy and customize their own extensions, many smart contracts **share almost the same logic** for certain functions. In this case, the same extensions can be reused by different contracts supporting LSP17. For example, **_smart contract A & B_** are two independent contracts that implement different functions but share the same logic for verifying signatures. Therefore, they can use the same extension for signature validation for the `isValidSignature(..)` function. This approach leads to fewer contracts being deployed on the blockchain with the same logic, resulting in less chain congestion and simplifying the development process by reusing already deployed and verified extension contracts. ### Security Considerations As the extensions are called using the **CALL** opcode not **DELEGATECALL**, it' safe to assume that there is no risk of destroying the extendable smart contract through `selfdestruct`. However, it is important to be aware that **adding random contracts as extensions carelessly** can be problematic as the extensions will have the extendable contract as their caller (`msg.sender`), which can lead to impersonating the extendable contract in certain situations. ## Example A decentralized exchange cannot accept safe ERC721 or ERC1155 transfers unless it implements specific functions with specific return values. This ensures that the contract knows how to handle these tokens, thus making the transfer safe. The decentralized exchange or any other type of contract can receive tokens of these types, but what happens if another token standard emerges that people start building on and that has the same validation system where it requires the function `onERCXXXReceived(..)` ? This will make the DEX unable to receive these kinds of tokens because it did not implement this function simply because it did not exist at the time. So the only way for this DEX to support new types of tokens is to redeploy the contract with this new function, which can be problematic as many protocols depend and interact with this DEX on a specific address. This problem can be resolved by utilizing **LSP17** in the decentralized exchange (DEX). With this standard, the contract can be deployed with only the `onERC721Received(..)` or `onERC1155Received(..)` functions implemented, but additional functions such as `onERCXXXReceived(..)` can be **added as extensions** later. LSP17 also allows for the potential addition of extensions for any future standard-required functions that may arise. --- --- sidebar_label: 'LSP20 - Call Verification' sidebar_position: 8 description: LUKSO's LSP20 - Call Verification for delegating the the verification of a function call to another smart contract. --- # LSP20 - Call Verification :::info Standard Specification [LSP20 - Call Verification](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-20-CallVerification.md) ::: > **Goal:** Enhances usability when interacting with smart contracts LSP20, known as Call Verification, introduces a smart way to delegate the verification of function calls to a separate contract. This setup allows a primary contract to consult a verifier contract before and after executing a call, ensuring that specific conditions or requirements are met. It's like having a security checkpoint for your contract's functions, where the verifier acts as the gatekeeper, deciding which calls are allowed based on predefined rules. This approach is particularly useful for managing complex or evolving requirements for function calls without needing to update the main contract (through upgradability for instance). It's akin to having a dynamic rulebook that can be changed or updated easily without touching the core logic of your application. For developers, it offers a flexible and modular way to build and maintain smart contracts, providing a scalable solution for managing access and permissions within decentralized applications. ## Introduction Smart contracts often have complex requirements that need to be checked before executing a function. These requirements might change over time, adding to the complexity of managing them within the same contract. In order to maintain the integrity and security of smart contracts, while enhancing their ability to respond to change, a mechanism that enables a contract to delegate the verification of a function call to another contract can be extremely useful. This mechanism would not only ensure the fulfillment of varying requirements but also allow these requirements to be modified, updated, or enhanced without disrupting the primary contract's functionality. ## What does this standard represent ? The LSP20 standard addresses this issue by introducing a mechanism for delegating the verification of a function call to another contract. This enables the smart contract to update, modify, or enhance the requirements without affecting the primary contract's functionality, making the smart contract more versatile and adaptable. ## Specification The LSP20 standard defines two sections, detailing the expected behavior in both the delegating contract and the verification-receiving contract. ### Delegating Contract The behavior of the delegating contract is defined in the LSP20 standard. When a function in this contract is called, it should forward the call to the `lsp20VerifyCall` function implemented on the verification-receiving contract, passing the necessary arguments for verification. These arguments include: 1. Caller information 2. Amount of native tokens sent (`msg.value`) 3. Calldata provided by the caller (the function called and its arguments) The logic verifier contract uses these arguments to perform the verification. For example, it may have logic that checks how much LYX is sent and authorizes the call based on a minimum amount sent. Alternatively, it could verify solely based on the address of the caller, irrespective of the amount of LYX sent. Once the `lsp20VerifyCall` verifies and authorizes the call, an optional post-execution check can be performed through the `lsp20VerifyCallResult` function. The result of the executed function gets passed to the logic verifier, which allows for checks such as balance changes or other aspects of the contract. ### Verification-receiving Contract (Logic Verifier) The logic verifier contract, which receives the delegation for verification, is required to implement the `lsp20VerifyCall` function, and `lsp20VerifyCallResult` function if it is to be used for post-execution checks. There is no standardized logic for these functions; it is up to the implementer to decide how to use them and integrate any required logic. The parameters provide context about the call's different aspects (caller, value sent, data sent), and it's up to the implementer to decide whether to allow it or not. As mentioned, the return value of the `lsp20VerifyCall` function determines whether the `lsp20VerifyCallResult` should be invoked. ### Example Usage **Online marketplace** Imagine a smart contract that governs an online marketplace where users can buy and sell goods. Each transaction in this marketplace might require specific verification checks like verifying the availability of goods from the seller, confirming the buyer's payment ability, and potentially even checking the reputation score of both parties. By leveraging the LSP20 standard, the marketplace contract can delegate these complex verification tasks to a separate logic verifier contract. In case the marketplace wants to introduce new checks in the future such as KYC status, dispute history, etc., they simply update the logic verifier contract. This decoupling of verification logic from the primary contract ensures that the marketplace contract remains agile, adaptable, and easy to manage. **Universal Profiles with Key Manager** When a Universal Profile is owned by a Key Manager, multiple controllers can use the Universal Profile according to the permissions they are granted. However this setup creates the following problem: since the `owner()` of the Universal Profile is the Key Manager, every single interactions must be done through the Key Manager. This creates development complexity, as interactions must be crafted, encoded and send to the Key Manager instead. Calling the Universal Profile directly is not possible. LSP20 being embedded in LSP0 (the smart contract based account under a Universal Profile) simplify this complexity, allowing anyone to interact directly with the Universal Profile without having to go through the Key Manager first. The LSP20 module embedded in the Universal Profile will see that the request does not come from the Key Manager directly, and will instead forward the request and the calldata back to the Key Manager to verify the permissions of the caller first. --- --- title: LSP25 - Execute Relay Call sidebar_position: 9 description: Learn about meta transactions using the LSP25 Execute Relay Call standards and how to use multi-channel nonces to dispatch transactions that are order independent or not. --- # LSP25 - Execute Relay Call Any interactions on the blockchain, from a simple native token transfer to interact with dApps and smart contracts require users to pay for gas fees. This creates friction when onboarding new users to web3, as there is the need for the user to acquire native tokens from the start, which involves complex steps (finding an exchange, KYC, etc...). The LSP25 standards resolve this problem through **relay calls**, enabling users to interact with smart contracts on the blockchain **without needing native tokens** to pay for transaction fees. This allows a better onboarding experience for users new to cryptocurrencies and blockchain. It minimizes **UX friction** for dapps, including removing the need for users to worry about gas fee, or any complex steps needed when starting. Dapps can then leverage the relay execution features to create their own business model around building their own **relay service**, smart contracts solution on top of the Key Manager to pay with their tokens, or agree with users on payment methods including subscriptions, ads, etc .. ## How to sign relay transactions? :::tip You can use our library [**eip191-signer.js**](https://github.com/lukso-network/tools-eip191-signer) to make it easier to sign an _EIP191 Execute Relay Call transaction_. See also our [step by step Javascript guide](../../learn/universal-profile/key-manager/execute-relay-transactions.md) to sign and execute relay transactions via the Key Manager. ::: To obtain a valid signature that can be used by anyone to execute a relayed transaction (= meta transaction) on behalf of someone else, we must do the following: 1. Gather 5 things: - 1. the **payload** (an abi-encoded function call) to be executed on the linked account. - 2. the **chain id** of the blockchain where the `payload` will be executed. - 3. the address of the smart contract implementing the [`ILSP25ExecuteRelayCall`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp25-contracts/contracts/ILSP25ExecuteRelayCall.sol) interface where the **payload** will be executed. - 4. the Key Manager **nonce** of the controller. - 5. the [`validityTimestamps`](#validity-timestamps), composed of 2 x `uint128` concatenated together, where: 4.1. the left-side `uint128` corresponds to the timestamp from which the relay call is valid from. 4.2. the right-side `uint128` corresponds to the timestamp from which the relay call is valid until. 2. Once you have gathered these 5 information, you must **concatenate them all together**. 3. Then you must get the `keccak256` hash of this data. 4. After that you can sign the data to obtain a valid signature ready to be used via [`executeRelayCall(...)`](../../contracts/contracts/LSP6KeyManager/LSP6KeyManager.md#executerelaycall). ### Parameters to generate a LSP25 signature The relay transactions are signed using the [**version 0 of EIP191**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-191.md#version-0x00). The relay call data that you want to sign **MUST** be the _keccak256 hash digest_ of the following elements _(bytes values)_ concatenated together. ```javascript 0x19 <0x00> ``` | Message elements | Details | | :----------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `0x19` | Byte used to ensure that the _relay call signed data_ is not a valid RLP. | | `0x00` | The [**version 0 of EIP191**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-191.md#version-0x00). | | `LSP25 implementation address` | The address of the contract that implements the [`ILSP25ExecuteRelayCall`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp25-contracts/contracts/ILSP25ExecuteRelayCall.sol) standard interface and that will execute the relay call. | | `LSP25_VERSION` | The `uint256` number **25** that defines the current version of the LSP25 Execute Relay Call standard. | | `chainId` | The chain id of the blockchain where the Key Manager is deployed, as `uint256`. | | `nonce` | The unique [**nonce**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md#getnonce) for the payload. | | `validityTimestamps` | Two `uint128` timestamps concatenated, the first timestamp determines from when the payload can be executed, the second timestamp delimits the end of the validity of the payload. If `validityTimestamps` is 0, the checks of the timestamps are skipped | | `value` | The amount of **native tokens** that will be transferred to the [**ERC725 Account**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-0-ERC725Account.md) linked to the Key Manager that will execute the relay call. | | `payload` | The payload that will be executed. | ## Sequential _vs_ Multi-Channel nonces Since the LSP25 standard offers **relay execution** via signed message, it is important to provide security measurements to ensure that the signed message can't be repeated once executed. **[Nonces](https://www.techtarget.com/searchsecurity/definition/nonce#:~:text=A%20nonce%20is%20a%20random,to%20as%20a%20cryptographic%20nonce.)** exist to solve this problem. Using nonces prevents [replay attacks], where old signed transactions can be re-executed again. A nonce is an arbitrary number that is used only once when signing a specific transaction. The LSP25 standard introduces the concept of **channels**. **Multi-channel** nonces allow to execute signed relay calls **with**/**without** a specific order depending on the signer choice. It allows for relay calls to be executed: - **sequentially**: by enforcing their order in the same channel. - or independently from each other across multiple channels (**out of order execution**). Signed relay calls with sequential nonces should be **executed in order**, meaning a signed message with nonce 4 can't be executed before the signed message with nonce 3 has been executed. Therefore, if a sequence of signed messages must be executed sequentially, they must be signed on the same channel. Alternatively, it they should be executed independently, they should be signed across different channels. > _Example:_ > A message signed with nonce 4 on channel 1: > > - ❌ can't be executed before the message signed with nonce 3 on channel 1. > - ✅ can be executed before the message signed with nonce 3 on channel 2. ### Ordered Transaction with Sequential Nonces. With native transactions, nonces are strictly sequential, meaning that relay calls signed with incremental nonces on the same channel must be executed in order. For instance, for message number 4 to be performed, it must wait for message number 3 to complete. This is a critical problem which can limit the usage of relay execution. ### Out of order execution using Multi-Channel Nonces :::info The concept of multi channel nonce is inspired by the [Out of order execution implementation of Permit by Amx](https://github.com/amxx/permit#out-of-order-execution). ::: **Sequential nonces come with the following limitation**: Some users may want to sign multiple messages, allowing the transfer of different assets to different recipients. In that case, the recipient wants to be able to use or transfer their assets whenever they want and will certainly not want to wait on anyone before signing another transaction. **Out-of-order execution** across multiple channels solve this. By using multiple independent channels, each channel's nonce behaves as expected, but different channels are independent. Meaning that: - relay calls 2, 3, and 4 of channel 0 must be executed sequentially, - but message 3 of channel 1 is separate and only depends on message 2 of channel 1. ## How nonces are represented? Since LSP25 allows out-of-order execution of relay calls using nonces through multiple channels, the nonce includes as part of its value the channel where it should be incremented on. Nonces are represented as `uint256` from the concatenation of two `uint128` : the `channelId` and the `nonceId`. - left most 128 bits : `channelId` - right most 128 bits: `nonceId`

Example of multi channel nonce, where channelId == 5 and nonceId == 1

The current nonce can be queried using: ```solidity function getNonce(address _address, uint256 _channel) public view returns (uint256) ``` Since the `channelId` represents the left-most 128 bits, a minimal value like `1` will return a huge `nonce` number: `2**128` equal to: `340282366920938463463374607431768211456`. After the signed transaction is executed the `nonceId` will be incremented by `1`, this will increment the `nonce` by `1` because the nonceId represents the first 128 bits of the nonce, so that it will be `340282366920938463463374607431768211457`. ```solidity title="Solidity example" _nonces[signer][nonce >> 128]++ ``` The expression `nonce >> 128` represents the channel which the signer chose for executing the transaction. After looking up the nonce of the signer at that specific channel, it will be incremented by one using `++`. For sequential messages, users could use channel `0`, and for out-of-order messages, they could use channel `n`. **Important:** It's up to the user to choose the channel that he wants to sign multiple sequential orders on, not necessary `channel 0`. ## Validity Timestamps :::info Use this website to generate validity timestamps for specific date and time. ::: An essential aspect to consider in relay execution is the **time validity of the signature**. In other words: > _"for how low is my signature valid to be executed?"_. Sometimes, it is beneficial to limit the duration for which the signature is valid and can be executed, or to allow it only during a specific time period (_e.g: the period during which votes can be casted_). This can prevent potential security risks. For example, if a user signs a relay transaction and the signature is stolen or compromised, an attacker could use this signature indefinitely if there's no validity period set. To mitigate such risks, an optional **validity timestamp** can be set when generating an LSP25 signature to mark the start date and expiry date of its effectiveness. Once the timestamp has passed, the signature is no longer valid, rendering the relay transaction unusable. This is done by constructing a **validity timestamp** that can be passed as the `uint256 validityTimestamp` parameter to `executeRelayCall` and `executeRelayCallBatch` functions. Below are examples of constructing different **validity timestamps**: ### Example 1: from a specific date / time Valid only from the 1st June 2024 (midnight). Timestamp for _1st June 2024_ = `1717200000` (decimal) = `0x665A6480` (hex) ``` valid from timestamp 1717200000 vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 0x000000000000000000000000665A648000000000000000000000000000000000 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ valid until indefinitely ``` ### Example 2: set an expiry date Valid until 31st January 2025, 5pm CET. Timestamp for _31st January 2025 (5pm CET)_ = `1738339200` (decimal) = `0x679CF380` (hex) ``` valid from anytime vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 0x00000000000000000000000000000000000000000000000000000000679CF380 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ valid until 31st January 2025 (5pm CET) ``` ### Example 3: valid during a specific period Valid from 1st January 2024 (midnight CET) to 1st April 2024 (midnight CET) - Timestamp for _1st January 2024 (midnight)_ = `1704063600` (decimal) = `0x6591F270` (hex) - Timestamp for _1st April 2024 (midnight)_ = `1711926000` (decimal) = `0x6609EAF0` (hex) ``` valid from vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 0x0000000000000000000000006591F2700000000000000000000000006609EAF0 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ valid until ``` ## Security considerations for Gas Less Transaction While gas-less transactions / relay-execution is a very convenient way of using your Universal Profile to surf the blockchain, it comes with its risks. - A relay call does not enforce a gas price to execute a transaction, meaning a Relay Service can potentially send your transaction with a lower gas price in order to cut costs which might take a long time to execute. - A Relay Service can also frontrun your transaction. **Best practices:** - Make sure to only use audited, transparent, community trusted Relay Services that have passed the test of time. - Stay away from Relay Services that try to acquire users by offering cheaper prices. In the end any Relay Service must have a business model in order to work. If it does not profit from users it profits from other ways, might be shady or not. [replay attacks]: https://www.quicknode.com/guides/ethereum-development/smart-contracts/what-are-replay-attacks-on-ethereum#what-are-replay-attacks --- --- sidebar_label: 'LSP26 - Follower System' sidebar_position: 10 title: 'LSP26 - Follower System' description: LUKSO's LSP26 Follower System for managing on-chain following relationships between addresses. --- # LSP26 - Follower System :::info Standard Specification [LSP26 - Follower System](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-26-FollowerSystem.md) ::: ## Introduction LSP26 introduces a Follower System that allows any address — whether it's a smart contract account like an [ERC725Account](../accounts/lsp0-erc725account.md), or even an Externally Owned Account (EOA) — to participate in a decentralized social graph. ## What does this standard represent? LSP26 defines a smart contract registry that maintains two crucial lists for each participating address: 1. **Follows**: A list of addresses that an address is following. 2. **Followers**: A list of addresses that follow an address. This system provides a foundation for social features in blockchain applications, enabling developers to create more engaging and interconnected user experiences. ```mermaid sequenceDiagram participant User A participant LSP26 Contract participant Event Log participant User B's Profile User A->>LSP26 Contract: follow(User B's address) LSP26 Contract->>LSP26 Contract: Update internal state LSP26 Contract->>Event Log: Emit Follow event LSP26 Contract->>User B's Profile: Call universalReceiver (if LSP1 supported) User B's Profile-->>LSP26 Contract: Acknowledge (optional) LSP26 Contract-->>User A: Confirm follow action ``` ## Specification The LSP26 Follower System is implemented as a smart contract with the following key functions: ### Core Functions - `follow(address addr)`: Allows an address to follow another address. - `unfollow(address addr)`: Allows an address to unfollow another address. - `followBatch(address[] memory addresses)`: Enables following multiple addresses in a single transaction. - `unfollowBatch(address[] memory addresses)`: Enables unfollowing multiple addresses in a single transaction. ### Query Functions - `isFollowing(address follower, address addr)`: Checks if one address is following another. - `followerCount(address addr)`: Returns the number of followers for an address. - `followingCount(address addr)`: Returns the number of addresses an address is following. - `getFollowsByIndex(address addr, uint256 startIndex, uint256 endIndex)`: Retrieves a paginated list of addresses that an address is following. - `getFollowersByIndex(address addr, uint256 startIndex, uint256 endIndex)`: Retrieves a paginated list of followers for an address. ### Events - `Follow(address follower, address addr)`: Emitted when an address starts following another. - `Unfollow(address unfollower, address addr)`: Emitted when an address unfollows another. ## LSP1 Integration LSP26 integrates with [LSP1-UniversalReceiver](../accounts/lsp1-universal-receiver.md) to notify addresses when they are followed or unfollowed: - When following: Calls `universalReceiver` with `typeId`: `keccak256('LSP26FollowerSystem_FollowNotification')` - When unfollowing: Calls `universalReceiver` with `typeId`: `keccak256('LSP26FollowerSystem_UnfollowNotification')` This integration allows for real-time reactions to follower changes, enhancing the interactive capabilities of LSP26-compatible addresses. ## Deployment The official LSP26 Follower System contract is deployed at `0xf01103E5a9909Fc0DBe8166dA7085e0285daDDcA` on the LUKSO mainnet. This address is consistent across different EVM-compatible networks when deployed using the [Nick Factory contract](https://github.com/Arachnid/deterministic-deployment-proxy/tree/master). :::tip The deployed [implementation code can be found here](https://github.com/lukso-network/lsp-smart-contracts/tree/bdd0f74dc88a8165f3d27aaa86d27faa3f81cff9/packages/lsp26-contracts/contracts). ::: ## Example Use-Cases > **Goals:** > > - Establish an on-chain follower system for addresses > - Enable decentralized curation of social connections > - Provide a foundation for social features in blockchain applications 1. **Social Media Dapps**: Build decentralized social platforms with follower/following functionality. 2. **Content Curation**: Create personalized content feeds based on followed addresses. 3. **Reputation Systems**: Develop trust or influence metrics based on follower counts and relationships. 4. **Follow protocols**: Allow addresses of protocols to be followed, and protocols to react on following addresses. LSP26 Follower System provides a robust foundation for building social features into blockchain applications. By standardizing how following relationships are managed on-chain, it opens up new possibilities for decentralized social interactions and user-centric experiences in the Web3 ecosystem. --- --- sidebar_label: 'LSP9 - Vault' sidebar_position: 5 description: LUKSO LSP9 - Vault for holding assets and interacting with other smart contracts. --- # LSP9 - Vault :::info Standard Specification [LSP9 - Vault](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-9-Vault.md) ::: ## Introduction Using the Key Manager with the Universal Profile will enable third parties to execute through your profile given specific permissions, but this will not eliminate the risk of operating maliciously with your data and belongings. Third parties should be restricted when talking to a specific smart contract through the Universal Profile to avoid this risk when it almost has the same functionalities and is controlled by the Universal Profile. ## What does this standard represent? This standard defines a vault that can hold assets and interact with other contracts. It can **attach information** via [ERC725Y](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y) to itself, **execute, deploy or transfer value** to any other smart contract or EOA via [ERC725X](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725x). It can be **notified of incoming assets** via the [LSP1-UniversalReceiver](https://github.com/lukso-network/LIPs/blob/master/LSPs/LSP-1-UniversalReceiver.md) function. This standard uses the **[ERC173](https://eips.ethereum.org/EIPS/eip-173)** standard to provide ownership functions for owning and controlling the implementation contract. ## Specification ### ERC725X - Generic Executor This substandard enables the vault to execute a call on any other smart contracts, transfer the blockchain's native token, or deploy a new smart contract. Only the owner can perform these operations below. The following `operationType` MUST exist: - `0` for `CALL` - `1` for `CREATE` - `2` for `CREATE2` - `3` for `STATICCALL` The following `operationType` COULD exist: - `4` for `DELEGATECALL` - **NOTE** This is a potentially dangerous operation ### ERC725Y - Generic Data Key-Value Store This substandard enables the vault to hold arbitrary data through a generic data key/value store. It gives flexibility to the contract storage by allowing to attach any information to the contract and update it easily. :::info The data keys and values are constructed according to the **[LSP2-ERC725YJSONSchema](../metadata/lsp2-json-schema.md)** standard. ::: ### LSP1 - UniversalReceiver :::info See the **[LSP1-UniversalReceiver](/standards/accounts/lsp1-universal-receiver.md)** standard for more information. ::: :::caution The implementation of the **UniversalReceiverDelegate** used by the Universal Profile is different from the one used by the vault. Check [LSP1UniversalReceiverDelegateVault](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateVault.md) ::: This standard enables the vault to be notified of incoming transactions such as token transfers, information transfers, etc. Notifications are handy when users want to customize how their account contract reacts to certain tokens by either rejecting them or operating a specific call on each received token. The **LSP9-Vault** implements the `universalReceiver(..)` function that: - Emits an event with the typeId and data passed to it, 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. - Forwards the call to the **UniversalReceiverDelegate** contract address stored under the data key attached below, if it supports [LSP1UniversalReceiverDelegate InterfaceId](../../contracts/interface-ids.md). ```json { "name": "LSP1UniversalReceiverDelegate", "key": "0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47", "keyType": "Singleton", "valueType": "address", "valueContent": "Address" } ``` - Forwards the call to the **typeId delegate** contract address stored under the data key attached below, if it supports [LSP1UniversalReceiverDelegate InterfaceId](../../contracts/interface-ids.md). ```json { "name": "LSP1UniversalReceiverDelegate:", "key": "0x0cfc51aec37c55a4d0b10000", "keyType": "Mapping", "valueType": "address", "valueContent": "Address" } ``` > \ is the `typeId` passed to the `universalReceiver(..)` function. ### LSP14 - Ownable2Step :::info See the **[LSP14 - Ownable2Step](../access-control/lsp14-ownable-2-step.md)** standard for more information. ::: This standard allows for the **LSP9 - Vault** contract's ownership to be controlled by an EOA or by another contract, by implementing **3 essential methods**: - [`transferOwnership()`](/contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md) - [`acceptOwnership()`](/contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md) - [`renounceOwnership()`](/contracts/contracts/LSP14Ownable2Step/LSP14Ownable2Step.md) ### Flow Developers could use the vault to hold assets and, as mentioned before, could be used to restrict third parties to only operate on the assets and metadata of the vault and not the Universal Profile. The Universal Profile's metadata and assets are safe if the third party tries to act maliciously. **1.** The **protocol** should be allowed to only talk to the vault A1 through [AllowedAddresses permission](/standards/access-control/lsp6-key-manager#address-permissions). **2.** All the **protocol** transactions should be routed through the vault. Otherwise, the transaction will **revert**. --- --- sidebar_label: 'ERC725 - Foundation of the LSPs' description: 'ERC725X operations: call, create, create2, staticcall, delegatecall, and ERC725Y Generic Data Key/Value Store.' --- # ERC725 :::info Standard Specification [ERC725 - General Executor and Data Key/Value Store](https://github.com/ERC725Alliance/ERC725/blob/develop/docs/ERC-725.md) ::: ## Introduction EOAs (Externally Owned Accounts) are controlled by private keys and can perform specific operations such as [**CALL**](https://www.evm.codes/#f1) to interact with other addresses and [**CREATE**](https://www.evm.codes/#f0) to create other smart contracts. However, they do not have any internal logic or storage capabilities. Smart contracts, on the other hand, can be controlled by EOAs or other smart contracts, which provide a flexible ownership management mechanism. They can store data and perform more complex operations, making them useful for a wide range of use cases, including digital assets, decentralized applications, DAO and smart contract based accounts. ## ERC725X There is a growing need for more functionalities beyond the basic **CALL** and **CREATE** that externally owned accounts (EOA) can do. These two opcodes enables interaction with other addresses on the blockchain to perform tasks such as calling functions, transferring native tokens, and creating new contracts. As the number of use cases for smart contracts increases, so does the need for additional functionality. One such operation is the ability to manipulate storage of a contract and execute other contracts logic in the caller context (delegatecall), which is not possible with EOA but can be helpful to extend the logic of a contract. Additionally, the ability to create contracts at predetermined addresses (CREATE2), as well as, performing calls without causing any state changes (staticcall) are also important features that are currently not available to EOAs. The need for these additional operations highlights the importance of having more functionality built into smart contracts. This standard aims to provide this functionality and enable the creation of more advanced and versatile smart contracts. ### Specification **ERC725X** is a standard that provides four types of operations that can be performed in a smart contract. These operations are defined as follows: :::warning The DELEGATECALL operation is very dangerous as it can alter the state of the contract and also change owner variables at will. Additionally it can destroy the contract by calling selfdestruct on other contracts. ::: | Operation number | Operation type | Description | | :--------------: | :----------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------ | | 0 | [`CALL`](https://www.evm.codes/#f1) | Transfer native tokens or calls smart contract functions. | | 1 | [`CREATE`](https://www.evm.codes/#f0) | Create a new smart contract based on the contract address and nonce. | | 2 | [`CREATE2`](https://eips.ethereum.org/EIPS/eip-1014) | Create a new smart contract based on the contract address, bytecode and the salt. The address can be predetermined. | | 3 | [`STATICCALL`](https://eips.ethereum.org/EIPS/eip-214) | Call another smart contract while disallowing any modification to the state during the call. | | 4 | [`DELEGATECALL`](https://eips.ethereum.org/EIPS/eip-7) | Run the function from another contract, but use the context of the current contract. | ## ERC725Y Generic Data Key/Value Store Using smart contracts to store data on the blockchain can be beneficial when that data will be used or referenced by other smart contracts. One limitation of this approach is that 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 if additional data needs to be stored in the future, as it would require deploying a new version of the contract. For example, if a token contract is deployed with variables for the token name, symbol, and decimals, it is not possible to add new variables for the creators or future collaborators. What is needed is a dynamic way to attach data to a contract even after it has been deployed. ### Specification ERC725Y solves this problem by standardizing 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 to redeploy the contract. Instead of representing the variable with a specific name such as `age`, or `name`, etc .. They are referenced as `bytes32` data key. Same as solidity treat variables under the hood. :::note See the section **["Layout of State Variables in Storage"](https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html)** in the Solidity documentation for more information about the structure of smart contract storage. ::: #### Normal contract vs ERC725Y 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(...)`. #### ERC725Y Data Representation Since the data is set in the contract's storage as **bytes32**/**bytes** data key/value pair, a representation of this data should be standardized to avoid having each user writing the data in a different way and to have the ability to getData from other people's contract storage in a unified way. **[LSP2 - ERC725YJSONSchema](./metadata/lsp2-json-schema.md)** is the standard used by the LSPs to organize how the data should be represented as **bytes32**/**bytes** pairs. ## Ownership An EOA (Externally Owned Account) is controlled by a private key, which means that only the holder of this **private key** can execute transactions and perform **CALL or CREATE** operations from this EOA. This can be limiting in certain use cases, such as when it is necessary to share the ability to interact with the address from multiple individuals or entities. Sharing the private key, however, would compromise the security of the EOA as anyone with access to the private key would be able to execute transactions from the EOA. One solution to this problem is to use a smart contract, which can be programmed to have specific addresses that can execute transactions. §§§§eswaq **ERC725** utilizes the [**ERC173**](https://eips.ethereum.org/EIPS/eip-173) standard for ownership management. Under this standard, an address is designated as the owner of the contract, and is the only one able to interact with other addresses and create contracts using the `execute(..)` functions. The owner is also the only one able to set data in the contract using the `setData(..)` function. This method provides significant control over who can access and operate the contract, and eliminates the need to share private keys. The owner of the contract is defined as an address, which can be an EOA (Externally Owned Account) or another contract with specific features, such as a DAO voting contract or a KeyManager. --- --- sidebar_label: 'LSP16 - Universal Factory' sidebar_position: 1 description: LUKSO's LSP16 - Universal Factory for deploying the same smart contracts to the same address across different chains. --- # LSP16 - Universal Factory :::info Standard Specification [LSP16 - Universal Factory](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-16-UniversalFactory.md) ::: > **Goals:** > > - Multi-chain compatibility > - CREATE2 opcode for the deployment of various contracts LSP16 introduces a universal factory for deploying smart contracts using the CREATE2 opcode, ensuring consistent contract addresses across multiple blockchains. This standard allows for the deployment of various contract types, including initializable contracts, with initialization data included in the deployment process to prevent address squatting. By leveraging the Nick Factory for deployment, LSP16 enables a decentralized way to replicate contract addresses on any chain, facilitating multi-chain identity and asset management. This approach offers significant advantages, such as ensuring that assets sent across chains reach their intended contract by maintaining consistent contract addresses. LSP16 is a cornerstone for building interoperable and scalable blockchain applications, offering developers a reliable tool for multi-chain deployment and management. ## Introduction The use of different blockchain networks has brought with it a unique challenge: ensuring that an entity or user controlling an address on one chain can have the same control on another chain. For Externally Owned Accounts, this is known, as possessing the private key of the address means control over it regardless of the chain. Currently, this control isn't guaranteed when it comes to smart contracts. Even if a contract resides at a particular address on one chain, the same contract does not necessarily exist at the same address on another chain or even a possibility of not having a contract at all on the other chain at the same address. When it comes to EOAs, people can send assets to EOA on any chain as there is a known control over any chain. This situation creates a problem where assets might be sent to a contract on a different chain under the assumption that it's identical and under the sender's control, which may not be the case. Therefore, it's preferable to opt for a situation that can allow for the creation of identical smart contracts at the same addresses across different chains. ## What does this standard represent? This standard defines a contract called **Universal Factory** which provide a way to deploy the same contracts at the same addresses across different chains given few requirements. This multi-chain compatibility eliminates the **risk of asset loss** due to mismatched contracts and addresses. Further, it opens up the possibility of establishing a kind of multi-chain identity, which is particularly beneficial for factory, registry, and account-based contracts. ## Specification :::tip Check the [**LSP16UniversalFactory contract functions**](../../contracts/contracts/LSP16UniversalFactory/LSP16UniversalFactory.md) to know how to deploy contracts at the same address across different chains. Check the **JavaScript** guides to know [**How to deploy contracts at the same address across different chains.**](../../learn/other-guides/deploy-multichain-contracts.md) ::: LSP16 establishes a range of functions to deploy different types of contracts using the [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode, including standard and initializable contracts (proxies). For initializable contracts, the initialization data is included into the salt to prevent address squatting across chains. Additionally, it ensures that the same bytecode and salt will create the same contract address on different chains, given that the UniversalFactory contract was deployed on the same address on each chain. For a contract to be replicated at the same address across different chain, it should be deployed using the same: - Bytecode - Salt - Initialization Data (If the contract is initializable) ## Example Suppose Alice wants to deploy a **UniversalProfile** on **LUKSO Mainnet** owned by her EOA. If she deploys the UniversalProfile using the UniversalFactory on LUKSO, she can later deploy the same UniversalProfile owned by her EOA on **Ethereum Mainnet** using the UniversalFactory with **producing the same address**. This interoperability also ensures that if Alice, or anyone else, sends assets to the contract's address on one chain, **those assets can be accessed** on the other chain as well, preventing inadvertent loss of assets and creating a **multi-chain identity**. --- --- sidebar_label: 'LSP23 - Linked Contracts Factory' sidebar_position: 2 description: LUKSO's LSP23 Linked Contracts Factory to allow the deployment of primary and secondary smart contracts that are linked together. --- # LSP23 Linked Contracts Factory :::info Standard Specification [LSP23 - Linked Contracts Factory](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md) ::: LSP 23 simplifies the deployment of interdependent smart contracts by providing a standardized way to deploy and link contracts that require knowledge of each other's details at creation. It addresses the challenge of circular dependencies in contract deployment, enabling the establishment of complex contract systems with ease. Through the use of post-deployment modules, LSP 23 also facilitates additional actions after contracts are deployed, streamlining the process and reducing potential errors. This standard is particularly beneficial for deploying contract ecosystems where components need to interact closely, ensuring seamless integration and interaction across the deployed contracts. ## Introduction Deploying smart contracts that are interdependent can be a complex process. Often, two or more contracts need each other's addresses at deployment, creating a circular dependency that can be challenging to resolve. The LSP23 Linked Contracts Factory addresses this issue by providing a unified interface for deploying linked contracts with an optional post-deployment execution. This standard simplifies the deployment of complex contract systems, making it easier for developers to deploy interdependent contracts without the need for manual intervention. ## What does this standard represent? This standard represents a smart contract factory that allows users to deploy **primary** and **secondary** contracts that are linked together. It also supports deploying contracts as `ERC1167` minimal proxies. The factory can execute post-deployment modules to perform additional logic after deploying the contracts (_example: pass the address of the secondary contract to the primary contract's `constructor` / initializer function_) Like [`LSP16`](./lsp16-universal-factory.md), the `LSP23` standard addresses the issue of deterministic address generation for contracts across different chains by generating the salt for contract deployment within the function, ensuring a fully decentralized deployment process. This approach guarantees consistent contract addresses across multiple chains and prevents "squatting addresses", enhancing the security and integrity of the deployment process. ## Specification :::tip Check the [**LSP23 LinkedContractsFactory contract functions**](/contracts/contracts/LSP23LinkedContractsFactory/) to know how to deploy contracts at the same address across different chains. ::: The `LSP23LinkedContractsFactory` contract provides two main functions for deploying linked contracts: [`deployContracts`](../../contracts/contracts/LSP23LinkedContractsDeployment/LSP23LinkedContractsFactory.md#deploycontracts) and [`deployERC1167Proxies`](../../contracts/contracts/LSP23LinkedContractsDeployment/LSP23LinkedContractsFactory.md#deployerc1167proxies). Both functions allow the deployment of primary and secondary contracts, with optional post-deployment modules. You can find the [`IPostDeploymentModule`](../../contracts/contracts/LSP23LinkedContractsDeployment/IPostDeploymentModule.md) interface. ## Example The deployment process for a [`Universal Profile`](../accounts/introduction.md) and its associated [`Key Manager`](../access-control/lsp6-key-manager.md) involves a series of steps that ensure proper integration and ownership assignment between the two contracts. The `Universal Profile` serves as the primary contract, while the `Key Manager` functions as the secondary contract. Both contracts require each other's addresses during deployment. Using, `LSP23`, the deployment flow is outlined as follows: - Deploy the `Universal Profile`, designating the post-deployment module as the initial owner of the `Universal Profile`. - Deploy the `Key Manager`, providing it with the address of the newly deployed `Universal Profile`. - Execute the post-deployment module to transfer ownership of the `Universal Profile` to the `Key Manager`. Additionally, carry out any other post-deployment logic as necessary. --- --- title: 'Introduction' description: Introduction to LSPs (LUKSO Standard Proposals). --- import StandardsGallery from '@site/src/components/StandardsGallery'; # The LUKSO Standard Proposals (LSPs) Discover the LSPs, the standards that represent the foundation of **LUKSO's ecosystem**. They can be used as **building blocks** and combined to create new and innovative protocols or dApps on the LUKSO Blockchain.
:::info **👉 📺 [Watch Fabian's Presentation from ETHCC6 2023](https://www.youtube.com/live/MKFB_pGse4A?si=Yuo_sYRrhrtAYycG&t=312) for a an high-level overview! 🦅** ::: The LSPs introduce new concepts like **blockchain-based accounts** (_e.g: **Universal Profiles**_), **Digital Assets, NFT 2.0** and **Permissions Management**. This section describes the fundamentals of the standards, their technical aspects and their applications and use cases across the LUKSO ecosystem. The **LUKSO Standards Proposals (LSPs)** represent the **main building blocks** of the LUKSO ecosystem. People, groups, and organizations can use them to build blockchain-based applications that aim to maximize the user experience, allow more flexibility and interaction, and open doors to innovation. The use of smart contracts and standards like the LSPs can mitigate some centralization risks by allowing for decentralized ownership and control of accounts and assets. :::note LSPs are **not order-dependent**. They can be related to each other in a **backward or forward** order. Meaning a standard could use another one that comes after or before in order. For example **[LSP0 - ERC725Account](../standards/accounts/lsp0-erc725account.md)** uses **[LSP1 - UniversalReceiver](../standards/accounts/lsp1-universal-receiver-delegate.md)**, **[LSP2 - ERC725YJSONSchema](../standards/metadata/lsp2-json-schema.md)** and could use **[LSP3 - ProfileMetadata](../standards/metadata/lsp3-profile-metadata.md)**, etc. ::: ## Smart Contracts in Solidity The **[default implementation of these standards in Solidity](../contracts/introduction.md)** is available as Open Source Software. They can be used as a base by developers to build their applications. > See the [Contracts](../contracts/introduction.md) section for the Solidity implementation of these standards and their ABI docs. ## LSP Standard Specifications See [LUKSO Improvement Proposals - LIPs (GitHub)](https://github.com/lukso-network/LIPs) if you are looking for the design and formal specifications of each LSP Standards. Developers wishing to understand the logic behind the standards and their tradeoffs within are well-advised to read these documents alongside the Solidity code itself. ## Further Resources - [The New Standard for Blockchain Accounts and NFT 2.0 (YouTube)](https://www.youtube.com/watch?v=7u0WGAS1k_Q) - [Tech Time with Fabian Ep.1 - LUKSO NFT's 2.0 Explained (YouTube)](https://www.youtube.com/watch?v=Nx5D9QWNIhI) - [Fabian Vogelsteller talks at BLOCKCHANCE 2021 about LUKSO (YouTube)](https://www.youtube.com/watch?v=aoZE_0Ey1SQ) - [Fabian Vogelsteller talks at NFT.NYC 2021 about the new Standards (YouTube)](https://www.youtube.com/watch?v=skA4Y-vvt5s) - [Developer DAO - Dev & Tell | Yamen - LUKSO Network (YouTube)](https://www.youtube.com/watch?v=1OeBpJIstSQ) - [ERC725 Alliance website](https://erc725alliance.org/) --- --- sidebar_label: 'LSP10 - Received Vaults' sidebar_position: 8 description: LUKSO LSP10 - Received Vaults for keeping track of all the vaults owned by a smart contract. --- # LSP10 - Received Vaults :::info Standard Specification [LSP10 - Received Vaults](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-10-ReceivedVaults.md) ::: ## Introduction To keep track of all the vaults that an address owns, we should avoid the same problem mentioned in [LSP5-ReceivedAssets](./lsp5-received-assets.md), which is not informing recipients and senders about the ownership transfer of [LSP9-Vaults](../accounts/lsp9-vault.md). One way to avoid this problem is to create generic metadata keys that developers should register in the smart contract storage, representing how many different vaults you own, their type, and the address of the transferred vault contract. ## What does this standard represent ? :::tip Recommendation Make sure to understand the **[ERC725Y Generic Key/Value Store](../erc725.md#erc725y---generic-data-keyvalue-store)** and **[LSP2 - ERC725YJSONSchema](../metadata/lsp2-json-schema.md)** Standards before going through the ERC725Y Data Keys. ::: This Metadata standard describes two data keys that can be added to an [ERC725Y](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md) smart contract to keep track of received and owned [LSP9-Vaults](../accounts/lsp9-vault.md). ### `LSP10Vaults[]` This data key represents a list of all the vaults owned by the contract. ```json { "name": "LSP10Vaults[]", "key": "0x55482936e01da86729a45d2b87a6b1d3bc582bea0ec00e38bdb340e3af6f9f06", "keyType": "Array", "valueType": "address", "valueContent": "Address" } ``` :::tip Recommendation It is recommended to query the **`LSP10Vaults[]`** data key to check if a smart contract supports the **[LSP10 - ReceivedVaults](./lsp10-received-vaults.md)** standard. ::: ### `LSP10VaultsMap` This data key represents a map key holding both: - an [ERC165 interface ID](https://eips.ethereum.org/EIPS/eip-165) to quickly identify the standard used by each vault's smart contract (without the need to query the assets contracts directly). - the index in the [`LSP10Vaults[]`](#lsp10vaults-) array where the received vaults addresses are stored. The `LSP10VaultsMap` data key also helps prevent adding duplications to the array when automatically added via smart contract (_e.g.,_ an [LSP1-UniversalReceiverDelegate](../accounts/lsp1-universal-receiver-delegate.md)). ```json { "name": "LSP10VaultsMap:
", "key": "0x192448c3c0f88c7f238c0000
", "keyType": "Mapping", "valueType": "(bytes4,uint128)", "valueContent": "(Bytes4,Number)" } ``` ### Flow :::info Note The data keys are also set on the **sender's Universal Profile** to remove the vault contract address when sent to the recipient. ::: If set when transferring vaults, these data keys are automatically updated in the UniversalProfile storage via the [LSP1UniversalReceiverDelegateUP](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP.md) contract. --- --- sidebar_label: 'LSP12 - Issued Assets' sidebar_position: 9 description: LUKSO LSP12 - Issued Assets for keeping track of all the assets issued by a smart contract. --- # LSP12 - Issued Assets :::info Standard Specification [LSP12 - Issued Assets](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-12-IssuedAssets.md) ::: ## Introduction Keeping track of all the assets that addresses create is currently unfeasible where listing the issued assets is being done by centralized services. This inconvenience brings light to the following problem: the absence of a standard way to read the issued assets on/off-chain which allow users to create fake assets claiming that they are the original ones. One way to solve this problem is to create generic metadata keys that would register in the smart contract storage how many different assets a smart contract has issued and their addresses. These keys will be a reference for users to check the authenticity of assets. ## What does this standard represent ? :::tip Recommendation Make sure to understand the **[ERC725Y Generic Key/Value Store](../erc725.md#erc725y---generic-data-keyvalue-store)** and **[LSP2 - ERC725YJSONSchema](../metadata/lsp2-json-schema.md)** Standards before going through the ERC725Y Data Keys. ::: This Metadata standard describes two data keys that can be added to an [ERC725Y](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md) smart contract to keep track of issued assets. ### `LSP12IssuedAssets[]` This data key represents a list of all issued assets by the contract. ```json { "name": "LSP12IssuedAssets[]", "key": "0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd", "keyType": "Array", "valueType": "address", "valueContent": "Address" } ``` ### `LSP12IssuedAssetsMap` This data key represents a map key holding both: - an [ERC165 interface ID](https://eips.ethereum.org/EIPS/eip-165) to quickly identify the standard used by the issued assets. (Could be LSP7 or LSP8 asset) - the index in the [`LSP12IssuedAssets[]`](#lsp12issuedassets) array where the issued assets addresses are stored. ```json { "name": "LSP12IssuedAssetsMap:
", "key": "0x74ac2555c10b9349e78f0000
", "keyType": "Mapping", "valueType": "(bytes4,uint128)", "valueContent": "(Bytes4,Number)" } ``` ### Asset Verification Flow The full **verification flow** for an asset should contain a check on the **asset** and the **issuer** smart contract. - **Step 1:** Should check on the asset smart contract, the **owner** or the **[LSP4Creators Array](../tokens/LSP4-Digital-Asset-Metadata.md#lsp4creators)** data key and retrieve the address of the creator from the array. - **Step 2:** Should check on the address retrieved in **Step 1** that the address of the asset being checked, matches one of the assets addresses stored in the **[LSP12IssuedAssets Array](#lsp12issuedassets)** of the UniversalProfile. --- --- sidebar_label: 'LSP2 - ERC725Y JSON Schema' sidebar_position: 3 description: LUKSO's LSP2 - ERC725Y JSON Schema for better abstraction on top of the storage of a smart contract. --- # LSP2 - ERC725Y JSON Schema :::info Standard Specification [LSP2 - ERC725Y JSON Schema](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md) ::: :::success Recommendation Our [JavaScript library **erc725.js**](../../tools/dapps/erc725js/getting-started.md) makes it easy to read + write data encoded according to the LSP2 Schema without manually going through all the encoding complexity. ::: > **Goal:** Introduces a JSON schema for ERC725Y data keys The LUKSO Standard Proposal 2, or LSP2, introduces a new way to structure, store and represent data stored in smart contracts through the ERC725Y JSON Schema. This innovative approach allows for the storage of structured data directly on-chain, utilizing the flexibility and accessibility of JSON formatting for ERC725Y data keys. Imagine being able to store your blockchain identity's profile information, preferences, or even configuration settings in a standardized, easily retrievable format. That's what LSP2 enables. By adopting the ERC725Y JSON Schema, developers can define clear, consistent data structures for their applications, enhancing interoperability and ease of integration across the LUKSO ecosystem. This structured approach not only simplifies data management but also paves the way for more complex and user-friendly decentralized applications. With LSP2, the potential for creating rich, interactive, and personalized user experiences on the blockchain becomes a reality, opening up a world of possibilities for developers and users alike. ## Introduction The storage of a smart contract consists of multiple **storage slots**. These slots are referenced by a **slot number** (as an **integer**) starting from slot 0. Each piece of data (= contract state) in a smart contract is stored as raw **bytes** under a specific storage slot. > In summary, smart contracts understand only two languages: bytes and uint256. > Take the following key-value pair, for instance. It is not easy to infer the meaning of these data keys by reading them as **bytes**. ```text (key) => (value) 0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1 => 0x4d7920546f6b656e20322e30 ``` Using **slot numbers** and **raw bytes** makes the contract storage very hard to handle. [ERC725Y](../accounts/lsp0-erc725account.md#erc725y---generic-key-value-store) solves part of the problem through a more flexible storage layout, where data is addressed via `bytes32` keys. However, with such low-level languages, it is difficult for humans to understand the data in the storage. The main problem around smart contract storage also arises when data is stored differently, depending on individual use cases and application needs. No standard schema defines "what the data stored under a specific data key represents". These two issues make it very hard for smart contracts to interact with each other and for external services to interact with contracts' storage. ## What does this standard represent? The LSP2 Standard aims to offer a better abstraction on top of the storage of a smart contract. This standard introduces a JSON schema that enables to represent the storage of a smart contract through more understandable data keys. It makes the data stored in a smart contract more organized. By introducing a schema, we can represent contract storage in the same way across contracts in the network. Everyone has a unified view of the data stored between smart contracts. Developers can quickly parse data, and contracts or interfaces can read or write data from or to the contract storage in the same manner. The standardization makes smart contracts **more interoperable with each other**. ## Specification LSP2 introduces new ways to encode data, depending on its type. From single to multiple entries (like arrays or maps). A data key in the contract storage can be defined as a JSON object with properties that describe the key. The schema includes information about the data key itself, as well as its value to explain what this data represents. ```json { "name": "LSP4TokenName", "key": "0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1", "keyType": "Singleton", "valueType": "string", "valueContent": "String" } ``` Below are descriptions of what each properties in the JSON schema represent. | Property in JSON schema | Explanation | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | data key `name` | Describe what kind of metadata value is stored under this data key in a human readable way. | | data `key` itself | The `bytes32` hex value used when calling [`setData`](../../contracts/contracts/ERC725/ERC725.md#setdata) or [`setDataBatch`](../../contracts/contracts/ERC725/ERC725.md#setdatabatch) on the smart contract. | | `keyType` | Define if the information stored under this data key is a single entry (_`Singleton`_), a list of items (_`Array`_), or map to a specific field like an address or unique identifier (_`Mapping` and `MappingWithGrouping`_). | | `valueType` | Describe the low level type to be used to encode or decode the data. | | `valueContent` | Describe how to interpret the data being fetched (_is it some text? is it some URL? is it an address? is it a JSON object?_) | ## Data Key Types A Data Key Type defines **HOW** a 32 bytes data key is constructed, representing how a particular data key type is described in 32 bytes. For example, `Singleton` data keys are simple keccak256 hashes of the key name string. Other Data Key Types are constructed of slices of hashes to group different key name parts or define array element keys. The LSP2 Standard defines several **data key types**: - [Singleton](#singleton) - [Array](#array) - [Mapping](#mapping) - [MappingWithGrouping](#mappingwithgrouping) ### Singleton A **Singleton** data key is helpful to store a unique single value under a single data key. Below is an example of a **Singleton** data key. ```json { "name": "LSP4TokenName", "key": "0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1", "keyType": "Singleton", "valueType": "string", "valueContent": "String" } ``` ### Array Developers can use a data key of the type Array to store a list of elements of the same data type. They are accessed by an _index_ that defines their position within it. The Array elements are arranged systematically, in the order they are added or removed to or from it. The **main properties** of the LSP2 Array data key type are: - _ordering matters_ :exclamation: - _duplicates are permitted_ :white_check_mark: A data key type Array can be useful when there is the need to store a large group of similar data items under the same data key. For instance, a list of tokens or NFTs that an address has received. Below is an example of an Array data key: ```json { "name": "LSP5ReceivedAssets[]", "key": "0x6460ee3c0aac563ccbf76d6e1d07bada78e3a9514e6382b736ed3f478ab7b90b", "keyType": "Array", "valueType": "address", "valueContent": "Address" } ``` --- ### Mapping The Mapping data key type is similar to the concept of lookup tables. It can be used to map data that have a shared significance (such as items derived from a common ancestor), and search or query specific elements efficiently. The **main properties** of the LSP2 Mapping data key type are: - _ordering does not matter_ :white_check_mark: - _duplicates are not permitted_ :x: The data being mapped can be words that have a specific meaning for the protocol or application implementation, or underlying data types (= ``) like `address`, `bytesN`, `uintN`, etc. For ``, all the data types are left padded. If the type is larger than 20 bytes, the second part of the key is: - left-cut for `uint`, `int` and `bool` - right cut for `bytes` and `address` Below are some examples of the **Mapping** key type. - mapping to **words:** `SupportedStandards:LSP3Profile`, `SupportedStandards:LSP4DigitalAsset`, `SupportedStandards:LSP{N}{StandardName}`, etc... - mapping to **``**, like an `address`: `LSP5ReceivedAssetsMap:
` - mapping to **``**, like a `bytes32`: `LSP8MetadataAddress:` #### Example 1: Mapping as `FirstWord:SecondWord` ```json { "name": "SupportedStandards:LSP3Profile", "key": "0xeafec4d89fa9619884b600005ef83ad9559033e6e941db7d7c495acdce616347", "keyType": "Mapping", "valueType": "bytes4", "valueContent": "0xabe425d6" } ``` #### Example 2: Mapping as `FirstWord:
` (``) `address` value = `0xcafecafecafecafecafecafecafecafecafecafe` ```json { "name": "LSP5ReceivedAssetsMap:
", "key": "0x812c4334633eb816c80d0000cafecafecafecafecafecafecafecafecafecafe", "keyType": "Mapping", "valueType": "(bytes4,uint128)", "valueContent": "(Bytes4,Number)" } ``` #### Example 3: Mapping as `FirstWord:` (``) `bytes32` value = `0xaaaabbbbccccddddeeeeffff111122223333444455556666777788889999aaaa`. The `bytes32` value is **right-cut**. ```json { "name": "LSP8MetadataAddress:", "key": "0x73dcc7c3c4096cdc7f8a0000aaaabbbbccccddddeeeeffff1111222233334444", "keyType": "Mapping", "valueType": "Mixed", "valueContent": "Mixed" } ``` ### MappingWithGrouping :::warning `:::` You must take into consideration the fact that if you choose the same value to hash for `firstWord` and `thirdWord` there is a 0.0000000233% chance that two random values for the `secondWord` will result in the same data key. ::: A data key of type **MappingWithGrouping** is similar to the **[Mapping](#mapping)** data key type, except that sub-types can be added to the main mapping data key. For instance, it can be used to differentiate various types from the primary mapping data key, like different types of permissions (see [LSP6 - Key Manager](../access-control/lsp6-key-manager.md)). Below is an example of a MappingWithGrouping data key: ```json { "name": "AddressPermissions:Permissions:
", "key": "0x4b80742de2bf82acb3630000
", "keyType": "MappingWithGrouping", "valueType": "bytes32", "valueContent": "BitArray" }, ```
Solidity Example Whenever you want to generate a data key of `keyType` **MappingWithGrouping**: ```solidity bytes32 dataKey = bytes32( bytes.concat( bytes6(keccak256(bytes(firstWord))), bytes4(keccak256(bytes(secondWord))), bytes2(0), bytes20(keccak256(bytes(thirdWord))) ) ); ```
## `valueType` encoding :::success Recommendation Watch our following video for an overview of how static types (`uintM`, `bytesN`, `bool`), `bytes` and `string` are encoded in the [ERC725Y](../erc725.md#erc725y-data-representation) storage of a smart contract using the LSP2 standard. :::
LSP2 differs in terms of how data is encoded depending on its type. As a basic summary, LSP2 and the [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) encoding specification can be compared as follow: **Differences:** - static types (types that have a fixed size like `uintM`, `bytesN` and `bool`) are encoded as they are without any padding to make a 32 bytes long word. - `bytes` and `string` are also encoded as they are as arbitrary bytes, without any 32 bytes words for the offset or the data length. **Similarities** - any array types (_e.g: `uintM[]`, `bytesN[]`, `bool[]`, etc..._) in LSP2 are ABI encoded the same way as the ABI specification. Below is a table that describe the LSP2 encoding format for `valueTypes`. | `valueType` | Encoding | Example | | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | | `bool` | `0x01` or `0x00` | `true` --> `0x01` / `false` --> `0x00` | | `string` | as utf8 hex bytes
**without padding ❌** | `"Hello"` --> `0x48656c6c6f` | | `address` | as a 20 bytes long address | `0x388C818CA8B9251b393131C08a736A67ccB19297` | | `uint256` | as a hex value 32 bytes long
**left padded** with zeros to fill 32 bytes | number `5` --> `0x0000000000000000000000000000000000000000000000000000000000000005` | | `uintN`
(where ` N` is a multiple of **8 bits** in the range`8 > N > 256`) | as a hex value **`M` bits long**
**left padded** with zeros to fill `M` bytes | number `5` as `uint32` --> `0x00000005` | | `bytes32` | as a hex value 32 bytes long
**right padded** to fill 32 bytes | `0xca5ebeeff00dca11ab1efe6701df563bc1add009076ded6bcf4c6f771f2e3436` | | `bytes4` | as a hex value 4 bytes long
**right padded** to fill 4 bytes | `0xcafecafe` | | `bytesN` (from 1 to 32) | as a hex value **`N` bytes long**
**right padded** to fill `N` bytes | | | `bytes` | as hex bytes of any length
**without padding** ❌ | `0xcafecafecafecafecafecafecafecafe...` | ## `valueContent` encoding ### `VerifiableURI` A [`VerifiableURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#verifiableuri) as defined by the **LSP2 - ERC725Y JSON Schema** is a type of encoding that allows anyone to verify that the content at the URI hasn't been tampered with. It contains both a verification hash and the URI where the data can be found. The encoding format is: | Bytes | Length | Description | | ----------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `0x0000` | 2 bytes | Header — `0x0000` indicates a VerifiableURI | | Storage options:
- `6f357c6a` (off-chain)
- `8019f9b1` (on-chain) | 4 bytes | Verification method: first 4 bytes of the keccak256 hash of the following words:
- `"keccak256('utf8')"` = `bytes4(keccak256('keccak256(utf8)'))`, or
- `"keccak256(bytes)"` = `bytes4(keccak256('keccak256(bytes)'))` | | `0020` | 2 bytes | Hash length — `32` bytes in hex | | `<32 bytes>` | 32 bytes | `keccak256` hash of the JSON content | | `` | variable | UTF-8 encoded URI (e.g., `ipfs://` or `data:...`) | :::warning Don't Forget the Hash Length! A common mistake is to omit the `0020` (hash length) bytes from the VerifiableURI header. The full header for `keccak256(utf8)` is **`0x00006f357c6a0020`**, not just `0x00006f357c6a`. Missing the `0020` will make the data unreadable by clients. ::: For **off-chain storage on IPFS** (where the JSON file or image is uploaded to IPFS), the verification method is `keccak256(utf8)` with method ID `6f357c6a`. The encoded data **MUST have the following header:** ``` 0x00006f357c6a0020... ``` For **on-chain storage in base64** (where the JSON file or image is embedded directly in the URI as `data:application/json;base64,...`), the verification method is to `keccak256(bytes)` with method ID `8019f9b1`. The encoded data **MUST have the following header:** ``` 0x00008019f9b10020... ``` --- --- sidebar_label: 'LSP3 - Profile Metadata' sidebar_position: 4 description: 'LUKSO LSP3-Profile-Metadata: a Metadata standard that defines specific data keys to describe a profile.' --- # LSP3 - Profile Metadata :::info Standard Specification [LSP3 - Profile Metadata](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md) ::: ## Introduction The implementation of the **[LSP0-ERC725Account](../accounts/lsp0-erc725account.md)** standard does not contain any metadata describing the account. **LSP3-Profile-Metadata** is a Metadata standard that defines specific data keys to describe a profile. A Universal Profile combines the following two standards. - **[LSP0-ERC725Account](../accounts/lsp0-erc725account.md)**: an interface for a smart contract-based account. - **LSP3-Profile-Metadata**: a set of predefined [ERC725Y](../accounts/lsp0-erc725account.md#erc725y---generic-key-value-store) Data keys to describe the profile. ## ERC725Y Data Keys :::tip Recommendation Make sure to understand the **[ERC725Y Generic Key/Value Store](../erc725.md#erc725y---generic-data-keyvalue-store)** and **[LSP2 - ERC725YJSONSchema](../metadata/lsp2-json-schema.md)** Standards before going through the ERC725Y Data Keys. ::: ### `SupportedStandards:LSP3Profile` ```json { "name": "SupportedStandards:LSP3Profile", "key": "0xeafec4d89fa9619884b600005ef83ad9559033e6e941db7d7c495acdce616347", "keyType": "Mapping", "valueType": "bytes4", "valueContent": "0x5ef83ad9" } ``` This data key is used to know if the contract contains some metadata to display as a profile. ### `LSP3Profile` This standardised data key exists to store the metadata that represent the profile metadata of any kind of contract (e.g: a Universal Profile, a Vault, etc...). This is useful when one might want to represent a specific contract with some form of "branding" to give a profile-like aspect to the smart contract. For instance, the metadata could represent the following in these scenarios: - a **Universal Profile**: to represent an individual, a brand, a company or a DAO. - a digital **Vault**: to represent a saving account, a safe contains high value NFTs, or a list of items about to be put on auction by an auction house. ```json { "name": "LSP3Profile", "key": "0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5", "keyType": "Singleton", "valueType": "bytes", "valueContent": "VerifiableURI" } ``` The value attached to this data key is a [VerifiableURI-encoded value](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#verifiableuri). It represents a reference to a [JSON file that describes the Profile MetaData](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md#lsp3profile). The file can be stored on a centralized or decentralized storage. Inside the JSON file, the keys `profileImage` and `backgroundImage` can accept an array of images, defining an image with different dimensions, `width` and `height`. Picture scaling is helpful for client interfaces to download and serve the images with the most suitable dimensions instead of re-scale them afterward.
Example of JSON File linked to LSP3Profile data key ```json { "LSP3Profile": { "name": "frozeman", "description": "The inventor of ERC725 and ERC20...", "links": [ { "title": "Twitter", "url": "https://twitter.com/feindura" }, { "title": "lukso.network", "url": "https://lukso.network" } ], "tags": ["brand", "public profile"], "avatar": [ { "hashFunction": "keccak256(bytes)", "hash": "0x98fe032f81c43426fbcfb21c780c879667a08e2a65e8ae38027d4d61cdfe6f55", "url": "ifps://QmPJESHbVkPtSaHntNVY5F6JDLW8v69M2d6khXEYGUMn7N", "fileType": "fbx" } ], "profileImage": [ { "address": 0x1231c7436a77a009a97e48e4e10c92e89fd95fe15, // the address of an LSP7 or LSP8 "tokenId": 0xdde1c7436a77a009a97e48e4e10c92e89fd95fe1556fc5c62ecef57cea51aa37 // (optional) if token contract is an LSP7 } ], "backgroundImage": [ { "width": 1800, "height": 1013, "hashFunction": "keccak256(bytes)", "hash": "0x98fe032f81c43426fbcfb21c780c879667a08e2a65e8ae38027d4d61cdfe6f55", "url": "ifps://QmPJESHbVkPtSaHntNVY5F6JDLW8v69M2d6khXEYGUMn7N" }, { "width": 1024, "height": 576, "hashFunction": "keccak256(bytes)", "hash": "0xfce1c7436a77a009a97e48e4e10c92e89fd95fe1556fc5c62ecef57cea51aa37", "url": "ifps://QmZc9uMJxyUeUpuowJ7AD6MKoNTaWdVNcBj72iisRyM9Su" } ] } } ```
### `LSP12IssuedAssets` **Universal Profiles** can create digital assets, such as [tokens and NFTs](../tokens/introduction.md). All assets (tokens and NFTs) created should be registered in the `LSP12IssuedAssets[]` Array. The `LSP12IssuedAssetsMap:
` can then be used to know the asset type (_e.g., an [LSP7 token](../tokens/LSP7-Digital-Asset.md) or an [LSP8 NFT](../tokens/LSP8-Identifiable-Digital-Asset.md)_) by extracting the `bytes4` ERC165 interface id of the asset contract. Developers can extract this `bytes4` value from the value retrieved, first 4bytes. ```json { "name": "LSP12IssuedAssets[]", "key": "0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd", "keyType": "Array", "valueType": "address", "valueContent": "Address" } ``` ```json { "name": "LSP12IssuedAssetsMap:
", "key": "0x74ac2555c10b9349e78f0000
", "keyType": "Mapping", "valueType": "(bytes4,uint128)", "valueContent": "(Bytes4,Number)" } ``` ### `LSP5ReceivedAssets` :::info See the [LSP5 - Received Assets](./lsp5-received-assets.md) standard page for more information. ::: ```json { "name": "LSP5ReceivedAssets[]", "key": "0x6460ee3c0aac563ccbf76d6e1d07bada78e3a9514e6382b736ed3f478ab7b90b", "keyType": "Array", "valueType": "address", "valueContent": "Address" } ``` If the Universal Profile is used with the **[LSP6-KeyManager](../access-control/lsp6-key-manager.md)** and **[LSP1-UniversalReceiverDelegate](../accounts/lsp1-universal-receiver-delegate.md)**, the received assets will be automatically registered in the storage. To know how many different assets you have, you can query this data key. --- --- sidebar_label: 'LSP5 - Received Assets' sidebar_position: 5 description: 'LUKSO LSP5 - Received Assets: a standard for referencing and keeping track of received assets.' --- # LSP5 - Received Assets :::info Standard Specification [LSP5 - Received Assets](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-5-ReceivedAssets.md) ::: > **Goal:** Keeps track of digital assets LSP5 - Received Assets enables smart contracts including Universal Profiles to automatically track and manage the assets they own and received, such as tokens and NFTs. Traditionally, keeping track of owned assets on the blockchain is cumbersome, requiring manual additions and checks or reliance on external services to scan the entire network. LSP5 simplifies this by providing a standardized way to list all assets associated with a Universal Profile directly in its smart contract storage. This is achieved through specific data keys within the ERC725Y data key-value store, allowing for a dynamic and efficient way to manage and reference assets. By integrating with the LSP1-UniversalReceiverDelegate, this process is automated, ensuring that any new assets received by the Universal Profile are immediately recognized and accessible. This standard not only enhances the usability of Universal Profiles by providing a clear overview of owned assets but also lays the foundation for more complex interactions and functionalities within the LUKSO ecosystem. ## Introduction Keeping track of all the tokens that an address owns is currently unfeasible. If you want to know from which tokens you own, you need to manually import the token contract address and query the balance of your key in it each time for each token. This inconvenience brings light to the following problem: owning tokens without being aware because there are no ways of being notified about the tokens you have received in the first place. Explorers like [Etherscan](https://etherscan.io/) are currently responsible for listing all the tokens each address owns. They do so through their API by scanning the entire network of Ethereum, including the balance on each token contract and potential interacting address. As a result, keeping track of the user's owned assets and balances relies on such centralized services. One way to solve this problem is to create generic metadata keys that would register in the smart contract storage how many different tokens you own and the address of the transferred token contracts. LSP5 removes the problem listed above by storing the addresses of the tokens you own directly inside your UP storage or any contract that implements LSP5. ## What does this standard represent? :::tip Recommendation Make sure to understand the **[ERC725Y Generic Key/Value Store](../erc725.md#erc725y---generic-data-keyvalue-store)** and **[LSP2 - ERC725YJSONSchema](/standards/metadata/lsp2-json-schema.md)** Standards before going through the ERC725Y Data Keys. ::: This Metadata standard describes two data keys that can be added to an [ERC725Y](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y) smart contract to reference and keep track of received assets. ### `LSP5ReceivedAssets[]` This data key represents a list of all tokens and NFTs currently owned by the contract. ```json { "name": "LSP5ReceivedAssets[]", "key": "0x6460ee3c0aac563ccbf76d6e1d07bada78e3a9514e6382b736ed3f478ab7b90b", "keyType": "Array", "valueType": "address", "valueContent": "Address" } ``` :::tip Recommendation It is advised to query the **`LSP5ReceivedAssets[]`** data key to verify if a contract supports the **[LSP5 - ReceivedAsset](./lsp5-received-assets.md)** standard. ::: ### `LSP5ReceivedAssetsMap` This data key represents a map key, both holding: - an [ERC165 interface ID](https://eips.ethereum.org/EIPS/eip-165) to quickly identify the standard used by each asset smart contract (without the need to query the asset contracts directly). - the index in the [`LSP5ReceivedAssets[]`](#lsp5receivedassets-) Array where the received asset addresses are stored. The `LSP5ReceivedAssetsMap` data key also helps to prevent adding duplications to the array when automatically added via smart contract (_e.g., _ an [LSP1-UniversalReceiverDelegate](/standards/accounts/lsp1-universal-receiver-delegate.md)). ```json { "name": "LSP5ReceivedAssetsMap:
", "key": "0x812c4334633eb816c80d0000
", "keyType": "Mapping", "valueType": "(bytes4,uint128)", "valueContent": "(Bytes4,Number)" } ``` ### Flow :::info Note The data keys are also set on the **sender Universal Profile** to remove the token contract address if all the balance is sent. ::: If set when transferring tokens, these data keys are automatically updated in the Universal Profile storage via the [LSP1UniversalReceiverDelegateUP](/contracts/contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP.md) contract. :::note Check the [token transfer scenario](/standards/accounts/lsp1-universal-receiver-delegate#token-transfer-scenario) for more details. ::: --- --- title: 'Types of LSPs Standards' description: 'Discover the different type of LUKSO Standards Proposals: smart contracts interfaces and standardised metadata keys.' --- # Types of LSPs Standards :::tip See the **[LSP Detection Guide](../learn/standard-detection.md)** to lean how to check standardized metadata and ERC165 interface IDs. ::: There are two types of **LSP** standards used to interact with smart contracts on the LUKSO blockchain. | Standard Type | Description | Examples | | :---------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Interface Standards** | **Standardize a set of functions**.
Defines the functions that can be called on a smart contract and their expected parameters | [LSP0-ERC725Account](./accounts/lsp0-erc725account.md)
[LSP6-KeyManager](./access-control/lsp6-key-manager.md)
[LSP7-DigitalAsset](./tokens/LSP7-Digital-Asset.md) | | **Metadata Standards** | **Standardize a set of ERC725Y data keys**.
Informs about the data set by default on the contract and which data keys to query to retrieve such data | [LSP3-Profile-Metadata](./metadata/lsp3-profile-metadata.md)
[LSP4-DigitalAsset-Metadata](./tokens/LSP4-Digital-Asset-Metadata.md)
[LSP10ReceivedVaults](./metadata/lsp10-received-vaults.md) | --- --- sidebar_label: 'LSP4 - Digital Asset Metadata' sidebar_position: 2 description: LUKSO LSP4 - Digital Asset Metadata for defining data keys to describe a Digital Asset. --- # LSP4 - Digital Asset Metadata :::info Standard Specification [LSP4 - Digital Asset Metadata](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md) ::: ## Introduction The existing tokens and NFTs standards offer limited functionalities to attach information to the contracts themselves. As an example, the ERC20 and ERC721 standards only define a **`name()`**, **`symbol()`**, and **`tokenURI()`** functions. This makes it difficult to add information more specific to the asset (e.g., an icon, the asset creator(s) , the utility or motive of the token, the community behind it, etc...). Such information is crucial to make each token or NFT descriptive and customised. **LSP4-DigitalAsset-Metadata** solves this problem by defining a set of data keys to describe a **Digital Asset** using [ERC725Y](https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#erc725y) as a backbone. ERC725Y enables smart contracts to have very flexible and extensible storage. With ERC725Y, any information or metadata can be attached to the token or NFT. ## Types of Digital Assets By mixing contract standards (LSP7/8), token types (Token, NFT, Collection) and metadata, you can create a wide array of Digital Assets. ### With LSP7 Digital Asset (Token)
Contract type LSP4TokenType Decimals LSP4Metadata Description
LSP7 0 (Token) \>=0 Represents the token information. A generic token, where the LSP4Metadata represents the token information.
LSP7 1 (NFT) 0 Represents the information of a single NFT, that has multiple ownable amounts or IDs. A single type of NFT with custom metadata and which has multiple ownable amounts or IDs.
LSP7 2 (Collection) - - Not compatible
### With LSP8 Identifiable Digital Asset (NFT)
Contract type LSP4TokenType LSP4Metadata for Contract LSP8TokenIdFormat LSP4Metadata for each TokenId Description
LSP8 0 (Token) - - - Not compatible
LSP8 1 (NFT) Represents the information of a single NFT, that has multiple ownable amounts or IDs. COULD be set for each individual token ID. COULD be set for each individual token ID. Each individual token ID COULD have its own custom metadata specific for the token ID, but MUST NOT be a different NFT, just different metadata per item in the NFT. See LSP8 for details.
LSP8 2 (Collection) Represents the information of the collection. MUST be set for each individual token ID. MUST be set for each individual token ID. Each individual token ID represents its own NFT, LSP4Metadata and LSP8TokenIdFormat must be set for each of them in case the individual token IDs are LSP8. See LSP8 for details.
## ERC725Y Data Keys :::tip Recommendation Make sure to understand the **[ERC725Y Generic Key/Value Store](../erc725.md#erc725y---generic-data-keyvalue-store)** and **[LSP2 - ERC725YJSONSchema](../metadata/lsp2-json-schema.md)** Standards before going through the ERC725Y Data Keys. ::: ### `SupportedStandards:LSP4DigitalAsset` ```json { "name": "SupportedStandards:LSP4DigitalAsset", "key": "0xeafec4d89fa9619884b60000a4d96624a38f7ac2d8d9a604ecf07c12c77e480c", "keyType": "Mapping", "valueType": "bytes4", "valueContent": "0xa4d96624" } ``` This key is used to know if the contract represents a **Digital Asset**. ### `LSP4TokenName` ```json { "name": "LSP4TokenName", "key": "0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1", "keyType": "Singleton", "valueType": "string", "valueContent": "String" } ``` The value attached to this data key represents the name of the digital asset. ### `LSP4TokenSymbol` ```json { "name": "LSP4TokenSymbol", "key": "0x2f0a68ab07768e01943a599e73362a0e17a63a72e94dd2e384d2c1d4db932756", "keyType": "Singleton", "valueType": "string", "valueContent": "String" } ``` The value attached to this data key represents the symbol of the digital asset. ### `LSP4TokenType` :::note References LSP4 defines 3 default token types (see [table above](./LSP4-Digital-Asset-Metadata.md#types-of-digital-assets)). However, these are not restrictive. Applications and protocols can define new custom token types starting from `3`. ::: ```json { "name": "LSP4TokenType", "key": "0xe0261fa95db2eb3b5439bd033cda66d56b96f92f243a8228fd87550ed7bdfdb3", "keyType": "Singleton", "valueType": "uint256", "valueContent": "Number" } ``` The value attached to this data key represents the type of token of the digital asset. The defaults values are: - 0 (Token) - 1 (NFT) - 2 (Collection) :::tip 👉 Please refer to the [Types of Digital Assets table](./LSP4-Digital-Asset-Metadata.md#types-of-digital-assets) to see how you can use it to create your assets. ::: ### `LSP4Metadata` ```json { "name": "LSP4Metadata", "key": "0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e", "keyType": "Singleton", "valueType": "bytes", "valueContent": "VerifiableURI" } ``` The value attached to this data key is a [`VerifiableURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#verifiableuri). It represents a reference to a [JSON file describing the **Digital Asset**](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md#lsp4metadata). The file can be stored on centralized or decentralized storage. ### `LSP4Creators` This data key refers to the **address(es)** of the **creator(s)** of the digital asset. It can help to check the **asset authenticity** when combined with **[LSP12-IssuedAssets](../metadata/lsp12-issued-assets.md)**. ```json { "name": "LSP4Creators[]", "key": "0x114bd03b3a46d48759680d81ebb2b414fda7d030a7105a851867accf1c2352e7", "keyType": "Array", "valueType": "address", "valueContent": "Address" } ``` ```json { "name": "LSP4CreatorsMap:
", "key": "0x6de85eaf5d982b4e5da00000
", "keyType": "Mapping", "valueType": "(bytes4,uint128)", "valueContent": "(Bytes4,Number)" } ``` --- --- sidebar_label: 'LSP7 - Digital Asset (Token)' sidebar_position: 3 description: LUKSO LSP7 - Digital Asset for fungible assets. --- # LSP7 - Digital Asset :::info Standard Specification [LSP7 - Digital Asset](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md) ::: ## Introduction Fungible assets such as **[ERC20](https://eips.ethereum.org/EIPS/eip-20)**, **[ERC223](https://eips.ethereum.org/EIPS/eip-223)** or **[ERC777](https://eips.ethereum.org/EIPS/eip-777)** tokens have a lot of limitations in terms of metadata, secure transfers, and asset interaction. This causes problems for users seeking, **full control** over which assets they accept or not, and a **simple user experience** while creating, buying, and exchanging assets. **[LSP7-DigitalAsset](../../standards/tokens/LSP7-Digital-Asset.md)** is the standard that aims to solve all problems mentioned above by: - Allowing more secure transfers via **force boolean parameter**. - More asset metadata **via [LSP4-DigitalAssetMetadata](./LSP4-Digital-Asset-Metadata.md)**. - More interaction between the asset contract and the asset _sender/recipient_ **via token hooks**. ## Specification **[LSP7-DigitalAsset](../../standards/tokens/LSP7-Digital-Asset.md)** is a standard that aims to describe fungible assets. The term _fungible_ means that these assets are **mutually interchangeable** (*e.g., *one token has the same value as another token). LSP7-DigitalAsset is an interface standard which describes a set of methods that fungible asset contracts should implement which other contracts and clients can call. This standard was based on the ideas of **[ERC20](https://eips.ethereum.org/EIPS/eip-20)** and **[ERC777](https://eips.ethereum.org/EIPS/eip-777)**. While it does not integrate all the functionality from [ERC777](https://eips.ethereum.org/EIPS/eip-777), LSP7 comes with the additional features mentioned below: ### Divisible _vs_ Non-Divisible When creating assets compliant with **LSP7-DigitalAsset** standard, it is possible to define the token as **divisible** or **non-divisible** in the constructor. - **Divisible** asset can have decimals (up to 18) and token amounts can be fractional. For instance, it is possible to mint or transfer less than one token (_e.g., 0.3 tokens_). - **Non-divisible** asset means that a token cannot be divided into fractional parts. For instance, you cannot transfer **1/10th** of a token, or 0.3 tokens, but only a whole token unit. **Tickets created as tokens** are a great example of a use case of **LSP7-DigitalAsset**. All tickets look the same, are **interchangeable** and have the same utility. Moreover, such tickets can be made as **non-divisible** as it is only possible to sell or give away a whole ticket. ### Unlimited Metadata :::tip Recommendation To mark the **asset authenticity**, it's advised to use a combination between **[LSP4-DigitalAssetMetadata](./LSP4-Digital-Asset-Metadata.md)** and **[LSP12-IssuedAssets](../metadata/lsp12-issued-assets.md)**. ::: The current token standards don't enable attaching metadata to the contract in a generic and flexible way, they set the **name**, **symbol**, and **tokenURI**. This is limiting for a digital asset that may want to list the creators, the community behind it, and to have the ability to update the metadata of the token and the tokenIds over time depending on a certain logic (Evolving tokens). To ensure a flexible and generic asset representation, the token contract should use the **[LSP4-DigitalAsset-Metadata](./LSP4-Digital-Asset-Metadata.md)**. In this way, any information could be attached to the token contract. ### LSP1 Token Hooks :::caution When LSP7 assets are transferred, the LSP7 contract will notify the token sender and recipient using [`_notifyTokenSender(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_notifytokensender) and [`_notifyTokenReceiver(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_notifytokenreceiver). **These methods will make external calls** to the [`universalReceiver(...)`](../../contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver) functions of both the sender and recipient. This function could perform more complex logic, like delegating the call to the `LSP1UniversalReceiverDelegate` contract. This contract can contain custom logic for each user. For instance, a user could decide to re-transfer the tokens to another address once they are transferred to his UP. ::: The current token standards act as **registry contracts** that keep track of each address's balance. They do not implement functionalities to **notify the recipient** that it has received some tokens or to **notify the sender** that it has sent some tokens. During an **ERC20 token transfer**, the sender's balance is decreased, and the recipient's balance is increased without further interaction. During an **LSP7 token transfer**, as well as updating the balances, both the sender and recipient are informed of the transfer by calling their **[`universalReceiver(...)`](../accounts/lsp1-universal-receiver.md#lsp1---universal-receiver)** function (if these are both smart contracts). In this way, users are **informed** about the token transfers and approval and can decide how to **react on the transfer or approval**, either by accepting or rejecting the tokens, or implementing a custom logic to run on each transfer with the help of **[LSP1-UniversalReceiverDelegate](../accounts/lsp1-universal-receiver-delegate.md)**. If the sender and recipient are smart contracts that implement the LSP1 standard, the LSP7 token contract will notify them using the following `bytes32 typeIds` when calling their `universalReceiver(...)` function. | address notified | `bytes32` typeId used | description | | --------------------------- | -------------------------------------------------------------------- | ----------------------------------------------- | | Token sender (`from`) | `0x429ac7a06903dbc9c13dfcb3c9d11df8194581fa047c96d7a4171fc7402958ea` | `keccak256('LSP7Tokens_SenderNotification')` | | Token recipient (`to`) | `0x20804611b3e2ea21c480dc465142210acf4a2485947541770ec1fb87dee4a55c` | `keccak256('LSP7Tokens_RecipientNotification')` | | Token Operator (`operator`) | `0x386072cc5a58e61263b434c722725f21031cd06e7c552cfaa06db5de8a320dbc` | `keccak256('LSP7Tokens_OperatorNotification')` | ### `force` mint and transfer :::success It is advised to set the `force` boolean to `false` when transferring or minting tokens to avoid sending them to the wrong address. For instance, if the wrong address was pasted by mistake by the user in the input field of a dApp. ::: It is expected in the LUKSO's ecosystem to use **[smart contract-based accounts](../accounts/lsp0-erc725account.md)** to interact on the blockchain. This includes sending and receiving tokens. EOAs can receive tokens, but should be used mainly to control these accounts, not to interact on the network or hold tokens. To ensure a **safe asset transfer**, an additional boolean parameter was added to the [`transfer(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#transfer) and [`_mint(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_mint) functions: - If set to `false`, the transfer will only pass if the recipient is a smart contract that implements the **[LSP1-UniversalReceiver](../accounts/lsp1-universal-receiver.md)** standard. - If set to `true`, the transfer will not be dependent on the recipient, meaning **smart contracts** not implementing the **[LSP1-UniversalReceiver](../accounts/lsp1-universal-receiver.md)** standard and **EOAs** will be able to receive the tokens. Implementing the **[LSP1-UniversalReceiver](../accounts/lsp1-universal-receiver.md)** standard will give a sign that the contract knows how to handle the tokens received. --- --- sidebar_label: 'LSP8 - Identifiable Digital Asset (NFT)' sidebar_position: 4 description: LUKSO LSP8 - Identifiable Digital Asset for non-fungible assets. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # LSP8 - Identifiable Digital Asset :::info Standard Specification [LSP8 - Identifiable Digital Asset](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md) ::: ## Introduction Non-Fungible assets such as **[ERC721](https://eips.ethereum.org/EIPS/eip-721)** and **[ERC1155](https://eips.ethereum.org/EIPS/eip-1155)** tokens have a lot of limitations in terms of metadata, secure transfers, asset representation, and asset interaction. This causes problems for users seeking, **full control** over which assets they accept or not, **more complex NFT functionality**, and a **simple user experience** while creating, buying, and exchanging assets. **[LSP8-IdentifiableDigitalAsset](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md)** is the standard that aims to solve all problems mentioned above by: - Allowing more secure transfers via **force boolean parameter**. - More asset metadata **via [LSP4-DigitalAssetMetadata](./LSP4-Digital-Asset-Metadata.md)**. - More asset representation **via bytes32 tokenIds**. - More interaction between the asset contract and the asset _sender/recipient_ **via token hooks**. ### Specification **[LSP8-IdentifiableDigitalAsset](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md)** is a standard that aims to describe _non-fungible_ assets. The term _Non-fungible_ means that each asset is **unique and different**. They are distinguishable from each other and therefore **not interchangeable**. This standard was based on **[ERC721](https://eips.ethereum.org/EIPS/eip-20)** and **[ERC1155](https://eips.ethereum.org/EIPS/eip-777)** with additional features mentioned below: ### Format of TokenIds The current NFT standards such as **[ERC721](https://eips.ethereum.org/EIPS/eip-721)** and **[ERC1155](https://eips.ethereum.org/EIPS/eip-1155)** **lack asset representation** as they define the tokenIds **as Numbers** `(uint256)`. Each token from the NFT collection will be defined and queried based on this tokenId, which is normally incremental. **[LSP8-IdentifiableDigitalAsset](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md)** defines the tokenIds as `bytes32` to allow a wide variety of representation, including numbers, string names, smart contract addresses, byte identifiers for serial numbers, or even hashed values. Finally a LSP8 Collection contract can also contains NFTs of different formats, illustrated under the **Mixed Formats tab** below. For instance all the NFTs by default are of the `number` format, but certain NFTs in the collection could be more complex and represented as their own smart contract. In this example use case, the tokenId format will be **`Mixed` with default as `address`** (Value `102`). | Value | Format | Representation | Description | | :---: | :-------: | :------------: | :----------------------------------------------------------------------------------------------------------------------------- | | `0` | `uint256` | Number | each NFT is parsed as a **unique number**. | | `1` | `string` | String | each NFT is parsed as a **unique name** (as a short **utf8 encoded string**, no more than 32 characters long) | | `2` | `address` | Smart Contract | each NFT is parsed as its **own smart contract** that can hold its own logic and metadata (_e.g [ERC725Y] compatible_). | | `3` | `bytes32` | Unique Bytes | each NFT is parsed as a 32 bytes long **unique identifier**. | | `4` | `bytes32` | Hash Digest | each NFT is parsed as a 32 bytes **hash digest**. This can be used as the hash of a very long string representing the tokenId. | | Value | Format | Description | | :---: | :--------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `100` | `Mixed` with default as `uint256` | Default NFT is parsed as a **unique number** with querying the `LSP8TokenIdFormat` for each `tokenId`. | | `101` | `Mixed` with default as `string` | Default NFT is parsed as a **unique name** (as a short **utf8 encoded string**, no more than 32 characters long) with querying the `LSP8TokenIdFormat` for each `tokenId`. | | `102` | `Mixed` with default as `address` | Default NFT is parsed as its **own smart contract** that can hold its own logic and metadata (_e.g [ERC725Y] compatible_) with querying the `LSP8TokenIdFormat` for each `tokenId`. . | | `103` | `Mixed` with default as `bytes32` unique bytes | Default NFT is parsed as a 32 bytes long **unique identifier** with querying the `LSP8TokenIdFormat` for each `tokenId`. | | `104` | `Mixed` with default as `bytes32` hash digest | Default NFT is parsed as a 32 bytes **hash digest**with querying the `LSP8TokenIdFormat` for each `tokenId`. | The **bytes32 tokenId** can be interpreted as a: - Number: - Hashed Value: - Contract Address: TokenIds represented as **smart contract address** allow the creation of more **complex NFTs**. When each tokenId is a contract that have its own **[ERC725Y](../erc725.md#erc725y---generic-data-keyvalue-store)** storage. For instance in a video game, by changing the features and metadata of the tokenId based on the **game rules**. ### Unlimited Metadata :::tip Recommendation To mark the **asset authenticity**, it's advised to use a combination between **[LSP4-DigitalAssetMetadata](./LSP4-Digital-Asset-Metadata.md)** and **[LSP12-IssuedAssets](../metadata/lsp12-issued-assets.md)**. ::: The current token standards don't enable attaching metadata to the contract in a generic and flexible way, they set the **name**, **symbol**, and **tokenURI**. This is limiting for a digital asset that may want to list the creators, the community behind it, and to have the ability to update the metadata of the token and the tokenIds over time depending on a certain logic (Evolving tokens). To ensure a flexible and generic asset representation, the token contract should use the **[LSP4-DigitalAsset-Metadata](./LSP4-Digital-Asset-Metadata.md)**. In this way, any information could be attached to the token contract. :::note Notice The Metadata defined by the **ERC725Y Data Keys** can be set for **each tokenId**, not just for the whole NFT collection. Check **[LSP8 ERC725Y Data Keys](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#erc725y-data-keys)** in the LSP8 Standard Document. ::: ### LSP1 Token Hooks :::caution When LSP8 assets are transferred, the LSP8 contract will notify the token sender and recipient using [`_notifyTokenSender(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#_notifytokensender) and [`_notifyTokenReceiver(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#_notifytokenreceiver). **These methods will make external calls** to the [`universalReceiver(...)`](../../contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.md#universalreceiver) functions of both the sender and recipient. This function could perform more complex logic, like delegating the call to the `LSP1UniversalReceiverDelegate` contract. This contract can contain custom logic for each user. For instance, a user could decide to re-transfer the tokens to another address once they are transferred to his UP. ::: The current NFTs standards act as **registry contracts** that keep track of the ownership of each tokenId. They do not implement functionalities to **notify the recipient** that it has received some tokens or to **notify the sender** that it has sent some tokens. During an **ERC721 token transfer**, the ownership of the tokenId is changed from the sender address to the recipient address without further interaction. During an **LSP8 token transfer**, as well as updating the tokenId ownership, both the sender and recipient are informed of the transfer by calling the **[`universalReceiever(...)`](../accounts/lsp1-universal-receiver.md#lsp1---universal-receiver)** function on their profiles. In this way, users are **informed** about the NFT transfer and can decide how to **react on the transfer**, either by accepting or rejecting the NFT, or implementing a custom logic to run on each transfer with the help of **[LSP1-UniversalReceiverDelegate](../accounts/lsp1-universal-receiver-delegate.md)**. If the sender and recipient are smart contracts that implement the LSP1 standard, the LSP8 token contract will notify them using the following `bytes32 typeIds` when calling their `universalReceiver(...)` function. | address notified | `bytes32` typeId used | description | | --------------------------- | -------------------------------------------------------------------- | ----------------------------------------------- | | Token sender (`from`) | `0xb23eae7e6d1564b295b4c3e3be402d9a2f0776c57bdf365903496f6fa481ab00` | `keccak256('LSP8Tokens_SenderNotification')` | | Token recipient (`to`) | `0x0b084a55ebf70fd3c06fd755269dac2212c4d3f0f4d09079780bfa50c1b2984d` | `keccak256('LSP8Tokens_RecipientNotification')` | | Token Operator (`operator`) | `0x468cd1581d7bc001c3b685513d2b929b55437be34700410383d58f3aa1ea0abc` | `keccak256('LSP8Tokens_OperatorNotification')` | ### `force` mint and transfer :::success Recommendation When transferring or minting tokens, it is advised to set the `force` boolean to `false` by default to ensure tokens won't be lost if sent accidentally to the wrong EOA or contract address. For instance, if the wrong address was pasted by mistake by the user in the input field of a dApp. ::: It is expected in the LUKSO's ecosystem to use **smart contract based accounts** to interact on the blockchain. This includes sending and receiving tokens. EOAs can receive tokens, but should be used mainly to control these accounts, not to interact on the network or hold tokens. To ensure a **safe asset transfer**, an additional boolean parameter was added to the [`transfer(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#transfer) and [`_mint(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#_mint) functions: - If set to `false`, the transfer will only pass if the recipient is a smart contract that implements the **[LSP1-UniversalReceiver](../accounts/lsp1-universal-receiver.md)** standard. - If set to `true`, the transfer will not be dependent on the recipient, meaning **smart contracts** not implementing the **[LSP1-UniversalReceiver](../accounts/lsp1-universal-receiver.md)** standard and **EOAs** will be able to receive the tokens. Implementing the **[LSP1-UniversalReceiver](../accounts/lsp1-universal-receiver.md)** standard will give a sign that the contract knows how to handle the tokens received. ## LSP8 Collection vs TokenId Metadata The LSP8 standard offers ways to set metadata for the whole LSP8 collection as well as metadata per specific token Id. This is done using the same `LSP4Metadata` data key, but different functions. - The generic metadata and information related to the whole LSP8 collection can be updated using [`setData(bytes32,bytes)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdata) or [`setDataBatch(bytes[],bytes[])`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatabatch), passing the `bytes32` data key of [`LSP4Metadata`](./LSP4-Digital-Asset-Metadata.md#lsp4metadata) as the first argument. - Alternatively, the generic information and metadata specific to a `tokenId` can be set using the [`setDataForTokenId`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatafortokenid) or [`setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatabatchfortokenids) functions. --- --- sidebar_label: 'Introduction' sidebar_position: 1 description: 'Introduction to LUKSO Tokens (LSP7-DigitalAsset ) and NFTs 2.0 (LSP8-IdentifiableDigitalAsset).' --- # Tokens & NFT 2.0 :::success Useful Tip The [guide section](../../learn/digital-assets/token/create-lsp7-token.md) will walk you through creating and deploying an LSP7 token or an LSP8 NFT on the [LUKSO Testnet](../../networks/testnet/parameters.md). Check the [profile explorer](https://universalprofile.cloud/) to browse the deployed digital assets. ::: ## Introduction The current standards representing fungible and non-fungible tokens (NFTs) are limiting the NFTs and token industry as they lack standardization and many powering features. The lack of standardization can be seen through each NFT or token standard implementing its own interface with its own function names. This leads to having multiple token contracts deployed on networks, implementing different interfaces, and being non-interoperable between each other. As for features, these standards are just representing **incremental tokenIds** without proper metadata, asset representation, standard interaction between sender and receivers, and no security measurements to ensure safe asset transfers. **Tokens & NFT 2.0** is a collective name for the new token and NFT standards **[LSP7-DigitalAsset](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-7-DigitalAsset.md)** and **[LSP8-IdentifiableDigitalAsset](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md)**. These replace ERC20 and ERC721, which you would usually use on other networks. ## Tokens & NFT 2.0 | Standard | Description | | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **[ LSP4 - DigitalAssetMetadata ](./LSP4-Digital-Asset-Metadata.md)** | The standard used by both **LSP7** & **LSP8** to provide proper **metadata** to the asset with standard ERC725Y Data Keys. | | **[LSP7 - DigitalAsset](./LSP7-Digital-Asset.md)** | Similar to ERC20 Standard, LSP7 represents **fungible tokens** standard with proper metadata, more secure transfers and more interactive transfer. | | **[LSP8 - IdentifiableDigitalAsset](./LSP8-Identifiable-Digital-Asset.md)** | Similar to ERC721 and ERC1155 Standard, LSP8 represents **non-fungible tokens (NFTs)** standard with proper metadata, more secure transfers, more asset representation and more interactive transfer. | The functions of the LSP7 and LSP8 standards are overall simpler, more straightforward and unified, with a **similar function names** for both LSP7 and LSP8.yarn Both functions in LSP7 and LSP8 have the same name (`transfer`) to transfer assets. This is easier compared to ERC20 and ERC721 that use different naming (`transfer` for ERC20 vs `transferFrom` in ERC721 to transfer tokens as the token owner). Looking at LSP7 & LSP8 we have unified `transfer(...)` & `transferBatch(...)` functions in both contracts. Those functions contain a hook which is executed conditionally and can be used in any of the above cases. ## References - [NFT NYC - Building Blocks for the New Creative Economy (Fabian Vogelsteller, Youtube)](https://www.youtube.com/watch?v=skA4Y-vvt5s) --- --- title: 🔍 Indexer API sidebar_position: 2 --- # Indexer API import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import MainnetIcon from '@site/static/img/icons/lukso-signet-fuschia.svg'; import TestnetIcon from '@site/static/img/icons/lukso-signet-yellow.svg'; import QueryExamples from '@site/src/components/QueryExamples'; The [**Envio Indexer**](https://envio.lukso-mainnet.universal.tech/) provides a powerful way to query any information, past events or metadata from the LUKSO blockchain. It offers flexible querying capabilities with support for filtering and real-time subscriptions. ## Get Started This guide covers how to query the LUKSO Indexer using GraphQL, with practical examples and code samples. Choose the client that best fits your use case: - **[HTTP client](#http-client)**: Best for one-time queries, searches, and fetching data on demand - **[WebSocket client](#websocket-client)**: Best for real-time updates, monitoring changes, and live data feeds :::success Interactive Playground Explore the full schema and test queries in the interactive playground: **[https://envio.lukso-mainnet.universal.tech/](https://envio.lukso-mainnet.universal.tech/)** ::: **GraphQL Endpoint:** Mainnet} default> ``` https://envio.lukso-mainnet.universal.tech/v1/graphql ``` Testnet}> ``` https://envio.lukso-testnet.universal.tech/v1/graphql ``` ## HTTP Client Install the `graphql-request` library to interact with the indexer: :::info graphql-request Any GraphQL client library will work for querying the LUKSO Indexer. ::: ```bash npm install graphql-request graphql ``` Once installed, you can start making queries: ```typescript import { request, gql } from 'graphql-request'; const GRAPHQL_ENDPOINT = 'https://envio.lukso-mainnet.universal.tech/v1/graphql'; // Example query to retrieve the Universal Profile's name and its images const query = gql` query { Profile(limit: 5) { id name fullName } } `; const data = await request(GRAPHQL_ENDPOINT, query); console.log(data); ``` ### Query Examples Below are the most common use cases for querying the LUKSO Indexer: ## WebSocket Client For real-time data subscriptions, use the WebSocket protocol with the `graphql-ws` library: ```bash npm install graphql-ws ``` Once installed, you can subscribe to live updates: ```typescript import { createClient } from 'graphql-ws'; const wsClient = createClient({ url: 'wss://envio.lukso-mainnet.universal.tech/v1/graphql', }); // Subscribe to profile updates for a specific Universal Profile address const subscription = wsClient.subscribe( { query: ` subscription OnProfileUpdate($profileId: String!) { Profile(where: { id: { _eq: $profileId } }) { id name fullName profileImages(where: { error: { _is_null: true } }) { src url } } } `, variables: { profileId: '0x...' }, }, { next: (data) => { console.log('Profile updated:', data); }, error: (error) => { console.error('Subscription error:', error); }, complete: () => { console.log('Subscription complete'); }, }, ); // Unsubscribe when done subscription(); ``` ## Resources - [LUKSO Indexer Playground](https://envio.lukso-mainnet.universal.tech/) - [LSP4 - Digital Asset Metadata](/standards/tokens/LSP4-Digital-Asset-Metadata/) - [LSP3 - Profile Metadata](/standards/metadata/lsp3-profile-metadata/) --- --- title: ⛽ Transaction Relay API sidebar_position: 3 --- # Transaction Relay API The LUKSO Transaction Relay Service enables gasless transactions for Universal Profiles. Registered Universal Profiles receive a **free monthly gas quota of 20 million gas**. Looking to deploy or register Universal Profiles? See the [Relayer User API](./relayer-user-api.md). ## API Endpoints No API key required — uses LSP25 signatures for authorization. | | Mainnet | Testnet | | ----------------------- | --------------------------------------- | --------------------------------------- | | **Base URL** | `https://relayer.mainnet.lukso.network` | `https://relayer.testnet.lukso.network` | | **Execute Transaction** | `POST /api/execute` | `POST /api/execute` | | **Check Quota** | `POST /api/quota` | `POST /api/quota` | ## Execute Transactions (Gasless) Execute transactions through the relay service using [LSP25 relay calls](../../standards/access-control/lsp6-key-manager.md). The relayer pays for gas; the controller signs authorization via LSP25. ### How It Works 1. **Encode the payload** — what you want the UP to do (e.g., `execute()`, `setData()`, `setDataBatch()`) 2. **Get the nonce** from the Key Manager 3. **Sign the message** using LSP25 format (EIP-191 v0) 4. **Send to the relay service's** `/api/execute` endpoint ### Request Body ```json { "address": "0x", "transaction": { "abi": "0x", "signature": "0x", "nonce": 0, "validityTimestamps": "0x0" } } ``` ### LSP25 Signature Format ``` hash = keccak256(0x19 || 0x00 || keyManagerAddress || encodedMessage) encodedMessage = abi.encodePacked( LSP25_VERSION, // 25 chainId, // 42 for mainnet, 4201 for testnet nonce, validityTimestamps, msgValue, // 0 for non-payable calls payload ) ``` :::warning EIP-191 Version 0 Sign with `SigningKey.sign(hash)` — **NOT** `wallet.signMessage()`. This is EIP-191 version 0 (`0x00`), not version 0x45 (Ethereum Signed Message). ::: ### Example (ethers.js v6) ```javascript import { ethers } from 'ethers'; const provider = new ethers.JsonRpcProvider('https://42.rpc.thirdweb.com'); const controllerPrivateKey = '0x...'; const controllerAddress = '0x...'; // Address derived from controllerPrivateKey const upAddress = '0x...'; // 1. Get Key Manager address const up = new ethers.Contract( upAddress, ['function owner() view returns (address)'], provider, ); const keyManagerAddress = await up.owner(); // 2. Encode the payload (example: setData) const dataKey = '0x...'; // Your data key const dataValue = '0x...'; // Your data value const iface = new ethers.Interface(['function setData(bytes32,bytes)']); const payload = iface.encodeFunctionData('setData', [dataKey, dataValue]); // 3. Get nonce from Key Manager const km = new ethers.Contract( keyManagerAddress, ['function getNonce(address,uint128) view returns (uint256)'], provider, ); const nonce = await km.getNonce(controllerAddress, 0); // 4. Build LSP25 message and sign (EIP-191 v0) const chainId = 42; // 4201 for testnet const encodedMessage = ethers.solidityPacked( ['uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'bytes'], [25, chainId, nonce, 0, 0, payload], // LSP25_VERSION=25, validityTimestamps=0, msgValue=0 ); const hash = ethers.keccak256( ethers.concat(['0x19', '0x00', keyManagerAddress, encodedMessage]), ); const signingKey = new ethers.SigningKey(controllerPrivateKey); const sig = signingKey.sign(hash); const signature = ethers.Signature.from(sig).serialized; // 5. Send to relay service (no API key needed) const response = await fetch( 'https://relayer.mainnet.lukso.network/api/execute', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ address: upAddress, transaction: { abi: payload, signature, nonce: Number(nonce), validityTimestamps: '0x0', }, }), }, ); const result = await response.json(); console.log('TX Hash:', result.transactionHash); ``` ### Required Permissions The controller signing the relay call must have the **`EXECUTE_RELAY_CALL`** permission (`0x0000000000000000000000000000000000000000000000000000000000400000`). ### Validity Timestamps - `0x0` — No time restriction (valid immediately, no expiry) - Custom: `(startTime << 128) | endTime` — Restrict when the signature is valid ## Check Quota Check remaining gas quota for a registered UP using the relay service. Requires a signed timestamp for authentication (no API key). ```javascript const timestamp = Math.floor(Date.now() / 1000); const message = `${upAddress}:${timestamp}`; const signature = await wallet.signMessage(message); const response = await fetch( 'https://relayer.mainnet.lukso.network/api/quota', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ address: upAddress, timestamp, signature, }), }, ); const quota = await response.json(); console.log('Remaining quota:', quota); ``` ## Support - **Email**: [support@lukso.network](mailto:support@lukso.network) - **Discord**: [discord.com/invite/lukso](https://discord.com/invite/lukso) - **Documentation**: [docs.lukso.tech](https://docs.lukso.tech/) --- --- title: 🆙 Relayer User API sidebar_position: 4 --- # Relayer User API :::info 🔓 Private Beta access This feature is currently in private beta. If you are interested, please [contact us](https://forms.gle/rhWA25m3jjuPNPva9). ::: The LUKSO Relayer User API enables deploying and registering Universal Profiles. Register your Universal Profiles to receive a **free monthly gas quota of 20 million gas** for gasless transactions. Looking to execute gasless transactions? See the [Transaction Relay API](./relayer-api.md). ## API Endpoints Requires an API key (`Authorization: Bearer `). | | Mainnet | Testnet | | --------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | | **Base URL** | `https://relayer-api.mainnet.lukso.network` | `https://relayer-api.testnet.lukso.network` | | **Deploy UP** | `POST /api/universal-profile` | `POST /api/universal-profile` | | **Register UP** | `POST /api/universal-profile/register` | `POST /api/universal-profile/register` | | **API Docs** | [Mainnet](https://relayer-api.mainnet.lukso.network/docs#/) | [Testnet](https://relayer-api.testnet.lukso.network/docs#/) | ## Integration Guide 1. **Request access** — Fill out the [access request form](https://forms.gle/rhWA25m3jjuPNPva9) to get an API key 2. **Deploy or register UPs** — Use the endpoints below with your API key 3. **Execute gasless transactions** — Use the [Transaction Relay API](./relayer-api.md) with LSP25 signatures 4. **Handle errors** — Implement handling for 400, 401, 403, 404, 429, 500 status codes ## Deploy Universal Profiles Deploy Universal Profiles using the Relayer API. Requires an API key. ### Option 1: Controller Address + LSP3 Profile Provide controller addresses and LSP3 metadata directly. ```mermaid sequenceDiagram participant App participant Relayer participant LUKSO Network App->>Relayer: POST /api/universal-profile Note over App,Relayer: lsp6ControllerAddress[]
lsp3Profile metadata Relayer->>LUKSO Network: Deploy UP + Set Controllers + Set Metadata LUKSO Network-->>Relayer: Success Relayer-->>App: Return UP Address ``` ```javascript import { ERC725 } from '@erc725/erc725.js'; import LSP3ProfileMetadataSchemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; // Encode the LSP3Profile metadata const erc725 = new ERC725(LSP3ProfileMetadataSchemas); const encodedLSP3Profile = erc725.encodeData([ { keyName: 'LSP3Profile', value: { verification: { method: 'keccak256(utf8)', data: '0x6d6d08aafb0ee059e3e4b6b3528a5be37308a5d4f4d19657d26dd8a5ae799de0', }, url: 'ipfs://QmPRoJsaYcNqQiUrQxE7ajTRaXwHyAU29tHqYNctBmK64w', }, }, ]); const response = await fetch( 'https://relayer-api.mainnet.lukso.network/api/universal-profile', { method: 'POST', headers: { Authorization: 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ lsp6ControllerAddress: ['0x9d9b6B38049263d3bCE80fcA3314d9CbF00C9E9D'], lsp3Profile: encodedLSP3Profile.values[0], // Encoded VerifiableURI }), }, ); const result = await response.json(); console.log('UP Address:', result.universalProfileAddress); ``` ### Option 2: Salt + Post-Deployment Calldata Use a salt for deterministic deployment across chains. ```mermaid sequenceDiagram participant App participant Relayer participant LUKSO Network Note over App: Generate salt + postDeploymentCallData App->>Relayer: POST /api/universal-profile Note over App,Relayer: salt
postDeploymentCallData Relayer->>LUKSO Network: Deploy with deterministic address LUKSO Network-->>Relayer: Success Relayer-->>App: Return UP Address ``` ```javascript import { keccak256, encodeAbiParameters, getCreate2Address, randomBytes, } from 'viem'; import { ERC725 } from '@erc725/erc725.js'; import LSP3ProfileMetadataSchemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; // 1. Generate salt for deterministic deployment const salt = `0x${Buffer.from(randomBytes(32)).toString('hex')}`; // 2. Prepare LSP3Profile metadata (same as Option 1) const erc725 = new ERC725(LSP3ProfileMetadataSchemas); const encodedData = erc725.encodeData([ { keyName: 'LSP3Profile', value: { verification: { method: 'keccak256(utf8)', data: '0x6d6d08aafb0ee059e3e4b6b3528a5be37308a5d4f4d19657d26dd8a5ae799de0', }, url: 'ipfs://QmPRoJsaYcNqQiUrQxE7ajTRaXwHyAU29tHqYNctBmK64w', }, }, ]); // Extract the data keys and values const dataKeys = encodedData.keys; const dataValues = encodedData.values; // 3. Encode post-deployment calldata (ERC725Y data to set on the UP) const postDeploymentCalldata = encodeAbiParameters( [{ type: 'bytes32[]' }, { type: 'bytes[]' }], [dataKeys, dataValues], ); // 4. (Optional) Calculate the deterministic UP address const linkedContractsFactoryAddress = '0x2300000A84D25dF63081feAa37ba6b62C4c89a30'; const primaryImplementationContractAddress = '0x3024D38EA2434BA6635003Dc1BDC0daB5882ED4F'; // UP implementation const secondaryImplementationContractAddress = '0x2Fe3AeD98684E7351aD2D408A43cE09a738BF8a4'; // KM implementation const upPostDeploymentModuleAddress = '0x000000000066093407b6704B89793beFfD0D8F00'; const secondaryContractInitializationCalldata = '0xc4d66de8'; // initialize() selector const secondaryContractAddControlledContractAddress = true; const secondaryContractExtraInitializationParams = '0x'; const generatedSalt = keccak256( encodeAbiParameters( [ { type: 'bytes32' }, { type: 'address' }, { type: 'bytes' }, { type: 'bool' }, { type: 'bytes' }, { type: 'address' }, { type: 'bytes' }, ], [ salt, secondaryImplementationContractAddress, secondaryContractInitializationCalldata, secondaryContractAddControlledContractAddress, secondaryContractExtraInitializationParams, upPostDeploymentModuleAddress, postDeploymentCalldata, ], ), ); const upAddress = getCreate2Address({ from: linkedContractsFactoryAddress, salt: generatedSalt, bytecodeHash: keccak256( `0x3d602d80600a3d3981f3363d3d373d3d3d363d73${primaryImplementationContractAddress.slice(2)}5af43d82803e903d91602b57fd5bf3`, ), }); console.log('Predicted UP Address:', upAddress); // 5. Deploy the Universal Profile const response = await fetch( 'https://relayer-api.mainnet.lukso.network/api/universal-profile', { method: 'POST', headers: { Authorization: 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ salt, postDeploymentCallData: postDeploymentCalldata, }), }, ); const result = await response.json(); console.log('Deployed UP Address:', result.universalProfileAddress); console.log( 'Matches prediction:', result.universalProfileAddress === upAddress, ); ``` See [Deploy UP with LSP23](/learn/universal-profile/advanced-guides/deploy-up-with-lsp23#create-the-universal-profile-initialization-calldata) for more details on LSP23 deployments. ## Register Universal Profiles Register existing Universal Profiles with the Relayer API to enable the monthly gas quota. Requires an API key. ```javascript const response = await fetch( 'https://relayer-api.mainnet.lukso.network/api/universal-profile/register', { method: 'POST', headers: { Authorization: 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ universalProfileAddress: '0x1234567890123456789012345678901234567890', }), }, ); const result = await response.json(); console.log('Registered:', result); ``` ## Support - **Email**: [support@lukso.network](mailto:support@lukso.network) - **Discord**: [discord.com/invite/lukso](https://discord.com/invite/lukso) - **Documentation**: [docs.lukso.tech](https://docs.lukso.tech/) --- --- title: 🆙 Additional RPC APIs description: LUKSO's RPC API supported methods. sidebar_position: 1 --- # 🆙 RPC API The [LUKSO UP Browser Extension](/install-up-browser-extension) uses the RPC API methods from the table below. The methods are grouped by category: signing methods, standard methods, and LUKSO-specific methods. ## Supported Methods
Name Type
eth_sign signing
personal_sign signing
eth_accounts standard
eth_requestAccounts standard
eth_sendTransaction standard
wallet_switchEthereumChain standard
up_addTransactionRelayer LUKSO specific
up_import LUKSO specific
up_generateLSP23Address LUKSO specific
## Signing ### eth_sign :::tip We encourage developers to use `eth_sign` for signing purposes. ::: While a security issue potentially existed in the initial implementation on Ethereum, the current implementation has no such potential exploit. As such usage of this method is preferable to [personal_sign](#personal_sign). This method returns a [EIP-191](https://eips.ethereum.org/EIPS/eip-191) signature over the data provided to the call. It requests that the user provides an Ethereum address that should sign the transaction as well as the data (encoded bytes) that are to be executed. #### Returns `string` - on a successful call the method returns a signature, a string representing hex encoded bytes or an error with code `4001` - if the user rejects the request ### personal_sign The `personal_sign` endpoint is enabled to allow for backward compatibility. However, its use is not recommended. Some libraries such as Ethers.js end up using `personal_sign` under the hood. That is why, for compatibility reasons, `personal_sign` is left enabled. Note however that `personal_sign` ultimately acts as a proxy, redirecting the call to the [eth_sign](#eth_sign) method. ## Standard ### eth_sendTransaction {#eth_sendTransaction} Creates new message call transaction and signs it using the account specified in `from`. This method requires that the user has granted permission to interact with their account first. The transaction will not be signed by the UP itself, but by a controller address that has sufficient permissions. ### eth_requestAccounts {#eth_requestAccounts} This method is specified by [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102). Calling this method may trigger a user interface that allows the user to approve or reject account access for a given DApp. #### Returns `string[]` - an array of accounts or throws an error with code `4001` if the request was rejected by the user. ### wallet_switchEthereumChain {#wallet_switchEthereumChain} This method implements [EIP-3326](https://eips.ethereum.org/EIPS/eip-3326). It allows Dapps to request that a wallet switches its active chain (connection). The method requires that a target chain ID is provided #### Returns `null` or `error` - the method will return null if successful or throw an error otherwise ### eth_accounts {#eth_accounts} Similar to the `eth_requestAccounts` this method returns all of the addresses that the user has approved for the DApp. This method does not trigger a user interface. #### Returns `string[]` - a successful request returns an array of hexadecimal Ethereum address strings ## LUKSO Specific ### up_addTransactionRelayer {#up_addTransactionRelayer} Add a custom relayer. #### Parameters ##### 1. `relayer` - Object Object containing the new relayer properties. To find more information about custom relayers, you can read the [Transaction Relay Service API](../../standards/accounts/lsp15-transaction-relayer-api.md). | Name | Type | Description | | :--------- | :----- | :---------------------------- | | `name` | String | The name of the relayer. | | `apiUrl` | String | The base API URL. | | `chainIds` | Array | Array of string (hex) or int. | ```js params: [ { name: 'My Relayer', apiUrl: 'https://relayer.testnet.staging.lukso.dev/api/v1/', chainIds: [4201], }, ]; ``` #### Returns ##### 1. `String Array` - Array of Universal Profile addresses the user selected for this relay service It returns an array of Universal Profile addresses. ### up_import {#up_import} Add a Universal Profile address to the UP Browser Extension. #### Parameters ##### 1. `String` - Universal Profile address to add to the extension The Universal Profile address to add. ```js params: ['0x311611C9A46a192C14Ea993159a0498EDE5578aC']; ``` #### Returns ##### 1. `String` - New controller address, to be added to the profile by the dapp. ### up_generateLSP23Address {#up_generateLSP23Address} It allows the creation of a Universal Profile for the UP Browser Extension using the [LSP23 Standard](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md), which under the hood will wrap many operations/transactions into one, simplifying deployment. To perform the deployment of a Universal Profile, the dApp needs the salt and the controllerAddress. The controllerAddress will be injected in the dataKeys and dataValues array, then the salt and the encoded dataKeys and dataValues are sent to the relayer to deploy the profile. Previously, the relayer had to do several consecutive transactions to deploy a profile. Now, all those transactions are taking place at the smart contract level, so the relayer only creates one transaction. **up_generateLSP23Address**: should be used for creating a new Universal Profile using the UP Browser Extension **up_import**: should be used for adding already existing Universal Profiles to the UP Browser Extension ##### Parameters
Name Type Description
primaryImplementationContractAddress string Universal Profile implementation address
secondaryImplementationContractAddress string Key Manager implementation address
secondaryContractInitializationCalldata string initialization calldata for for the Key Manager contract
secondaryContractAddControlledContractAddress boolean the my.universalprofile.cloud sets it as true
secondaryContractExtraInitializationParams string my.universalprofile.cloud sets it as '0x'
upPostDeploymentModuleAddress string address of the post deployment module
linkedContractsFactoryAddress string address of the linkedContractsFactory (LSP23)
dataKeys string[] data that will be set on a smart contract, e.g: adding controllers, adding LSP3 metadata, or adding default controller permissions
dataValues string[] data that will be set on a smart contract, e.g: adding controllers, adding LSP3 metadata, or adding default controller permissions
dataKeysControllerIndex number an array index where the controller key is placed
dataValuesControllerIndex number array index where the controller value is placed
#### Returns | Name | Type | | ------------------- | --------- | | `salt` | string | | `controllerAddress` | string | | `upAddress` | upAddress | ### Additional Resources - [🎥 BuildUP #2 | Introduction to the Transaction Relay Service (YouTube)](https://www.youtube.com/watch?v=cpoczP3Y7Hk) --- --- sidebar_position: 1 --- # EIP191Signer ## hashEthereumSignedMessage ```javascript eip191Signer.hashEthereumSignedMessage(message); ``` Hashes the given message. The message will be enveloped as follows: `'\x19' + '\x45' + 'thereum Signed Message:\n' + messageBytes.length + message` and hashed using keccak256. ### Parameters `message` - `String`: A message to hash. ### Returns `String`: The hashed message constructed as `'\x19' + '\x45' + 'thereum Signed Message:\n' + messageBytes.length + message` ### Example ```javascript eip191Signer.hashEthereumSignedMessage('Hello World'); // '0xa1de988600a42c4b4ab089b619297c17d53cffae5d5120d82d8a92d0bb3b78f2'; ``` ## hashDataWithIntendedValidator ```javascript eip191Signer.hashDataWithIntendedValidator(validatorAddress, message); ``` Hashes the given message. The message will be enveloped as follows: `'\x19' + '\x00' + validatorAddress + message` and hashed using keccak256. ### Parameters `validatorAddress` - `String`: The address of the validator. `message` - `String`: A message to hash. ### Returns `String`: The hashed message constructed as `'\x19' + '\x00' + validatorAddress + message` ### Example ```javascript eip191Signer.hashDataWithIntendedValidator( 0xad278a6ead89f6b6c6fdf54a3e6e876660593b45, 'Hello World', ); // '0xa63022286ecaa3317625e319a64b3bf01c41da558dfc1890e8cb196eb414ffd5'; ``` ## signEthereumSignedMessage ```javascript eip191Signer.signEthereumSignedMessage(message, signingKey); ``` Signs a message. The message passed as parameter will be wrapped as follows: `'\x19' + '\x45' + 'thereum Signed Message:\n' + messageBytes.length + message` ### Parameters 1. `message` - `String`: The message to sign. 2. `signingKey` - `String`: The private key to sign with. ### Returns `Object`: **The Message object** - `message` - `String`: The given message. - `messageHash` - `String`: The hash of the given message constructed as `'\x19' + '\x45' + 'thereum Signed Message:\n' + messageBytes.length + message`. - `r` - `String`: First 32 bytes of the signature. - `s` - `String`: Next 32 bytes of the signature. - `v` - `String`: Recovery value + 27. - `signature` - `String`: The raw RLP encoded signature. ### Example ```javascript eip191Signer.signEthereumSignedMessage( 'Hello World', 'ffeb17b9a6059fec3bbab63d76b060b7380cac7a62ce6621a134531a46458968', ); /** { message: 'Hello World', messageHash: '0xa1de988600a42c4b4ab089b619297c17d53cffae5d5120d82d8a92d0bb3b78f2', v: '0x1c', r: '0x85c15865f2909897c1be6d66c1d9c86d6125978aec9e28d1a69d4d306bde694f', s: '0x7cf9723f0eeaf8815e3fa984ac1d7bf3c420786ead91abd4dd9c1657897efec1', signature: '0x85c15865f2909897c1be6d66c1d9c86d6125978aec9e28d1a69d4d306bde694f7cf9723f0eeaf8815e3fa984ac1d7bf3c420786ead91abd4dd9c1657897efec11c' } */ ``` ## signDataWithIntendedValidator ```javascript eip191Signer.signDataWithIntendedValidator( validatorAddress, message, signingKey, ); ``` Signs a message. The message passed as parameter will be wrapped as follows: `'\x19' + '\x00' + validatorAddress + message` ### Parameters 1. `validatorAddress` - `String`: The address of the validator. 2. `message` - `String`: The message to sign. 3. `signingKey` - `String`: The private key to sign with. ### Returns `Object`: **The Message object** - `message` - `String`: The given message. - `messageHash` - `String`: The hash of the given message constructed as `'\x19' + '\x00' + validatorAddress + message`. - `r` - `String`: First 32 bytes of the signature. - `s` - `String`: Next 32 bytes of the signature. - `v` - `String`: Recovery value + 27. - `signature` - `String`: The raw RLP encoded signature. ### Example ```javascript eip191Signer.signDataWithIntendedValidator( '0xad278a6ead89f6b6c6fdf54a3e6e876660593b45', 'Hello World', 'ffeb17b9a6059fec3bbab63d76b060b7380cac7a62ce6621a134531a46458968', ); /** { message: 'Hello World', messageHash: '0xa1de988600a42c4b4ab089b619297c17d53cffae5d5120d82d8a92d0bb3b78f2', v: '0x1c', r: '0x85c15865f2909897c1be6d66c1d9c86d6125978aec9e28d1a69d4d306bde694f', s: '0x7cf9723f0eeaf8815e3fa984ac1d7bf3c420786ead91abd4dd9c1657897efec1', signature: '0x85c15865f2909897c1be6d66c1d9c86d6125978aec9e28d1a69d4d306bde694f7cf9723f0eeaf8815e3fa984ac1d7bf3c420786ead91abd4dd9c1657897efec11c' } */ ``` ## recover ```javascript eip191Signer.recover(message, signature); ``` Recovers the address which was used to sign the given message. ### Parameters 1. `messageHash` - `String|Object`: **Either signed message already prefixed and hashed or Message object with the following values**: - `message` - `String`: The given message. - `messageHash` - `String`: The hash of the given message. - `r` - `String`: First 32 bytes of the signature. - `s` - `String`: Next 32 bytes of the signature. - `v` - `String`: Recovery value + 27. - `signature` - `String`: The raw RLP encoded signature. 2. `signature` - `String`: The raw RLP encoded signature. ### Returns `String`: The address used to sign the given message. ### Example ```javascript eip191Signer.recover( 'Hello World', '0x1eab2de0103b8e82650f9706b17cf2adce55a335e7041bad5a94ab49c56a9c12662e80a369ffa2a6a77fbeaad1f32653cbd74860c8fbc999b1fc47b8d1cb7d931c', ); // 0x4C58e78663CB5D2Bd84Dc10beDe82A7C83442a8d; ``` --- --- sidebar_position: 1 --- # Getting Started - [GitHub Repository](https://github.com/lukso-network/tools-eip191-signer) - [NPM Package](https://www.npmjs.com/package/@lukso/eip191-signer.js) The `@lukso/eip191-signer.js` package is used to sign any EIP191 data. The following format is used to sign data : ```bash 0x19 <1 byte version> ``` In the case of an Ethereum Signed Message: - 1 byte version = `0x45` - version specific data = `thereum Signed Message:\n + len(message)` In the case of data with intended validator: - 1 byte version = `0x00` - version specific data = validatorAddress This prefix is used so that a transaction cannot be inadvertently signed when signing an Ethereum signed message. # Install ```bash npm install @lukso/eip191-signer.js ``` # Setup ```javascript import { EIP191Signer } from '@lukso/eip191-signer.js'; const eip191Signer = new EIP191Signer(); ``` --- --- sidebar_position: 1 --- # Getting Started :::caution This package is currently in the early stages of development. Feel free to [report issues or feature requests](https://github.com/ERC725Alliance/erc725.js/issues) through the Github repository. :::

The `@erc725/erc725.js` package allows you to retrieve, encode and decode data easily from any ERC725Y smart contracts using ERC725Y JSON Schemas. :::tip ERC725 Inspect You can easily retrieve the list of metadata and permissions from Universal Profile and Digital Assets, as well as encoding and decoding data using the [ERC725 Inspect Tool](https://erc725-inspect.lukso.tech/?network=lukso+mainnet). ::: ## Installation :::info If you install it on the backend side, you may need to also install [`isomorphic-fetch`](https://www.npmjs.com/package/isomorphic-fetch). ::: ```bash npm install @erc725/erc725.js ``` ## Usage > If you are using ES6 `import` statements in Node.js, make sure your file has a `.mjs` extension, or that your project is set up to support ES6 modules. There are 3 main ways to use _erc725.js_. ### Option 1: use a schema for encoding / decoding data Create an instance of `ERC725` with just a [schema](https://docs.lukso.tech/tools/dapps/erc725js/schemas/). **Useful for just encoding / decoding data.** ```js import ERC725, { ERC725JSONSchema } from '@erc725/erc725.js'; const schemas: ERC725JSONSchema[] = [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', keyType: 'Singleton', valueType: 'bytes', valueContent: 'VerifiableURI', }, ]; const erc725 = new ERC725(schemas); ``` ### Option 2: connect to a smart contract to fetch/decode data Same as option 1 where you can pass an ERC725Y contract address, an RPC URL and some additional configurations (e.g: IPFS gateway). **Useful to fetch and decode data automatically from a contract deployed on a network**. ```js import ERC725, { ERC725JSONSchema } from '@erc725/erc725.js'; // Part of LSP3-Profile-Metadata Schema // https://github.com/lukso-network/LIPs/blob/master/LSPs/LSP-3-Profile-Metadata.md const schemas: ERC725JSONSchema[] = [ { name: 'SupportedStandards:LSP3Profile', key: '0xeafec4d89fa9619884b600005ef83ad9559033e6e941db7d7c495acdce616347', keyType: 'Mapping', valueType: 'bytes', valueContent: '0x5ef83ad9', }, { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', keyType: 'Singleton', valueType: 'bytes', valueContent: 'VerifiableURI', }, { name: 'LSP1UniversalReceiverDelegate', key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', keyType: 'Singleton', valueType: 'address', valueContent: 'Address', }, ]; const address = '0x0Dc07C77985fE31996Ed612F568eb441afe5768D'; const RPC_URL = 'https://rpc.testnet.lukso.network'; const config = { ipfsGateway: 'https://YOUR-IPFS-GATEWAY/ipfs/', gas: 20_000_000, // optional, default is 1_000_000 }; const erc725 = new ERC725(schemas, address, RPC_URL, config); ``` ### Option 3: use specific functions or static methods You can import specific functions or use static methods from the `ERC725` class. **Useful to add only specific functionalities to your dApp (_e.g:_ decoding `VerifiableURI`, encoding dynamic keys).** ```js import { encodeValueType, encodeDataSourceWithHash, decodeDataSourceWithHash, } from '@erc725/erc725.js'; const someNumber = encodeValueType('uint128', 3); // 0x00000000000000000000000000000003 const reEncodedVerifiableURI = decodeDataSourceWithHash( '0x00006f357c6a0020820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455a4c6a7452504466573834554178', ); // verification: { // data: '820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361', // method: 'keccak256(utf8)', // source: 'ifps://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx' // }, const verifiableURI = encodeDataSourceWithHash( { method: 'keccak256(utf8)', data: '820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361', }, 'ifps://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx', ); // 0x00006f357c6a0020820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455a4c6a7452504466573834554178 ``` ## Functionalities :::tip Try it out Try running the code snippets below within your browser using [StackBlitz](https://stackblitz.com/edit/erc725js-instantiation?devtoolsheight=66&file=index.js). ::: The _erc725.js_ contains multiple functionalities such as reading and decoding data. A full list is available under the [**Methods**](./methods.md) page. For fetching data, it is possible to query one data key (as a `string` name) or multiple data keys at once by passing an array parameter, as shown below. ```js await erc725.getOwner(); // > '0x28D25E70819140daF65b724158D00c373D1a18ee' await erc725.getData('SupportedStandards:LSP3Profile'); /** { 'SupportedStandards:LSP3Profile': '0x5ef83ad9' } */ await erc725.getData(['LSP3Profile', 'SupportedStandards:LSP3Profile']); /** { LSP3Profile: { url: 'ipfs://QmXybv2LdJWscy1C6yRKUjvnaj6aqKktZX4g4xmz2nyYj2', verification: { data: '0xb4f9d72e83bbe7e250ed9ec80332c493b7b3d73e0d72f7b2c7ab01c39216eb1a', method: 'keccak256(utf8)' } }, 'SupportedStandards:LSP3Profile': '0x5ef83ad9' } */ await erc725.fetchData('LSP3Profile'); // downloads and verifies the linked JSON /** { LSP3Profile: { LSP3Profile: { name: 'frozeman', description: 'The inventor of ERC725 and ERC20...', links: [ { title: 'Twitter', url: 'https://twitter.com/feindura' }, { title: 'lukso.network', url: 'https://lukso.network' } ], ... } } } */ ``` After the `ERC725` instance has been created, it is still possible to change settings through the `options` property. ```javascript myERC725.options.schema = '' // change schema myERC725.options.address '
' // change address myERC725.options.ipfsGateway = '' // used for fetchData(), default: 'https://cloudflare-ipfs.com/ipfs/' myERC725.options.gas = 20_000_000 // change gas setting // NOTE: ERC725.provider can not be changed ``` --- --- sidebar_position: 1 title: 'Methods' --- import CodeSandbox from "@site/src/components/CodeSandbox"; ## Encoding ### encodeData ```js myErc725.encodeData(data [, schemas]); ``` ```js ERC725.encodeData(data, schemas); ``` Encode the data of a smart contract according to your `ERC725JSONSchema` so that you can store the information in smart contracts. :::tip When encoding JSON, it is possible to pass in the JSON object and the URL where it is available publicly. The JSON will be hashed with `keccak256`. ::: :::info When encoding some values using specific `string` or `bytesN` as `valueType`, if the data passed is a non-hex value, _erc725.js_ will convert the value to its utf8-hex representation for you. For instance: - If `valueType` is `string` and you provide a `number` as input. _Example: input `42` --> will encode as `0x3432` (utf-8 hex code for `4` = `0x34`, for `2` = `0x32`)._ - If `valueType` is `bytes32` or `bytes4`, it will convert as follow: _Example 1: input `week` encoded as `bytes4` --> will encode as `0x7765656b`._ _Example 2: input `1122334455` encoded as `bytes4` --> will encode as `0x42e576f7`._ ::: #### Parameters ##### 1. `data` - Array of Objects An array of objects containing the following properties: | Name | Type | Description | | :---------------------------- | :---------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `keyName` | string | Can be either the named key (i.e. `LSP3Profile`, `LSP12IssuedAssetsMap:
`) or the hashed key (with or without `0x` prefix, i.e. `0x5ef...` or `5ef...`). | | `dynamicKeyParts` (optional) | string or
string[ ] | The dynamic parts of the `keyName` that will be used for encoding the key. | | `value` | string or
string[ ]
JSON | The value that should be encoded. Can be a string, an array of string or a JSON... | | `startingIndex` (optional) | number | Starting index for `Array` types to encode a subset of elements. Defaults to `0`. | | `totalArrayLength` (optional) | number | Parameter for `Array` types, specifying the total length when encoding a subset of elements. Defaults to the number of elements in the `value` field. | The `keyName` also supports dynamic keys for [`Mapping`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#mapping) and [`MappingWithGrouping`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#mapping). Therefore, you can use variables in the key name such as `LSP12IssuedAssetsMap:
`. In that case, the value should also set the `dynamicKeyParts` property: - `dynamicKeyParts`: string or string[ ] which holds the variables that needs to be encoded. :::info Handling keyType `Array`. If the keyType is Array and you pass an integer as a value it will encode only the data key for the Array length. See the example below. Additionally, the `totalArrayLength` parameter must be explicitly provided to ensure integrity when encoding subsets or modifying existing array elements. Its value specifies the total length of the array **after the operation is completed**, not just the size of the encoded subset. **When to use `totalArrayLength`** - **Adding Elements:** When adding new elements to an array, `totalArrayLength` should equal the sum of the current array's length plus the number of new elements added. - **Modifying Elements:** If modifying elements within an existing array without changing the total number of elements, `totalArrayLength` should match the previous length of the array. - **Removing Elements:** In cases where elements are removed, `totalArrayLength` should reflect the number of elements left. ::: :::caution Encoding array lengths Please be careful when updating existing contract data. Incorrect usage of `startingIndex` and `totalArrayLength` can lead to improperly encoded data that changes the intended structure of the data field. ::: ##### 2. `schemas` - Array of Objects (optional) An array of extra [LSP-2 ERC725YJSONSchema] objects that can be used to find the schema. If called on an instance, it is optional and it will be concatenated with the schema provided on instantiation. #### Returns | Name | Type | Description | | :------------ | :----- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `encodedData` | Object | An object containing the encoded keys and values according to the [LSP2 ERC725Y JSON Schema](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md) of the data which was passed | After the `data` is encoded, the object is ready to be stored in smart contracts. #### Examples
**Encode** a Singleton data key ```javascript title="encode a Singleton data key of valueContent Address" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'LSP1UniversalReceiverDelegate', key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', keyType: 'Singleton', valueType: 'address', valueContent: 'Address', }, ]; const myErc725 = new ERC725(schemas); myErc725.encodeData([ { keyName: 'LSP1UniversalReceiverDelegate', value: '0x1183790f29BE3cDfD0A102862fEA1a4a30b3AdAb', }, ]); /** { keys: ['0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47'], values: ['0x1183790f29be3cdfd0a102862fea1a4a30b3adab'], } */ ```
Encode a VerifiableURI with JSON and uploaded URL ```javascript title="Encode a VerifiableURI with JSON and uploaded URL" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', keyType: 'Singleton', valueType: 'bytes', valueContent: 'VerifiableURI', }, ]; const myErc725 = new ERC725(schemas); myErc725.encodeData([ { keyName: 'LSP3Profile', value: { json: profileJson, url: 'ipfs://QmQTqheBLZFnQUxu5RDs8tA9JtkxfZqMBcmGd9sukXxwRm', }, }, ]); /** { keys: ['0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5'], values: ['0x6f357c6a2404a2866f05e53e141eb61382a045e53c2fc54831daca9d9e1e039a11f739e1696670733a2f2f516d5154716865424c5a466e5155787535524473387441394a746b78665a714d42636d47643973756b587877526d'], } */ // You can also use the hashed key (with or without 0x prefix) myErc725.encodeData([ { keyName: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { json: profileJson, url: 'ipfs://QmQTqheBLZFnQUxu5RDs8tA9JtkxfZqMBcmGd9sukXxwRm', }, }, ]); /** { keys: ['0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5'], values: ['0x6f357c6a2404a2866f05e53e141eb61382a045e53c2fc54831daca9d9e1e039a11f739e1696670733a2f2f516d5154716865424c5a466e5155787535524473387441394a746b78665a714d42636d47643973756b587877526d'], } */ myErc725.encodeData([ { keyName: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { json: profileJson, url: 'ipfs://QmQTqheBLZFnQUxu5RDs8tA9JtkxfZqMBcmGd9sukXxwRm', }, }, ]); /** { keys: ['0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5'], values: ['0x6f357c6a2404a2866f05e53e141eb61382a045e53c2fc54831daca9d9e1e039a11f739e1696670733a2f2f516d5154716865424c5a466e5155787535524473387441394a746b78665a714d42636d47643973756b587877526d'], } */ ```
**Encode** a VerifiableURI with hash function, hash and uploaded URL ```javascript title="Encode a VerifiableURI with hash function, hash and uploaded URL" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', keyType: 'Singleton', valueType: 'bytes', valueContent: 'VerifiableURI', }, ]; const myErc725 = new ERC725(schemas); myErc725.encodeData([ { keyName: 'LSP3Profile', value: { verification: { method: 'keccak256(utf8)', data: '0x820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361', }, url: 'ipfs://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx', }, }, ]); /** { keys: ['0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5'], values: ['0x6f357c6a820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455a4c6a7452504466573834554178'], } */ ```
Encode dynamic keys ```javascript title="Encode dynamic keys" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'DynamicKey:
', key: '0x0fb367364e1852abc5f20000
', keyType: 'Mapping', valueType: 'bytes', valueContent: 'Address', }, ]; myErc725.encodeData( [ { keyName: 'DynamicKey:
', dynamicKeyParts: ['0xbedbedbedbedbedbedbedbedbedbedbedbedbedb'], value: '0xcafecafecafecafecafecafecafecafecafecafe', }, ], schemas, ); /** { keys: ['0x0fb367364e1852abc5f20000bedbedbedbedbedbedbedbedbedbedbedbedbedb'], values: ['0xcafecafecafecafecafecafecafecafecafecafe] } */ const schemas = [ { name: 'DynamicKey::', key: '0xForDynamicKeysThisFieldIsIrrelevantAndWillBeOverwriten', keyType: 'Mapping', valueType: 'bytes', valueContent: 'Address', }, ]; myErc725.encodeData( [ { keyName: 'DynamicKey::', dynamicKeyParts: ['0x11223344', 'Summer'], value: '0xcafecafecafecafecafecafecafecafecafecafe', }, ], schemas, ); /** { keys: ['0x0fb367364e1852abc5f2000078c964cd805233eb39f2db152340079088809725'], values: ['0xcafecafecafecafecafecafecafecafecafecafe'] } */ ```
Encode multiple data keys at once ```javascript title="Encode multiple keys at once" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', keyType: 'Singleton', valueType: 'bytes', valueContent: 'VerifiableURI', }, { name: 'LSP1UniversalReceiverDelegate', key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', keyType: 'Singleton', valueType: 'address', valueContent: 'Address', }, { name: 'LSP12IssuedAssets[]', key: '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', keyType: 'Array', valueType: 'address', valueContent: 'Address', }, ]; const myErc725 = new ERC725(schemas); myErc725.encodeData([ { keyName: 'LSP3Profile', value: { verification: { method: 'keccak256(utf8)', data: '0x820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361', }, url: 'ipfs://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx', }, }, { keyName: 'LSP1UniversalReceiverDelegate', value: '0x1183790f29BE3cDfD0A102862fEA1a4a30b3AdAb', }, { keyName: 'LSP12IssuedAssets[]', value: [ '0xD94353D9B005B3c0A9Da169b768a31C57844e490', '0xDaea594E385Fc724449E3118B2Db7E86dFBa1826', ], }, ]); /** { keys: [ '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', // LSP3Profile -> data key '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', // LSP1UniversalReceiverDelegate -> data key '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', // LSP12IssuedAssets[] -> data key for `LSP12IssuedAssets[].length` '0x7c8c3416d6cda87cd42c71ea1843df2800000000000000000000000000000000', // LSP12IssuedAssets[0] -> data key for index 0 '0x7c8c3416d6cda87cd42c71ea1843df2800000000000000000000000000000001', // LSP12IssuedAssets[1] -> data key for index 1 ], values: [ '0x6f357c6a820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455 a4c6a7452504466573834554178', // LSP3Profile -> value as VerifiableURI '0x1183790f29be3cdfd0a102862fea1a4a30b3adab', // LSP1UniversalReceiverDelegate -> value as Address '0x00000000000000000000000000000002', // LSP12IssuedAssets[].length = 2 '0xd94353d9b005b3c0a9da169b768a31c57844e490', // LSP12IssuedAssets[0] -> Address stored at index 0 '0xdaea594e385fc724449e3118b2db7e86dfba1826', // LSP12IssuedAssets[1] -> Address stored at index 1 ], } */ ```
Encode array length only ```javascript title="Encode the length of an array" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'LSP12IssuedAssets[]', key: '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', keyType: 'Array', valueType: 'address', valueContent: 'Address', }, ]; const myErc725 = new ERC725(schemas); myErc725.encodeData([ { keyName: 'LSP12IssuedAssets[]', value: 5, }, ]); /** { keys: [ '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', ], values: ['0x00000000000000000000000000000005'], } */ ```
Encode a subset of array elements ```javascript title="Encode a subset of array elements" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'AddressPermissions[]', key: '0xdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e3', keyType: 'Array', valueType: 'address', valueContent: 'Address', }, ]; const myErc725 = new ERC725(schemas); myErc725.encodeData( [ { keyName: 'AddressPermissions[]', value: [ '0x983abc616f2442bab7a917e6bb8660df8b01f3bf', '0x56ecbc104136d00eb37aa0dce60e075f10292d81', ], totalArrayLength: 23, startingIndex: 21, }, ], schemas, ); /** { keys: [ '0xdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e3', // LSP12IssuedAssets[] -> data key for `LSP12IssuedAssets[].length` '0xdf30dba06db6a30e65354d9a64c6098600000000000000000000000000000015', // LSP12IssuedAssets[21] -> data key for index 21 '0xdf30dba06db6a30e65354d9a64c6098600000000000000000000000000000016', // LSP12IssuedAssets[22] -> data key for index 22 ], values: [ '0x00000000000000000000000000000017', // LSP12IssuedAssets[].length = 23 '0x983abc616f2442bab7a917e6bb8660df8b01f3bf', // LSP12IssuedAssets[21] -> Address stored at index 21 '0x56ecbc104136d00eb37aa0dce60e075f10292d81', // LSP12IssuedAssets[22] -> Address stored at index 22 ], } */ ```
Encode a tuple for valueType / valueContent ```javascript title="Encode a tuple for valueType / valueContent" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'LSP4CreatorsMap:
', key: '0x6de85eaf5d982b4e5da00000
', keyType: 'Mapping', valueType: '(bytes4,uint128)', valueContent: '(Bytes4,Number)', }, ]; ERC725.encodeData( [ { keyName: 'LSP4CreatorsMap:
', dynamicKeyParts: "0xcafecafecafecafecafecafecafecafecafecafe" value: ['0x24871b3d', '11'], }, ], schemas, ); /** { keys: [ '0xdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e3', // -> data key for `LSP4CreatorsMap:0xcafecafecafecafecafecafecafecafecafecafe` ], values: [ '0x24871b3d0000000000000000000000000000000b', // (bytes4,uint128) ], } */ ```
Encode a tuple of CompactBytesArray ```ts title="Encode a tuple of CompactBytesArray" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'AddressPermissions:AllowedCalls:
', key: '0x4b80742de2bf393a64c70000
', keyType: 'MappingWithGrouping', valueType: '(bytes4,address,bytes4,bytes4)[CompactBytesArray]', valueContent: '(BitArray,Address,Bytes4,Bytes4)', } ]; ERC725.encodeData( [ { keyName: 'AddressPermissions:AllowedCalls:
', dynamicKeyParts: "0xcafecafecafecafecafecafecafecafecafecafe" value: [ [ '0x00000003', // CALL and TRANSFERVALUE '0xCA41e4ea94c8fA99889c8EA2c8948768cBaf4bc0', // addresses are decoded as checksummed '0x3e89ad98', // LSP0 interface ID '0xffffffff', // any function ], [ '0x00000002', // CALL only '0xF70Ce3b58f275A4c28d06C98615760dDe774DE57', '0xffffffff', // any standard interface ID '0x760d9bba', // function selector of `transfer(address,address,uint256,bool,bytes)` ], [ '0x00000001', // TRANSFERVALUE only '0xd3236aa1B8A4dDe5eA375fd1F2Fb5c354e686c9f', '0xffffffff', // any standard interface ID '0xffffffff', // any function ], ] }, ], schemas, ); /** { keys: [ '0x4b80742de2bf393a64c70000cafecafecafecafecafecafecafecafecafecafe', // -> data key for `AddressPermissions:AllowedCalls:0xcafecafecafecafecafecafecafecafecafecafe` ], values: [ '0x002000000003ca41e4ea94c8fa99889c8ea2c8948768cbaf4bc03e89ad98ffffffff002000000002f70ce3b58f275a4c28d06c98615760dde774de57ffffffff760d9bba002000000001d3236aa1b8a4dde5ea375fd1f2fb5c354e686c9fffffffffffffffff', // (bytes4,address,bytes4,bytes4)[CompactBytesArray] ], } */ ```
--- ### encodeArrayKey ```js ERC725.encodeArrayKey(key, index); ``` Generate the raw bytes key for an array element at a specific index according to the LSP2 ERC725Y JSON Schema standard. :::info `encodeArrayKey` is available as a static function. ::: #### Parameters ##### 1. `key` - String The schema key of a schema with keyType = 'Array' ##### 2. `index` - Number An integer representing the intended array index #### Returns | Name | Type | Description | | :----------- | :----- | :-------------------------------------- | | `encodedKey` | string | The raw bytes key for the array element | #### Example ```javascript title="Encode an array key for a specific index" import { encodeArrayKey } from '@erc725/erc725.js'; const arrayKey = '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd'; // LSP12IssuedAssets[] const index = 2; const encodedArrayKey = encodeArrayKey(arrayKey, index); // '0x7c8c3416d6cda87cd42c71ea1843df2800000000000000000000000000000002' ``` --- ### encodeKeyName ```js ERC725.encodeKeyName(keyName [, dynamicKeyParts]); ``` Hashes a key name for use on an [ERC725Y contract](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y) according to the [LSP2 ERC725Y JSON Schema Standard](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md). :::info `encodeKeyName` is available as either a static or non-static method so can be called without instantiating an ERC725 object. ::: #### Parameters ##### 1. `keyName` - String The key name you want to encode, for instance: `LSP3Profile`. ##### 2. `dynamicKeyParts` - String or array of Strings (optional) The variables used to encode the key name, if the key name is a dynamic (i.e.: `MyKey:
`...) #### Returns | Name | Type | Description | | :--------------- | :----- | :------------------------------------------- | | `encodedKeyName` | string | The keccak256 hash of the provided key name. | The hash must be retrievable from the ERC725Y contract via the [getData](#getdata) function. #### Example ```javascript title="Encode the key name" import ERC725 from '@erc725/erc725.js'; ERC725.encodeKeyName('LSP3Profile'); // '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5' ERC725.encodeKeyName('SupportedStandards:LSP3Profile'); // '0xeafec4d89fa9619884b600005ef83ad9559033e6e941db7d7c495acdce616347' ERC725.encodeKeyName( 'AddressPermissions:Permissions:cafecafecafecafecafecafecafecafecafecafe', ); // '0x4b80742de2bf82acb3630000cafecafecafecafecafecafecafecafecafecafe' ERC725.encodeKeyName('MyKeyName:', 'true'); // '0x35e6950bc8d21a1699e500000000000000000000000000000000000000000001' ERC725.encodeKeyName('MyKeyName::', ['ffff', '4081242941']); // 0x35e6950bc8d20000ffff000000000000000000000000000000000000f342d33d ERC725.encodeKeyName('MyKeyName:', ['4081242941']); // 0x35e6950bc8d21a1699e5000000000000000000000000000000000000f342d33d // This method is also available on the instance: myErc725.encodeKeyName('LSP3Profile'); ``` --- ### isDynamicKeyName ```js import { isDynamicKeyName } from '@erc725/erc725.js'; isDynamicKeyName(keyName); ``` Check if a key name contains dynamic parts (like `
`, ``, etc.) according to the LSP2 ERC725Y JSON Schema standard. :::info `isDynamicKeyName` is available as a standalone function import. ::: #### Parameters ##### 1. `keyName` - String The key name to check for dynamic parts. #### Returns | Name | Type | Description | | :------- | :------ | :---------------------------------------------------------------- | | `result` | boolean | `true` if the key name contains dynamic parts, `false` otherwise. | #### Examples ```javascript title="Check if key names are dynamic" import { isDynamicKeyName } from '@erc725/erc725.js'; isDynamicKeyName('LSP3Profile'); // false isDynamicKeyName('LSP5ReceivedAssetsMap:
'); // true isDynamicKeyName('AddressPermissions:AllowedStandards:
'); // true isDynamicKeyName('MyKey::'); // true isDynamicKeyName(''); // true ``` --- ### encodeValueType ```js myErc725.encodeValueType(type, value); ``` ```js ERC725.encodeValueType(type, value); ``` #### Parameters | Name | Type | Description | | :------ | :--------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------- | | `type` | string | The value type to encode the value (i.e. `uint256`, `bool`, `bytes4`, etc...). | | `value` | string or
string[ ] or
number or
number[ ] or
boolean or
boolean[] | The value that should be encoded as `type` | #### Returns | Name | Type | Description | | :----------------- | :----- | :------------------------------------------------------- | | `encodedValueType` | string | A hex string representing the `value` encoded as `type`. | After the `value` is encoded, the hex string can be used to be stored inside the ERC725Y smart contract. #### Examples ```javascript import ERC725 from '@erc725/erc725.js'; const myErc725 = new ERC725(); myErc725.encodeValueType('uint256', 5); // '0x0000000000000000000000000000000000000000000000000000000000000005' myErc725.encodeValueType('bool', true); // '0x01' // the word `boolean` (Name of the Typescript type) is also available myErc725.encodeValueType('boolean', true); // '0x01' // `bytesN` type will pad on the right if the value contains less than N bytes myErc725.encodeValueType('bytes4', '0xcafe'); // '0xcafe0000' myErc725.encodeValueType('bytes32', '0xcafe'); // '0xcafe000000000000000000000000000000000000000000000000000000000000' // `bytesN` type will throw an error if the value contains more than N bytes myERC725.encodeValueType('bytes4', '0xcafecafebeef'); // Error: Can't convert 0xcafecafebeef to bytes4. Too many bytes, expected at most 4 bytes, received 6. // Can also be used to encode arrays as `CompactBytesArray` myERC725.encodeValueType('uint256[CompactBytesArray]', [1, 2, 3]); // '0x002000000000000000000000000000000000000000000000000000000000000000010020000000000000000000000000000000000000000000000000000000000000000200200000000000000000000000000000000000000000000000000000000000000003' myERC725.encodeValueType('bytes[CompactBytesArray]', [ '0xaaaaaaaa', '0xbbbbbbbbbbbbbbbbbb', ]); // '0x0004aaaaaaaa0009bbbbbbbbbbbbbbbbbb' ``` This method is also available as a static method. ```javascript import ERC725 from '@erc725/erc725.js'; ERC725.encodeValueType('string', 'Hello'); // '0x48656c6c6f' ``` --- ### encodeValueContent ```js myErc725.encodeValueContent(valueContent, value); ``` or ```js ERC725.encodeValueContent(valueContent, value); ``` or ```js import { encodeValueContent } from '@erc725/erc725.js'; encodeValueContent(valueContent, value); ``` Encode `value` into a hex bytestring that can be then fetched, decoded and interpreted as the specified `valueContent`. #### Parameters | Name | Type | Description | | :------------- | :------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `valueContent` | `string` | Available options are:
  • `AssetURL`
  • `JSONURL`
  • `Boolean`
  • `Keccak256`
  • `Number`
  • `Address`
  • `String`
  • `Markdown`
  • `URL`
  • `VerifiableURI`
  • `BytesN`
  • `BitArray`
  • `Boolean`
  • Any Hex `Literal` (e.g.: 0x1345ABCD...)
| | `value` | `string` or
`number` or
`boolean` or
`AssetURLEncode` or
`AssetURLEncode` | The value to encode. | #### Returns | Name | Type | Description | | :--- | :------- | :--------------------------------------- | | | `string` | The `value` encoded as a `valueContent`. | #### Examples ```javascript import { encodeValueContent } from '@erc725/erc725.js'; encodeValueContent('String', 'hello'); // 0x68656c6c6f // BytesN will right pad encodeValueContent('Bytes8', '0xaabbccdd'); // 0xaabbccdd00000000 // Encoding some markdown encodeValueContent( 'Markdown', `# Lorem Ipsum dolor sit amet ebriscus lanfogern`, ); // 0x23204c6f72656d20497073756d0a2020202020202020646f6c6f722073697420616d6574206562726973637573206c616e666f6765726 encodeValueContent('URL', 'http://test.com'); // 0x687474703a2f2f746573742e636f6d encodeValueContent('VerifiableURI', { verification: { method: 'keccak256(utf8)', data: '0x027547537d35728a741470df1ccf65de10b454ca0def7c5c20b257b7b8d16168', }, url: 'http://test.com/asset.glb', }); // 0x00006f357c6a0020027547537d35728a741470df1ccf65de10b454ca0def7c5c20b257b7b8d16168687474703a2f2f746573742e636f6d2f61737365742e676c62 encodeValueContent('VerifiableURI', { verification: { method: '0x00000000', data: '0x', }, url: 'https://name.universal.page/', }); // 0x000000000000000068747470733a2f2f6e616d652e756e6976657273616c2e706167652f ``` This method is also available as a static method or as a method from the `ERC725` instance. ```javascript import ERC725 from '@erc725/erc725.js'; ERC725.encodeValueContent('String', 'hello'); // 0x68656c6c6f const erc725 = new ERC725(); erc725.encodeValueContent('String', 'hello'); // 0x68656c6c6f ``` --- ## Decoding ### decodeData ```js myErc725.decodeData(data [, schemas]); ``` ```js ERC725.decodeData(data, schemas); ``` If you are reading the key-value store from an ERC725 smart contract you can use the `decodeData` function to do the decoding for you. :::tip If you want total convenience, it is recommended to use the [`fetchData`](#fetchdata) function, which automatically `decodes` and `fetches` external references. ::: #### Parameters ##### 1. `data` - Object or array of Objects An object or array of objects containing the following properties: | Name | Type | Description | | :--------------------------- | :----------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `keyName` | string | Can be either the named key (i.e. `LSP3Profile`, `LSP12IssuedAssetsMap:
`) or the hashed key (with or without `0x` prefix, i.e. `0x5ef...` or `5ef...`). | | `dynamicKeyParts` (optional) | string or
string[ ] | If `keyName` is a dynamic key, the dynamic parts of the `keyName` that will be used for encoding the key. | | `value` | string or
string[ ] | The value that should be decoded. Can be a string, an array of string, or a JSON. | The `keyName` also supports dynamic keys for [`Mapping`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#mapping) and [`MappingWithGrouping`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#mapping). Therefore, you can use variables in the key name such as `LSP12IssuedAssetsMap:
`. In that case, the value should also set the `dynamicKeyParts` property: - `dynamicKeyParts`: string or string[ ] which holds the variables that needs to be encoded. ##### 2. `schemas` - Array of Objects (optional) An array of extra [LSP-2 ERC725YJSONSchema] objects that can be used to find the schema. If called on an instance, the parameter is optional and will be concatenated with the schema provided on instantiation. #### Returns | Name | Type | Description | | :------------ | :-------------- | :----------------------------------------------------------------- | | `decodedData` | Object or Array | The decoded data as defined and expected in the following schemas. | :::info - If the input is an array of objects, the values will be returned in an array. - If the input is a single object, the output will be the decodedData object directly. ::: #### Single-Key Example ```javascript title="Decoding an object with one key" myErc725.decodeData([ { keyName: 'LSP3Profile', value: '0x6f357c6a820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455a4c6a7452504466573834554178', }, ]); /** [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { method: 'keccak256(utf8)', data: '0x820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361' }, url: 'ipfs://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx', }, }, ] */ myErc725.decodeData({ keyName: 'LSP3Profile', value: '0x6f357c6a820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455a4c6a7452504466573834554178', }); /** { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { method: 'keccak256(utf8)', data: '0x820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361' }, url: 'ipfs://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx', }, } */ ``` #### Multi-Key Example ```javascript title="Decoding an object with multiple keys" myErc725.decodeData([ { keyName: 'LSP3Profile', value: '0x6f357c6a820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455a4c6a7452504466573834554178', }, { keyName: 'LSP12IssuedAssets[]', value: [ { key: '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', value: '0x00000000000000000000000000000002', }, { key: '0x7c8c3416d6cda87cd42c71ea1843df2800000000000000000000000000000000', value: '0xd94353d9b005b3c0a9da169b768a31c57844e490', }, { key: '0x7c8c3416d6cda87cd42c71ea1843df2800000000000000000000000000000001', value: '0xdaea594e385fc724449e3118b2db7e86dfba1826', }, ], }, ]); /** [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { data: '0x820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361', method: 'keccak256(utf8)' }, url: 'ipfs://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx', }, }, { name: 'LSP12IssuedAssets[]', key: '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', value: [ '0xD94353D9B005B3c0A9Da169b768a31C57844e490', '0xDaea594E385Fc724449E3118B2Db7E86dFBa1826', ], }, ]; */ ``` #### Dynamic-Key Example ```javascript title="Decoding an object with dynamic key and a custom schema" const schemas = [ { name: 'MyKeyName::', key: '0x...', keyType: 'Singleton', valueType: 'bytes', valueContent: 'VerifiableURI', }, ]; myErc725.decodeData( [ { keyName: 'MyKeyName::', dynamicKeyParts: [ '0xaaaabbbbccccddddeeeeffff111122223333444455556666777788889999aaaa', 'true', ], value: '0x00006f357c6a0020820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455a4c6a7452504466573834554178', }, ], schemas, ); /** [ { name: 'MyKeyName:aaaabbbbccccddddeeeeffff111122223333444455556666777788889999aaaa:true', key: '0x35e6950bc8d2aaaabbbb00000000000000000000000000000000000000000001', value: { verification: { method: 'keccak256(utf8)', data: '0x820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361' }, url: 'ifps://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx', }, }, ]; */ ``` --- #### Tuple Example ```javascript title="Decode a key with tuple as valueType / valueContent" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'LSP4CreatorsMap:
', key: '0x6de85eaf5d982b4e5da00000
', keyType: 'Mapping', valueType: '(bytes4,uint128)', valueContent: '(Bytes4,Number)', }, ]; ERC725.decodeData( { keyName: 'LSP4CreatorsMap:
', dynamicKeyParts: "0xcafecafecafecafecafecafecafecafecafecafe" value: "0x24871b3d0000000000000000000000000000000b", }, schemas, ); /** { key: '0x6de85eaf5d982b4e5da00000cafecafecafecafecafecafecafecafecafecafe', name: 'LSP4CreatorsMap:cafecafecafecafecafecafecafecafecafecafe', value: ['0x24871b3d', 11] } */ ``` #### Tuple of CompactBytesArray Example ```ts title="Decode a tuple of CompactBytesArray" import ERC725 from '@erc725/erc725.js'; const schemas = [ { name: 'AddressPermissions:AllowedCalls:
', key: '0x4b80742de2bf393a64c70000
', keyType: 'MappingWithGrouping', valueType: '(bytes4,address,bytes4,bytes4)[CompactBytesArray]', valueContent: '(BitArray,Address,Bytes4,Bytes4)', } ]; ERC725.decodeData( [ { keyName: 'AddressPermissions:AllowedCalls:
', dynamicKeyParts: "0xcafecafecafecafecafecafecafecafecafecafe" value: '0x002000000003ca41e4ea94c8fa99889c8ea2c8948768cbaf4bc03e89ad98ffffffff002000000002f70ce3b58f275a4c28d06c98615760dde774de57ffffffff760d9bba002000000001d3236aa1b8a4dde5ea375fd1f2fb5c354e686c9fffffffffffffffff' }, ], schemas, ); /** { key: '0x4b80742de2bf393a64c70000cafecafecafecafecafecafecafecafecafecafe', name: 'AddressPermissions:AllowedCalls:cafecafecafecafecafecafecafecafecafecafe', value: [ [ '0x00000003', // CALL and TRANSFERVALUE '0xCA41e4ea94c8fA99889c8EA2c8948768cBaf4bc0', // addresses are decoded as checksummed '0x3e89ad98', // LSP0 interface ID '0xffffffff', // any function ], [ '0x00000002', // CALL only '0xF70Ce3b58f275A4c28d06C98615760dDe774DE57', '0xffffffff', // any standard interface ID '0x760d9bba', // function selector of `transfer(address,address,uint256,bool,bytes)` ], [ '0x00000001', // TRANSFERVALUE only '0xd3236aa1B8A4dDe5eA375fd1F2Fb5c354e686c9f', '0xffffffff', // any standard interface ID '0xffffffff', // any function ] ] } */ ``` ### decodeValueType ```js myErc725.decodeValueType(type, data); ``` ```js ERC725.decodeValueType(type, data); ``` Decode some data according to a provided value type. #### Parameters | Name | Type | Description | | :----- | :----- | :---------------------------------------------------------------------------- | | `type` | string | The value type to decode the data (i.e. `uint256`, `bool`, `bytes4`, etc...). | | `data` | string | A hex encoded string starting with `0x` to decode | #### Returns | Name | Type | Description | | :------------- | :--------------------- | :----------------------------------- | | `decodedValue` | string or
number | A value decoded according to `type`. | #### Examples ```javascript myErc725.decodeValueType('uint128', '0x0000000000000000000000000000000a'); // 10 myErc725.decodeValueType('bool', '0x01'); // true myErc725.decodeValueType('string', '0x48656c6c6f21'); // 'Hello!'; // also available for ABI encoded array + CompactBytesArray myErc725.decodeValueType( 'uint256[]', '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001e', ); // [ 10, 20, 30 ] myErc725.decodeValueType( 'uint256[CompactBytesArray]', '0x0020000000000000000000000000000000000000000000000000000000000000000500200000000000000000000000000000000000000000000000000000000000000008', ); // [ 5, 8 ] ``` This method is also available as a static method: ```js ERC725.decodeValueType( 'uint256', '0x000000000000000000000000000000000000000000000000000000000000002a', ); // 42 ``` --- ### decodeValueContent ```js const erc725js = new ERC725(); erc725js.decodeValueContent(valueContent, value); ``` OR ```js ERC725.decodeValueContent(valueContent, value); ``` OR ```js import { decodeValueContent } from '@erc725/erc725.js'; decodeValueContent(valueContent, value); ``` Decode a hex encoded value and return it as if it was interpreted as a `valueContent`. Available `valueContent` are: - `Address` (checksummed) - `AssetURL` (deprecated) - `Boolean` - `BytesN` - `JSONURL` (deprecated) - `Keccak256` - `Markdown` (similar to `String`) - `Number` - `String` - `URL` - `VerifiableURI` - Any Hex `Literal` (e.g.: 0x1345ABCD...) #### Parameters | Name | Type | Description | | :------------- | :------- | :----------------------------------------------------------------- | | `valueContent` | `string` | One of the value content options defined by the LSP2 standard. | | `value` | `string` | A hex encoded string starting with `0x` to decode as `valueContent | #### Returns | Name | Type | Description | | :------------- | :--------------------------------------------------------------------------------------- | :------------------------------------------- | | `decodedValue` | `string` or
`URLDataWithHash` or
`number` or
`boolean` or
`null` | A value decoded according to `valueContent`. | #### Examples ```javascript title="decodeValueContent example" erc725js.decodeValueContent( 'VerifiableURI', '0x00006f357c6a0020027547537d35728a741470df1ccf65de10b454ca0def7c5c20b257b7b8d16168687474703a2f2f746573742e636f6d2f61737365742e676c62', ); // { // verification: { // method: SUPPORTED_VERIFICATION_METHOD_STRINGS.KECCAK256_UTF8, // data: '0x027547537d35728a741470df1ccf65de10b454ca0def7c5c20b257b7b8d16168', // }, // url: 'http://test.com/asset.glb', // } erc725js.decodeValueContent('String', '0x232068656c6c6f'); // # hello erc725js.decodeValueContent('String', '0x68656c6c6f'); // hello // `Address` will be checksummed erc725js.decodeValueContent( 'Address', '0xa29afb8f3cce086b3992621324e9d7c104f03d1b', ); // 0xa29Afb8F3ccE086B3992621324E9d7c104F03D1B erc725js.decodeValueContent( 'Number', '0x000000000000000000000000000000000000000000000000000000000000000a', ); // 10 erc725js.decodeValueContent( 'Number', '0x000000000000000000000000000000000000000000000000000000000000036c', ); // 876 erc725js.decodeValueContent('Boolean', '0x01'); // true erc725js.decodeValueContent('Boolean', '0x00'); // false ``` --- ### decodeMappingKey ```js ERC725.decodeMappingKey(keyNameOrSchema, keyHash); ``` Decode the values of the dynamic parts of a hashed key used on an [ERC725Y contract](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y) according to the [LSP2 ERC725Y JSON Schema Standard](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md). :::info `decodeMappingKey` is available as either a static or non-static method, so it can be called without instantiating an ERC725 object. ::: #### Parameters ##### 1. `keyHash` - String The bytes32 key hash that needs to be decoded ##### 2. `keyNameOrSchema` - String or ERC725JSONSchema The key name or erc725y json schema associated to the key hash to decode, for instance: `MySuperKey:
`. #### Returns | Name | Type | Description | | :---------------- | :----------------------------------------------------- | :----------------------------------------------- | | `dynamicKeyParts` | \{type: string, value: string OR number OR boolean\}[] | The dynamic key parts decoded from the key hash. | #### Example ```javascript title="Decode the mapping key" ERC725.decodeMappingKey( '0x35e6950bc8d21a1699e50000cafecafecafecafecafecafecafecafecafecafe', 'MyKeyName:
', ); // Decoding will checksum addresses // [{ // type: 'address', // value: '0xCAfEcAfeCAfECaFeCaFecaFecaFECafECafeCaFe' // }] ERC725.decodeMappingKey( '0x35e6950bc8d21a1699e5000000000000000000000000000000000000f342d33d', 'MyKeyName:', ); // [{ type: 'uint32', value: 4081242941 }] ERC725.decodeMappingKey( '0x35e6950bc8d21a1699e5000000000000000000000000000000000000abcd1234', 'MyKeyName:', ); // [{ type: 'bytes4', value: 'abcd1234' }] ERC725.decodeMappingKey( '0x35e6950bc8d21a1699e50000aaaabbbbccccddddeeeeffff1111222233334444', 'MyKeyName:', ); // [{ // type: 'bytes32', // value: 'aaaabbbbccccddddeeeeffff1111222233334444' // }] ERC725.decodeMappingKey( '0x35e6950bc8d21a1699e500000000000000000000000000000000000000000001', 'MyKeyName:', ); // [{ type: 'bool', value: true }] ERC725.decodeMappingKey( '0x35e6950bc8d20000ffff000000000000000000000000000000000000f342d33d', 'MyKeyName::', ); // [ // { type: 'bytes2', value: 'ffff' }, // { type: 'uint32', value: 4081242941 } // ] // This method is also available on the instance: myErc725.decodeMappingKey( '0x35e6950bc8d20000ffff000000000000000000000000000000000000f342d33d', 'MyKeyName::', ); ``` --- ### getSchema ```js myErc725.getSchema(keys [, providedSchemas]); ``` Parses a hashed key or a list of hashed keys and will attempt to return its corresponding [LSP2 ERC725YJSONSchema](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md) object. Additionally, it will look for a corresponding key within the schemas: - in the [`schemas`](https://github.com/ERC725Alliance/erc725.js/tree/main/schemas) folder (which includes all [LSPs](https://github.com/lukso-network/LIPs/tree/main/LSPs)), - that were provided at ERC725 initialization, and - that were provided in the function call (`providedSchemas`). #### Parameters ##### 1. `keys` - String or array of Strings The key(s) you are trying to get the schema for. ##### 2. `providedSchemas` - Object (optional) An array of extra [LSP-2 ERC725YJSONSchema] objects that can be used to find the schema. #### Returns | Name | Type | Description | | :------- | :----------------- | :-------------------------------------------------------------------- | | `result` | `ERC725JSONSchema` | If the parameter `keys` is a string and the schema was found. | | `result` | `string[]` | If the parameter `keys` is a string[ ] and the schema was found. | | `result` | `null` | If the schema was not found. | #### Example using a predefined LSP3 schema ```javascript title="Parsing the hashed key from the LSP3 schema" myErc725.getSchema( '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', ); /** { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', keyType: 'Singleton', valueContent: 'VerifiableURI', valueType: 'bytes' } */ myErc725.getSchema([ '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', '0x3a47ab5bd3a594c3a8995f8fa58d087600000000000000000000000000000001', ]); /** { '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5': { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', keyType: 'Singleton', valueContent: 'VerifiableURI', valueType: 'bytes' }, '0x3a47ab5bd3a594c3a8995f8fa58d087600000000000000000000000000000001': { name: 'LSP12IssuedAssets[1]', key: '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', keyType: 'Singleton', valueContent: 'Address', valueType: 'address' } } */ ``` #### Example using a custom schema ```javascript title="Parsing the hashed key from a custom schema" myErc725.getSchema( '0x777f55baf2e0c9f73d3bb456dfb8dbf6e609bf557969e3184c17ff925b3c402c', [ { name: 'ParameterSchema', key: '0x777f55baf2e0c9f73d3bb456dfb8dbf6e609bf557969e3184c17ff925b3c402c', keyType: 'Singleton', valueContent: 'VerifiableURI', valueType: 'bytes', }, ], ); /** { name: 'ParameterSchema', key: '0x777f55baf2e0c9f73d3bb456dfb8dbf6e609bf557969e3184c17ff925b3c402c', keyType: 'Singleton', valueContent: 'VerifiableURI', valueType: 'bytes', } */ ``` --- ## Fetching Data ### fetchData ```js myErc725.fetchData([keys]); ``` The `fetchData` function fetches smart contract data and can additionally return [`VerifiableURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#verifiableuri) data from IPFS, HTTP, or HTTPS endpoints. :::info To ensure **data authenticity** `fetchData` compares the `hash` of the fetched JSON with the `hash` stored on the blockchain. ::: :::info If you get the `ReferenceError: fetch is not defined` error, you need to install and import [`isomorphic-fetch`](https://www.npmjs.com/package/isomorphic-fetch). ::: #### Parameters ##### 1. `keys` - String, Object, or array of Strings or/and Objects (optional) The name(s) (or the encoded name(s) as schema key) of the element(s) in the smart contract's schema. If no keys are set, it will fetch all the non-dynamic schema keys given at instantiation. For dynamic keys, you can use the object below: | Name | Type | Description | | :---------------- | :----------------------------- | :------------------------------------------------------------------------- | | `keyName` | string | The dynamic key name, such as `MyKey:
` | | `dynamicKeyParts` | string or
string[ ] | The dynamic parts of the `keyName` that will be used for encoding the key. | #### Returns | Name | Type | Description | | :--- | :------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | data | `Promise` or
`Promise` | An array with same objects as for [`decodeData()`](#decodedata) function but with the value being replaced by the actual file for `VerifiableURI` valueContent. If there is a hash mismatch, the value will be `null`. | :::info - If the input is an array, the values will be returned in an array. - If the input is a single key, the output will be the object directly. ::: #### All-Keys Example ```javascript title="Receiving all keys from the schema" import ERC725 from '@erc725/erc725.js'; import LSP3Schemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.sjon'; const universalProfileAddress = '0x0F4180da178ed1C71398a57ca8Cb177F69591f1f'; const myErc725 = new ERC725(LSP3Schemas, universalProfileAddress); await myErc725.fetchData(); /** [ { name: 'SupportedStandards:LSP3Profile', key: '0xeafec4d89fa9619884b600005ef83ad9559033e6e941db7d7c495acdce616347', value: '0x5ef83ad9' }, { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { LSP3Profile: [Object] } }, { name: 'LSP1UniversalReceiverDelegate', key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', value: '0xE2D6038acD92200790Df695Ebd13856CdF2a6942' }, { name: 'LSP12IssuedAssets[]', key: '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', value: [ '0xc444009d38d3046bb0cF81Fa2Cd295ce46A67C78', '0x4fEbC3491230571F6e1829E46602e3b110215A2E', '0xB92a8DdA288638491AEE5C2a003D4CAbfa47aE3F', '0x1e52e7F1707dcda57dD33F003B2311652A465acA', '0x0BDA71aA980D37Ea56E8a3784E4c309101DAf3E4', '0xfDB4D9C299438B9839e9d04E34B9609C5b56600D', '0x081D3F0bff8ae2339cb65113822eEc1510704d5c', '0x55C98c6944B7497FaAf4db0386a1aD1E6efF526E', '0x90D1a1D68fa23AEEE991220703f1a1C3782e0b35', '0xdB5AB19792d9fB61c1Dff57810Fb7C6f839Af8ED' ] } ] */ ``` #### Single-Key Example ```javascript title="Receiving one key from the schema" import ERC725 from '@erc725/erc725.js'; import LSP3Schemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.sjon'; const universalProfileAddress = '0x0F4180da178ed1C71398a57ca8Cb177F69591f1f'; const myErc725 = new ERC725(LSP3Schemas, universalProfileAddress); await myErc725.fetchData('LSP3Profile'); /** { key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', name: 'LSP3Profile', value: { LSP3Profile: { name: 'Test', description: 'Cool' } } } */ await myErc725.fetchData(['LSP1UniversalReceiverDelegate']); /** [ { name: 'LSP1UniversalReceiverDelegate', key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', value: '0xE2D6038acD92200790Df695Ebd13856CdF2a6942' } ] */ ``` #### Multi-Keys / Dynamic-Keys Example ```javascript title="Receiving multiple keys from the schema" import ERC725 from '@erc725/erc725.js'; import LSP3Schemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.sjon'; const universalProfileAddress = '0x0F4180da178ed1C71398a57ca8Cb177F69591f1f'; const myErc725 = new ERC725(LSP3Schemas, universalProfileAddress); await myErc725.fetchData(['LSP3Profile', 'LSP1UniversalReceiverDelegate']); /** [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { LSP3Profile: [Object] } }, { name: 'LSP1UniversalReceiverDelegate', key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', value: '0xE2D6038acD92200790Df695Ebd13856CdF2a6942' } ] */ await myErc725.fetchData([ 'LSP1UniversalReceiverDelegate', { keyName: 'LSP12IssuedAssetsMap:
', dynamicKeyParts: '0xcafecafecafecafecafecafecafecafecafecafe', }, ]); /** [ { name: 'LSP1UniversalReceiverDelegate', key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', value: '0xE2D6038acD92200790Df695Ebd13856CdF2a6942' }, { name: 'LSP12IssuedAssetsMap:cafecafecafecafecafecafecafecafecafecafe', key: '0x74ac2555c10b9349e78f0000cafecafecafecafecafecafecafecafecafecafe', value: null } ] */ ``` --- ### getData ```js myErc725.getData([keys]); ``` Gets **decoded data** for one, many, or all of the specified `ERC725` smart contract's keys. When omitting the `keys` parameter, it will give back every key (as per `ERC725JSONSchema` definition). :::caution - Data returned by this function does not contain external data of [`VerifiableURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#verifiableuri) schema elements. - If you would like to receive everything in one go, you can use [`fetchData`](#fetchdata). ::: #### Parameters ##### 1. `keys` - String, Object, or array of Strings or/and Objects (optional) The name(s) (or the encoded name(s) as schema key) of the element(s) in the smart contract's schema. If no keys are set, it will fetch all the non-dynamic schema keys given at instantiation. For dynamic keys, you can use the object below: | Name | Type | Description | | :---------------- | :----------------------------- | :------------------------------------------------------------------------- | | `keyName` | string | The dynamic key name, such as `MyKey:
` | | `dynamicKeyParts` | string or
string[ ] | The dynamic parts of the `keyName` that will be used for encoding the key. | #### Returns | Name | Type | Description | | :--- | :------------------------------------------ | :---------------------------------------------------------------------------- | | data | `Promise` or
`Promise` | An array with the same objects as for [`decodeData()`](#decodedata) function. | :::info - If the input is an array, the values will be returned in an array. - If the input is a single key, the output will be the object directly. ::: #### All-Keys Example ```javascript title="Receiving all keys from the schema" import ERC725 from '@erc725/erc725.js'; import LSP3Schemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.sjon'; const universalProfileAddress = '0x0F4180da178ed1C71398a57ca8Cb177F69591f1f'; const myErc725 = new ERC725(LSP3Schemas, universalProfileAddress); await myErc725.getData(); /** [ { name: 'SupportedStandards:LSP3Profile', key: '0xeafec4d89fa9619884b600005ef83ad9559033e6e941db7d7c495acdce616347', value: '0x5ef83ad9', }, { name: 'LSP1UniversalReceiverDelegate', key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', value: '0x50A02EF693fF6961A7F9178d1e53CC8BbE1DaD68', }, { name: 'LSP12IssuedAssets[]', key: '0x7c8c3416d6cda87cd42c71ea1843df28ac4850354f988d55ee2eaa47b6dc05cd', value: [ '0xc444009d38d3046bb0cF81Fa2Cd295ce46A67C78', '0x4fEbC3491230571F6e1829E46602e3b110215A2E', '0xB92a8DdA288638491AEE5C2a003D4CAbfa47aE3F', '0x1e52e7F1707dcda57dD33F003B2311652A465acA', '0x0BDA71aA980D37Ea56E8a3784E4c309101DAf3E4', '0xfDB4D9C299438B9839e9d04E34B9609C5b56600D', '0x081D3F0bff8ae2339cb65113822eEc1510704d5c', '0x55C98c6944B7497FaAf4db0386a1aD1E6efF526E', '0x90D1a1D68fa23AEEE991220703f1a1C3782e0b35', '0xdB5AB19792d9fB61c1Dff57810Fb7C6f839Af8ED' ], }, { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { method: 'keccak256(utf8)', data: '0x70546a2accab18748420b63c63b5af4cf710848ae83afc0c51dd8ad17fb5e8b3', }, url: 'ipfs://QmecrGejUQVXpW4zS948pNvcnQrJ1KiAoM6bdfrVcWZsn5', }, }, ] */ ``` #### Single-Key Example ```javascript title="Receiving one key from the schema" import ERC725 from '@erc725/erc725.js'; import LSP3Schemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.sjon'; const universalProfileAddress = '0x0F4180da178ed1C71398a57ca8Cb177F69591f1f'; const myErc725 = new ERC725(LSP3Schemas, universalProfileAddress); await myErc725.getData('LSP3Profile'); /** { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { method: 'keccak256(utf8)', data: '0xd96ff7776660095f661d16010c4349aa7478a9129ce0670f771596a6ff2d864a', }, url: 'ipfs://QmbTmcbp8ZW23vkQrqkasMFqNg2z1iP4e3BCUMz9PKDsSV' }, } */ await myErc725.getData(['LSP3Profile']); /** [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { method: 'keccak256(utf8)', data: '0xd96ff7776660095f661d16010c4349aa7478a9129ce0670f771596a6ff2d864a', }, url: 'ipfs://QmbTmcbp8ZW23vkQrqkasMFqNg2z1iP4e3BCUMz9PKDsSV' }, } ] */ await myErc725.getData('LSP1UniversalReceiverDelegate'); /** { name: 'LSP1UniversalReceiverDelegate', key: '0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', value: '0x50A02EF693fF6961A7F9178d1e53CC8BbE1DaD68', } */ ``` #### Multi-Key Example ```javascript title="Receiving multiple keys from the schema" import ERC725 from '@erc725/erc725.js'; import LSP3Schemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.sjon'; const universalProfileAddress = '0x0F4180da178ed1C71398a57ca8Cb177F69591f1f'; const myErc725 = new ERC725(LSP3Schemas, universalProfileAddress); await myErc725.getData(['LSP3Profile', 'LSP1UniversalReceiverDelegate']); /** [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { method: 'keccak256(utf8)', data: '0xeeafeebeb416923dfb0dcf4c66b045c72742121ce2a06f93ae044ee0efb70777', }, url: 'ipfs://QmZnG5Z5B5Dq8iFFtsL5i7AnrgH16P4DJ8UhY7j8RzX51p' } }, { name: 'LSP1UniversalReceiverDelegate', key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47', value: '0xE2D6038acD92200790Df695Ebd13856CdF2a6942' } ] */ ``` #### Dynamic-Key Example ```javascript title="Receiving dynamic keys from the schema" import ERC725 from '@erc725/erc725.js'; import LSP3Schemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.sjon'; const luksoUniversalProfile = '0x8363Cfe6c787218f0ADA0A4aBC289A8d9dfc2453'; const myErc725 = new ERC725(LSP3Schemas, luksoUniversalProfile); await myErc725.getData({ keyName: 'LSP12IssuedAssetsMap:
', dynamicKeyParts: '0x592dCACb0A0d4b85eea0975992E42Bc543207F74', // asset address (KidSuper World Arts Path) }); /** { name: 'LSP12IssuedAssetsMap:592dCACb0A0d4b85eea0975992E42Bc543207F74', key: '0x74ac2555c10b9349e78f0000592dCACb0A0d4b85eea0975992E42Bc543207F74', value: '0x6b175474e89094c44da98b954eedeac495271d0f', } */ await myErc725.getData([ { keyName: 'LSP12IssuedAssetsMap:
', dynamicKeyParts: '0xcafecafecafecafecafecafecafecafecafecafe', }, ]); /** [ { name: 'LSP12IssuedAssetsMap:cafecafecafecafecafecafecafecafecafecafe', key: '0x74ac2555c10b9349e78f0000cafecafecafecafecafecafecafecafecafecafe', value: '0x6b175474e89094c44da98b954eedeac495271d0f', } ] */ ``` ```javascript title="Receiving dynamic keys from the schema" await myErc725.getData([ 'LSP3Profile', { keyName: 'LSP12IssuedAssetsMap:
', dynamicKeyParts: '0xcafecafecafecafecafecafecafecafecafecafe', }, ]); /** [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { method: 'keccak256(utf8)', data: '0xeeafeebeb416923dfb0dcf4c66b045c72742121ce2a06f93ae044ee0efb70777', }, url: 'ipfs://QmZnG5Z5B5Dq8iFFtsL5i7AnrgH16P4DJ8UhY7j8RzX51p' } }, { name: 'LSP12IssuedAssetsMap:cafecafecafecafecafecafecafecafecafecafe', key: '0x74ac2555c10b9349e78f0000cafecafecafecafecafecafecafecafecafecafe', value: null } ] */ ``` --- ### getOwner ```js myErc725.getOwner([address]); ``` Returns the contract owner and is not directly related to ERC725 specifications. #### Parameters ##### 1. `address` - String (optional) The contract address you wish to find the owner of. If no address is set, it will return the owner of the contract used to initialize the ERC725 class. #### Returns | Name | Type | Description | | :-------- | :----- | :---------------------------------------- | | `Promise` | string | The contract or EOA address of the owner. | :::info The address of the contract owner as stored in the contract. ::: #### Example ```javascript title="Receiving the owner address" // If no address is set, it will return the owner of the contract used to initialize the ERC725() class. await myErc725.getOwner(); // '0x94933413384997F9402cc07a650e8A34d60F437A' // You can also get the owner of a specific contract by setting the address parameter await myErc725.getOwner('0x3000783905Cc7170cCCe49a4112Deda952DDBe24'); // '0x7f1b797b2Ba023Da2482654b50724e92EB5a7091' ``` --- ### isValidSignature ```js myErc725.isValidSignature(messageOrHash, signature); ``` Checks if a signature was signed by the `owner` of the ERC725 Account contract, according to [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271). If the `owner` is a contract itself, it will delegate the `isValidsignature()` call to the owner contract if it supports [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271). Otherwise, it will fail. #### Parameters ##### 1. `messageOrHash` - String Value of a message or hash that needs to be verified. ##### 2. `signature` - String The raw RLP encoded signature. :::info - The hash must be 66 chars long with the `0x` prefix. Otherwise, it will be interpreted as message. - The message will be: enveloped as `"\x19Ethereum Signed Message:\n" + message.length + message` and hashed using `keccak256` function. The signature can be generated with [`web3.eth.accounts.sign()`](https://web3js.readthedocs.io/en/v1.2.11/web3-eth-accounts.html#sign). ::: #### Returns | Name | Type | Description | | :-------- | :------ | :------------------------------------------------------------- | | `Promise` | boolean | `true` if signature is valid, `false` if signature is invalid. | :::info - A valid signature means that the smart contract response IS the MAGICVALUE: `0x1626ba7e`. - If this function is called on a contract which does not support [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271), it will throw an error. ::: #### Examples ```javascript title="Checking the signature with a message" await myErc725.isValidSignature( 'hello', '0xb91467e570a6466aa9e9876cbcd013baba02900b8979d43fe208a4a4f339f5fd6007e74cd82e037b800186422fc2da167c747ef045e5d18a5f5d4300f8e1a0291c', ); // true ``` ```javascript title="Checking the signature with a hash" await myErc725.isValidSignature( '0x1da44b586eb0729ff70a73c326926f6ed5a25f5b056e7f47fbc6e58d86871655', '0xcafecafeb915466aa9e9876cbcd013baba02900b8979d43fe208a4a4f339f5fd6007e74cd82e037b800186422fc2da167c747ef045e5d18a5f5d4300f8e1a0291c', ); // false ``` [lsp6 keymanager permissions]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager/#permissions [lsp6 keymanager standard]: https://docs.lukso.tech/standards/access-control/lsp6-key-manager/ [lsp-2 erc725yjsonschema]: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md ### supportsInterface ```js myERC725.supportsInterface(interfaceIdOrName); ``` ```js ERC725.supportsInterface(interfaceIdOrName, options); ``` You can use this function if you need to check if the ERC725 object or a smart contract supports a specific interface (by ID or name). When you use the function on your instantiated ERC725 class, it will use the contract address and provider provided at instantiation. On a non-instantiated class, you need to specify them in the `options` parameter. :::caution The `interfaceId` is not the most secure way to check for a standard, as they could be set manually. ::: #### Parameters ##### 1. `interfaceIdOrName` - String Either a string of the hexadecimal `interfaceID` as defined by [ERC165](https://eips.ethereum.org/EIPS/eip-165) or one of the predefined interface names: | interfaceName | Standard | | :------------------------------ | :----------------------------------------------------------------------------------------------------------------- | | `ERC1271` | [EIP-1271: Standard Signature Validation Method for Contracts](https://eips.ethereum.org/EIPS/eip-1271) | | `ERC725X` | [EIP-725: General execution standard](https://eips.ethereum.org/EIPS/eip-725) | | `ERC725Y` | [EIP-725: General key-value store](https://eips.ethereum.org/EIPS/eip-725) | | `LSP0ERC725Account` | [LSP-0: ERC725 Account](https://docs.lukso.tech/standards/accounts/lsp0-erc725account/) | | `LSP1UniversalReceiver` | [LSP-1: Universal Receiver](https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver/) | | `LSP1UniversalReceiverDelegate` | [LSP-1: Universal Receiver Delegate](https://docs.lukso.tech/standards/accounts/lsp1-universal-receiver-delegate/) | | `LSP6KeyManager` | [LSP-6: Key Manager](https://docs.lukso.tech/standards/access-control/lsp6-key-manager/) | | `LSP7DigitalAsset` | [LSP-7: Digital Asset](https://docs.lukso.tech/standards/tokens/LSP7-Digital-Asset/) | | `LSP8IdentifiableDigitalAsset` | [LSP-8: Identifiable Digital Asset](https://docs.lukso.tech/standards/tokens/LSP8-Identifiable-Digital-Asset/) | | `LSP9Vault` | [LSP-9: Vault](https://docs.lukso.tech/standards/accounts/lsp9-vault/) | :::info The `interfaceName` will only check for the latest version of the standard's `interfaceID`, which can be found in `src/constants/interfaces`. For LSPs, the `interfaceIDs` are taken from the latest release of the [@lukso/lsp-smart-contracts](https://github.com/lukso-network/lsp-smart-contracts) library. ::: ##### 2. `options` - Object (optional) On non instantiated class, you should provide an `options` object. | Name | Type | Description | | :-------- | :----- | :------------------------------------------------------------------- | | `address` | string | Address of the smart contract to check against a certain interface. | | `rpcUrl` | string | RPC URL to connect to the network the smart contract is deployed to. | | `gas` | number | Optional: gas parameter to use. Default: 1_000_000. | #### Returns | Type | Description | | :----------------- | :------------------------------------------------------------ | | `Promise` | Returns `true` if the interface was found, otherwise `false`. | #### Examples ```javascript title="By using the interface ID" myErc725.supportsInterface('0xfd4d5c50'); // true ERC725.supportsInterface('0xfd4d5c50', { address: '0xe408BDDbBAB1985006A2c481700DD473F932e5cB', rpcUrl: 'https://rpc.testnet.lukso.network', }); // false ``` ```javascript title="By using interface name" myErc725.supportsInterface('LSP0ERC725Account'); // false ERC725.supportsInterface('LSP0ERC725Account', { address: '0x0Dc07C77985fE31996Ed612F568eb441afe5768D', rpcUrl: 'https://rpc.testnet.lukso.network', gas: 20_000_000, }); // true ``` --- ## External Data Source utilities (`VerifiableURI` and `JSONURI`) ### encodeDataSourceWithHash ```js const myErc725 = new ERC725(); myErc725.encodeDataSourceWithHash(verification, dataSource); ``` OR ```js ERC725.encodeDataSourceWithHash(verification, dataSource); ``` Encode a verifiableURI providing the hashing function of the json file (method), the hash of the json file (data) and the url where the json file is stored. #### Parameters | Name | Type | Description | | :------------- | :---------------------------- | :----------------------------------------------------------------------------------------------------------------------- | | `verification` | `undefined` or `Verification` | Verification is an object containing the hashing function of the json file (method) and the hash of the json file (data) | | `dataSource` | `string` | The url where the json file is stored. |
Types details ```js interface Verification { method: SUPPORTED_VERIFICATION_METHODS | string; data: string; source?: string; } type SUPPORTED_VERIFICATION_METHODS = | SUPPORTED_VERIFICATION_METHOD_STRINGS | SUPPORTED_VERIFICATION_METHOD_HASHES; enum SUPPORTED_VERIFICATION_METHOD_STRINGS { KECCAK256_UTF8 = 'keccak256(utf8)', KECCAK256_BYTES = 'keccak256(bytes)', } enum SUPPORTED_VERIFICATION_METHOD_HASHES { HASH_KECCAK256_UTF8 = '0x6f357c6a', HASH_KECCAK256_BYTES = '0x8019f9b1', } ```
#### Returns | Name | Type | Description | | :-------------- | :----- | :---------------- | | `verifiableURI` | string | The verifiableURI | #### Examples
Encode a VerifiableURI providing the hashing function, the JSON hash and the uploaded URL ```javascript title="Encode a VerifiableURI providing the hashing function, the JSON hash and the uploaded URL" const verifiableURI = myErc725.encodeDataSourceWithHash( { method: 'keccak256(utf8)', data: '0x820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361', }, 'ifps://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx', ); /** 0x00006f357c6a0020820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455a4c6a7452504466573834554178 */ ```
### decodeDataSourceWithHash ```js const myErc725 = new ERC725(); myErc725.decodeDataSourceWithHash(verifiableURI); ``` ```js ERC725.decodeDataSourceWithHash(verifiableURI); ``` Decode a verifiableURI into the hash function of the json file, the hash of the json file and the url where the json file is stored. #### Parameters | Name | Type | Description | | :-------------- | :------- | :---------------- | | `verifiableURI` | `string` | The verifiableURI | #### Returns | Name | Type | Description | | :--------------------- | :---------------- | :--------------------------------------------------------------------------------------------------------- | | `decodedVerifiableURI` | `URLDataWithHash` | Object containing the hash function, the hash of the JSON file and the link where the json file is stored. |
Types details ```js interface URLDataWithHash { verification: Verification; url: string } interface Verification { method: SUPPORTED_VERIFICATION_METHODS | string; data: string; source?: string; } type SUPPORTED_VERIFICATION_METHODS = | SUPPORTED_VERIFICATION_METHOD_STRINGS | SUPPORTED_VERIFICATION_METHOD_HASHES; enum SUPPORTED_VERIFICATION_METHOD_STRINGS { KECCAK256_UTF8 = 'keccak256(utf8)', KECCAK256_BYTES = 'keccak256(bytes)', } enum SUPPORTED_VERIFICATION_METHOD_HASHES { HASH_KECCAK256_UTF8 = '0x6f357c6a', HASH_KECCAK256_BYTES = '0x8019f9b1', } ```
#### Examples
Decode a VerifiableURI ```javascript title="Decode a VerifiableURI" const decodedVerifiableURI = myErc725.decodeDataSourceWithHash( '0x00006f357c6a0020820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361696670733a2f2f516d597231564a4c776572673670456f73636468564775676f3339706136727963455a4c6a7452504466573834554178', ); /** verification: { data: '820464ddfac1bec070cc14a8daf04129871d458f2ca94368aae8391311af6361', method: 'keccak256(utf8)', } url: 'ifps://QmYr1VJLwerg6pEoscdhVGugo39pa6rycEZLjtRPDfW84UAx' */ ```
### getDataFromExternalSources ```js getDataFromExternalSources(schema, dataFromChain, ipfsGateway, [ (throwException = true), ]); ``` Retrieve the data stored on IPFS using one (or multiple) IPFS CID(s) and link(s) under the `dataFromChain` parameter. #### Parameters | Name | Type | Description | | :-------------------------- | :------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | | `schema` | `ERC725JSONSchema[]` | A list of JSON schemas for some given data keys. | | `dataFromChain` | `DecodeDataOutput[]` | A list of data output previously fetched from the ERC725Y contract via [`getData(...)](#getdata) or [`fetchData`](#fetchdata) | | `ipfsGateway` | `string` | The URL to use to fetch data from the IPFS network. | | `throwException` (optional) | `boolean` | Define if the function should throw an error when fetching data. Set to `true` by default. This is useful for handling exceptions differently. |
Types details ```js interface ERC725JSONSchema { name: string; // Describes the name of the key, SHOULD be composed of the Standards name + sub type. e.g: LSP2Name key: string; // The keccak256 hash of the name. This is the actual key that MUST be retrievable via ERC725Y.getData(bytes32 key) keyType: ERC725JSONSchemaKeyType | string; // Types that determine how the values should be interpreted. valueContent: ERC725JSONSchemaValueContent | string; // string holds '0x1345ABCD...' If the value content are specific bytes, than the returned value is expected to equal those bytes. valueType: ERC725JSONSchemaValueType | string; // The type of the value. This is used to determine how the value should be encoded / decode (`string` for tuples and CompactBytesArray). } interface DecodeDataOutput { value: Data | Data[] | URLDataWithHash | null; name: string; key: string; } type Data = string | number | boolean | null; interface URLDataWithHash extends URLData { verification: Verification; // | string is to allow use of string directly without importing the enum json?: never; } interface URLData { url: string; } interface GetDataExternalSourcesOutput extends DecodeDataOutput { value: any; } ```
#### Returns | Name | Type | Description | | :--- | :------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | | `GetDataExternalSourcesOutput[]` (see above) | An array of objects that contain the result of the data fetch inside the `.value` property. Can be anything from a `string` to a JSON object. | #### Examples ```javascript import { getDataFromExternalSources } from '@erc725/erc725.js'; const schema = [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', keyType: 'Singleton', valueType: 'bytes', valueContent: 'VerifiableURI', }, ]; const dataFromChain = [ { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { data: '0xdb864ed42104cee179785036cb4ff1183ebc57e5532ae766ad8533fa48acfbb3', method: 'keccak256(utf8)', }, url: 'ipfs://QmdMGUxuQsm1U9Qs8oJSn5PfY4B1apGG75YBRxQPybtRVm', }, }, ]; const ipfsGateway = 'https://my-ipfs-gateway.com/ipfs/'; await getDataFromExternalSources(schema, dataFromChain, ipfsGateway); /** { name: 'LSP3Profile', key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { LSP3Profile: { name: 'test', description: '', tags: ['profile'], links: [], profileImage: [ { width: 1024, height: 709, verification: { method: 'keccak256(bytes)', data: '0x6a0a28680d65b69f5696859be7e0fcebbbcf0df47f1f767926de35402c7d525c', }, url: 'ipfs://QmVUYyft3j2JVrG4RzDe1Qx7K5gNtJGFhrExHQFeiRXz1C', }, // more images... ], backgroundImage: [ { width: 1800, height: 1012, verification: { method: 'keccak256(bytes)', data: '0x3f6be73b35d348fb8f0b87a47d8c8b6b9db8858ee044cb13734cdfe5d28031d8', }, url: 'ipfs://QmfLCPmL31f31RRB4R7yoTg3Hsk5PjrWyS3ZaaYyhRPT4n', }, // more images... ], }, }, }, ]); }); */ ``` --- ### getVerificationMethod ```js const myErc725 = new ERC725(); myErc725.getVerificationMethod(nameOrSig); ``` ```js ERC725.getVerificationMethod(nameOrSig); ``` ```js import { getVerificationMethod } from '@erc725/erc725.js'; getVerificationMethod(nameOrSig); ``` Get the verification method definition, including the name, signature and related method. #### Parameters | Name | Type | Description | | :---------- | :----- | :------------------------------------------ | | `nameOrSig` | string | The 4 bytes hex of the verification method. | #### Returns | Name | Type | Description | | :--- | :----- | :-------------------------------------------------------------------------------------- | | | object | An object containing the name, signature and method related to the verification method. | #### Example ```javascript title="Example of the method" getVerificationMethod('0x6f357c6a'); /* { method: [Function: keccak256Method], name: 'keccak256(utf8)', sig: '0x6f357c6a' } */ ``` ### isDataAuthentic ```js const myErc725 = new ERC725(); ERC725.isDataAuthentic(data, verificationOptions); ``` ```js ERC725.isDataAuthentic(data, verificationOptions); ``` ```js import { isDataAuthentic } from '@erc725/erc725.js'; isDataAuthentic(data, verificationOptions); ``` Hashes the `data` passed as parameter using the specified hashing functions (available under `method` in the `verificationOption` object) and compares the result with the provided hash. :::info This method will console an error if the hash provided as `data` and the expected hash obtained using the verification method do not match. ::: #### Parameters | Name | Type | Description | | :-------------------- | :----------------------- | :---------------------------------- | | `data` | `string` or `Uint8Array` | The data to be hashed and verified. | | `verificationOptions` | `Verification` | An object as defined below |
Types details ```js KECCAK256_UTF8 = , KECCAK256_BYTES = , HASH_KECCAK256_UTF8 = , HASH_KECCAK256_BYTES = , export interface Verification { data: string; method: 'keccak256(utf8)' | 'keccak256(bytes)' | '0x6f357c6a' | '0x8019f9b1' | string; source?: string; } ```
#### Returns | Name | Type | Description | | :--- | :-------- | :-------------------------------------------------------------------------------------------- | | | `boolean` | `true` if the data is authentic according to the verification method used, `false` otherwise. | #### Example
JSON data to verify from data.json ```json [ { "name": "LSP3Profile", "key": "0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5", "value": { "LSP3Profile": { "name": "test", "description": "", "tags": ["profile"], "links": [], "profileImage": [ { "width": 1024, "height": 709, "verification": { "method": "keccak256(bytes)", "data": "0x6a0a28680d65b69f5696859be7e0fcebbbcf0df47f1f767926de35402c7d525c" }, "url": "ipfs://QmVUYyft3j2JVrG4RzDe1Qx7K5gNtJGFhrExHQFeiRXz1C" }, { "width": 640, "height": 443, "verification": { "method": "keccak256(bytes)", "data": "0x7cd399f2a2552aa5cd21b1584a98db3efa39c701c311c38a60c680343cfa6d82" }, "url": "ipfs://QmeU8FUZC9F1qMYmcWyBhfGqaf7g3kLzGb4xBpoCfyVLZW" }, { "width": 320, "height": 221, "verification": { "method": "keccak256(bytes)", "data": "0x272d2e57ae1710ac7c5e3d1c9f9d24f48954ad43d0e821f8bd041a4734e309a5" }, "url": "ipfs://QmdViKPWYhZv7u86z7HBTgAkTAwEkNSRi1VkYEU8K5yUsH" }, { "width": 180, "height": 124, "verification": { "method": "keccak256(bytes)", "data": "0x1a464ff7e0eff05da98ed309a25195d8666b6211a5dfa2214865c3fd50ead810" }, "url": "ipfs://QmXZUCW6MqCNfYJEFsi54Vkj6PRrUoiPjzTuA2mWtas3RJ" } ], "backgroundImage": [ { "width": 1800, "height": 1012, "verification": { "method": "keccak256(bytes)", "data": "0x3f6be73b35d348fb8f0b87a47d8c8b6b9db8858ee044cb13734cdfe5d28031d8" }, "url": "ipfs://QmfLCPmL31f31RRB4R7yoTg3Hsk5PjrWyS3ZaaYyhRPT4n" }, { "width": 1024, "height": 576, "verification": { "method": "keccak256(bytes)", "data": "0xcb57ed802bcd7dc4964395a609b3a0f557c5f46a602b28b058b9587bb77bb54f" }, "url": "ipfs://QmPoPEaoGNVYhiMTwBWp6XzLPRXyuLjZWnuMobdCbfqsU9" }, { "width": 640, "height": 360, "verification": { "method": "keccak256(bytes)", "data": "0x57e8039288c3e1a7f891c839e03805984ab36524b710656f072492c1c8ebd967" }, "url": "ipfs://QmU3pDA4eDNPMeARsJXxKaZsMC5MgFLgzGQccnydbU9WLV" }, { "width": 320, "height": 180, "verification": { "method": "keccak256(bytes)", "data": "0x2bebf9baac33d719bbd3b481b1af468701409ad7578f84be04e8f7563d5a1509" }, "url": "ipfs://QmcKtenPsRvrqZJQ1gLCdUFkex4i9DGp7RFvucb9nbkzsz" }, { "width": 180, "height": 101, "verification": { "method": "keccak256(bytes)", "data": "0xe32154c03c892d7c41c91220b8757ec5b7847eb2dd91413f7238b0c25f55b475" }, "url": "ipfs://QmU7ueJ467E9HRahaqQmSPhvkTkMhCLXRxV45P4kmMk6vm" } ] } } } ] ```
```typescript title="isDataAuthentic example" import jsonData from './data.json'; isDataAuthentic(jsonData, { data: '0xdb864ed42104cee179785036cb4ff1183ebc57e5532ae766ad8533fa48acfbb3', method: 'keccak256(utf8)', }); // true isDataAuthentic(jsonData, { data: '0xdeadbeef00000000000000000000000000000000000000000000000000000000', method: 'keccak256(utf8)', }); // false ``` --- ## Permissions ### checkPermissions ```js myErc725.checkPermissions(requiredPermissions, grantedPermissions); ``` ```js ERC725.checkPermissions(requiredPermissions, grantedPermissions); ``` Check if the required permissions are included in the granted permissions as defined by the [LSP6 KeyManager Standard](https://docs.lukso.tech/standards/access-control/lsp6-key-manager/). :::info `checkPermissions` is available as either a static or non-static method, so it can be called without instantiating an ERC725 object. ::: #### Parameters ##### 1. `requiredPermissions` - String[] | String An array of required permissions or a single required permission. (32bytes hex or the official name of the permission). ##### 2. `grantedPermissions` - String The granted permissions. (32bytes hex). #### Returns | Type | Description | | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------- | | boolean | A boolean value indicating whether the required permissions are included in the granted permissions as defined by the [LSP6 KeyManager Standard] | #### Permission-Name Example ```javascript title="Checking permissions by name" const requiredPermissions = 'CHANGEOWNER'; const grantedPermissions = '0x000000000000000000000000000000000000000000000000000000000000ff51'; ERC725.checkPermissions(requiredPermissions, grantedPermissions); // true // This method is also available on the instance: const requiredPermissions = ['CHANGEOWNER', 'CALL']; const grantedPermissions = '0x0000000000000000000000000000000000000000000000000000000000000051'; myErc725.checkPermissions(requiredPermissions, grantedPermissions); // false ``` #### 32bytes hex Example ```javascript title="Checking permissions by 32bytes hex" const requiredPermissions = [ '0x0000000000000000000000000000000000000000000000000000000000000001', '0x0000000000000000000000000000000000000000000000000000000000000800', ]; const grantedPermissions = '0x0000000000000000000000000000000000000000000000000000000000000051'; ERC725.checkPermissions(requiredPermissions, grantedPermissions); // false // This method is also available on the instance: const requiredPermissions = '0x0000000000000000000000000000000000000000000000000000000000000001'; const grantedPermissions = '0x0000000000000000000000000000000000000000000000000000000000000051'; myErc725.checkPermissions(requiredPermissions, grantedPermissions); // true ``` --- ### encodePermissions ```js ERC725.encodePermissions(permissions); ``` Encodes permissions into a hexadecimal string as defined by the [LSP6 KeyManager Standard](https://docs.lukso.tech/standards/access-control/lsp6-key-manager/). :::info `encodePermissions` is available as either a static or non-static method, so it can be called without instantiating an ERC725 object. ::: #### Parameters ##### 1. `permissions` - Object An object with [LSP6 KeyManager Permissions] as keys and a `boolean` as value. Any omitted permissions will default to `false`. #### Returns | Type | Description | | :----- | :---------------------------------------------------------------------------------------- | | string | The permissions encoded as a hexadecimal string defined by the [LSP6 KeyManager Standard] | #### Example ```javascript title="Encoding permissions" ERC725.encodePermissions({ CHANGEOWNER: false, ADDCONTROLLER: false, EDITPERMISSIONS: false, ADDEXTENSIONS: false, CHANGEEXTENSIONS: true, ADDUNIVERSALRECEIVERDELEGATE: false, CHANGEUNIVERSALRECEIVERDELEGATE: false, REENTRANCY: false, SUPER_TRANSFERVALUE: true, TRANSFERVALUE: true, SUPER_CALL: false, CALL: true, SUPER_STATICCALL: false, STATICCALL: false, SUPER_DELEGATECALL: false, DELEGATECALL: false, DEPLOY: false, SUPER_SETDATA: false, SETDATA: false, ENCRYPT: false, DECRYPT: false, SIGN: false, EXECUTE_RELAY_CALL: false, ERC4337_PERMISSION: false }), // '0x0000000000000000000000000000000000000000000000000000000000000110' // Any omitted Permissions will default to false ERC725.encodePermissions({ ADDCONTROLLER: true, ADDEXTENSIONS: true, }), // '0x000000000000000000000000000000000000000000000000000000000000000a' ERC725.encodePermissions({ EDITPERMISSIONS: true, CHANGEEXTENSIONS: true, CHANGEUNIVERSALRECEIVERDELEGATE: true, SETDATA: true, }), // '0x0000000000000000000000000000000000000000000000000000000000040054' // This method is also available on the instance: myErc725.encodePermissions({ EDITPERMISSIONS: true, SETDATA: true, }), ``` --- ### decodePermissions ```js ERC725.decodePermissions(permission); ``` Decodes permissions from hexadecimal defined by the [LSP6 KeyManager Standard](https://docs.lukso.tech/standards/access-control/lsp6-key-manager/). :::info `decodePermissions` is available as either a static or non-static method, so it can be called without instantiating an ERC725 object. ::: #### Parameters ##### 1. `permission` - String The encoded permission (32bytes hex). #### Returns | Name | Type | Description | | :------------------- | :----- | :------------------------------------------------------------------------------------------------- | | `decodedPermissions` | Object | An object specifying whether default LSP6 permissions are included in provided hexadecimal string. | #### Example ```javascript title="Decoding permissions" ERC725.decodePermissions('0x0000000000000000000000000000000000000000000000000000000000000110'), /** { CHANGEOWNER: false, EDITPERMISSIONS: false, ADDCONTROLLER: false, SETDATA: false, CALL: true, STATICCALL: false, DELEGATECALL: false, DEPLOY: false, TRANSFERVALUE: true, SIGN: false, } */ ERC725.decodePermissions('0x000000000000000000000000000000000000000000000000000000000000000a'), /** { CHANGEOWNER: false, EDITPERMISSIONS: true, ADDCONTROLLER: false, SETDATA: true, CALL: false, STATICCALL: false, DELEGATECALL: false, DEPLOY: false, TRANSFERVALUE: false, SIGN: false, } */ // This method is also available on the instance: myErc725.decodePermissions('0x0000000000000000000000000000000000000000000000000000000000000110'), ``` --- ### mapPermission ```js const erc725 = new ERC725(); erc725.mapPermission(permissionName); ``` ```js ERC725.mapPermission(permissionName); ``` ```js import { mapPermission } from '@erc725/erc725.js'; mapPermission(permissionName); ``` /\*\* Return the bytes32 representation of an LSP6 permission from its name. :::tip When using the `mapPermission` method, if the permission is not known, the function will return `null`. ::: #### Parameters | Name | Type | Description | | :--------------- | :------- | :------------------------------------------------------------------------------------------------ | | `permissionName` | `string` | The name of the permission to return the associated `bytes32` value (\_e.g: `SETDATA`, `DEPLOY`). | #### Returns | Name | Type | Description | | :--- | :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | | `string` or `null` | A bytes32 hex string representing the `permissionName`. Or `null` if the input is not a known permission name or a valid 32-byte hex string. | ### Example ```javascript title="mapPermission example" erc725js.mapPermissions('CHANGEOWNER'); // 0x0000000000000000000000000000000000000000000000000000000000000001 erc725js.mapPermissions('SETDATA'); // 0x0000000000000000000000000000000000000000000000000000000000040000 erc725js.mapPermissions('DEPLOY'); // 0x0000000000000000000000000000000000000000000000000000000000010000 ``` --- --- sidebar_position: 3 --- # Providers The provider by which `@erc725/erc725.js` will request blockchain data is set on the instantiation of the class through the configuration object. The following provider types are supported: ## RPC URL An RPC URL can be passed when instantiating the `ERC725` class. ```javascript import ERC725 from '@erc725/erc725.js'; const RPC_URL = 'https://rpc.testnet.lukso.network'; const erc725 = new ERC725([], '0x...', RPC_URL); ``` ## Ethereum (injected provider from extension) ```javascript import ERC725 from '@erc725/erc725.js'; const ethereumProvider = window.ethereum; const erc725 = new ERC725([], '0x...', ethereumProvider); ``` ## Web3 (deprecated) The following code snippet will use the web3 provider available at `web3.providers` from the corresponding `web3` library. :::caution Warning Web3.js providers are being deprecated. Please provide an RPC URL or injected Ethereum provider instead. ::: The following code snippet will use the web3 provider available at web3.providers from the corresponding `web3` library. ```javascript import Web3 from 'web3'; import ERC725 from '@erc725/erc725.js'; const web3provider = new Web3( new Web3.providers.HttpProvider('https://rpc.testnet.lukso.network'), ); const erc725 = new ERC725([], '0x...', web3provider); ``` --- --- sidebar_position: 2 --- # Schemas :::info 📄 Schema Specification For more details on schemas, see the [**official specification** of the LSP2 ERC725 JSON schemas](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md) standard specification ::: The ⚒️ [erc725.js](https://npmjs.com/package/@erc725/erc725.js) library works with [ERC725Y JSON schemas](/standards/metadata/lsp2-json-schema.md). These schemas are JSON structures that tell developers and programs how to decode and encode 🗂️ [ERC725Y data keys](/standards/erc725#erc725y-generic-data-keyvalue-store) from any [ERC725Y](https://eips.ethereum.org/EIPS/eip-725) smart contract.. You need to load the required schemas of the data keys you want to fetch when initializing the `ERC725` class. The most common and standard schemas are [available](https://docs.lukso.tech/tools/dapps/erc725js/schemas) directly within the _erc725.js_ library. But you can also create and load your own ERC725Y JSON schemas if you want to use custom data keys. _A quick reference for keys used in schema definitions can be seen below_ - `name`: An arbitrary name - `key`: The sha3 hash of the name - `keyType`: One of the supported erc725 keyTypes - `valueType`: The type of the content data in store for decoding - `valueContent`: The described content type for parsing ## Standard LSP Schemas The most common schemas of [LUKSO Standard Proposals](https://github.com/lukso-network/LIPs/tree/main/LSPs) are available to import. These are typed automatically with the Typescript type `ERC725JSONSchema[]` for when instantiating `new ERC725(...)` from Typescript projects. ```ts import { LSP1Schema, LSP3Schema, LSP4Schema, LSP4LegacySchema, LSP5Schema, LSP6Schema, LSP8Schema, LSP9Schema, LSP10Schema, LSP12Schema, LSP17Schema, } from '@erc725/erc725.js/schemas'; const erc725js = new ERC725(LSP12Schema); ``` The raw JSON schemas are also available for import from the [`schemas/`](https://github.com/ERC725Alliance/erc725.js/tree/develop/schemas) folder. Current provided LSPs JSON schemas are: ``` LSP1UniversalReceiverDelegate.json LSP3ProfileMetadata.json LSP4DigitalAssetLegacy.json LSP4DigitalAsset.json LSP5ReceivedAssets.json LSP6KeyManager.json LSP8IdentifiableDigitalAsset.json LSP9Vault.json LSP10ReceivedVaults.json LSP12IssuedAssets.json LSP17ContractExtension.json ``` You can import the raw JSON as follow: ```js import LSP3 from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json'; import LSP5 from '@erc725/erc725.js/schemas/LSP5ReceivedAssets.json'; // ... // Later use them on instantiation const myErc725Contract = new ERC725js(LSP3, address, web3.currentProvider); // You can retrieve the current loaded schema via myErc725Contract.options.schemas; ``` --- --- sidebar_position: 1.1 --- # Getting Started :::warning Deprecation notice This package is deprecated. Please check the following guides and library: - [Deploying Universal Profiles with LSP23 Factory](/learn/universal-profile/advanced-guides/deploy-up-with-lsp23/) - [Deploying tokens and NFTs](/learn/digital-assets/getting-started) - [`lsp-utils`](../lsp-utils/getting-started.md) library to easily set profile and asset metadata ::: --- --- sidebar_position: 9 --- ### validateIpfsUrl ▸ **validateIpfsUrl**(`url`, `ipfsGateway?`): `string` Returns a valid URL. If it is an IPFS URL (E.g. `ipfs://{hash}`), the IPFS Gateway will be used to generate a valid link. Otherwise the link is returned. #### Parameters | Name | Type | Description | | :------------- | :------- | :----------------------------------------- | | `url` | `string` | The URL that is to be validated. | | `ipfsGateway?` | `string` | The IPFS Gateway to be used for IPFS URLs. | #### Returns `string` **`Since`** v0.0.1 **`Example`** ```ts validateIpfsUrl('ipfs://{hash}') => 'https://2eff.lukso.dev/ipfs/{hash}' validateIpfsUrl('https://google.com/something') => 'https://google.com/something' validateIpfsUrl('') => '' ``` #### Defined in [IPFS/validateIpfsUrl/validateIpfsUrl.ts:17](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/IPFS/validateIpfsUrl/validateIpfsUrl.ts#L17) --- --- sidebar_position: 7 --- ### addIssuedAssets ▸ **addIssuedAssets**(`issuer`, `newIssuedAssets`, `signer?`): `Promise`\<`void`\> Add LSP12 Issued Assets to a issuer contract that supports ERC725Y. #### Parameters | Name | Type | Description | | :---------------- | :----------------------- | :------------------------------------------------------------------------------------------- | | `issuer` | `BytesLike` \| `ERC725Y` | - | | `newIssuedAssets` | `DigitalAsset`[] | An array of issued assets which specifies the address and interface id of each issued asset. | | `signer?` | `Signer` \| `Wallet` | The signer that will send the transaction. | #### Returns `Promise`\<`void`\> **`Since`** v0.0.2 **`Throws`** - When `newIssuedAssets` is an empty array. - When `issuerAddress` is not a valid address. - When the contract deployed at `issuerAddress` address does not support the `ERC725Y` interface id. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-12-IssuedAssets.md #### Defined in [LSP12IssuedAssets/addIssuedAssets/addIssuedAssets.ts:32](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP12IssuedAssets/addIssuedAssets/addIssuedAssets.ts#L32) --- ### authenticateIssuedAssets ▸ **authenticateIssuedAssets**(`issuer`, `provider?`): `Promise`\<`IssuerAssets`\> Get the authenticated LSP12 Issued Assets of a issuer contract that supports ERC725Y. #### Parameters | Name | Type | Description | | :---------- | :----------------------- | :------------------ | | `issuer` | `BytesLike` \| `ERC725Y` | - | | `provider?` | `Provider` | An ethers provider. | #### Returns `Promise`\<`IssuerAssets`\> An array of authenticated & unauthenticated Digital Assets. **`Since`** v0.0.2 **`Throws`** When `issuerAddress` is not a valid address. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-12-IssuedAssets.md #### Defined in [LSP12IssuedAssets/authenticateIssuedAssets/authenticateIssuedAssets.ts:27](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP12IssuedAssets/authenticateIssuedAssets/authenticateIssuedAssets.ts#L27) --- ### getIssuedAssets ▸ **getIssuedAssets**(`issuer`, `provider?`): `Promise`\<`DigitalAsset`[]\> Get the LSP12 Issued Assets of a issuer contract that supports ERC725Y. #### Parameters | Name | Type | Description | | :---------- | :----------------------- | :------------------ | | `issuer` | `BytesLike` \| `ERC725Y` | - | | `provider?` | `Provider` | An ethers provider. | #### Returns `Promise`\<`DigitalAsset`[]\> An array of Digital Assets. **`Since`** v0.0.2 **`Throws`** - When `issuerAddress` is not a valid address. - When the contract deployed at `issuerAddress` does not support the `ERC725Y` interface id. - When the length for `LSP12IssuedAssets[]` is not a valid LSP2 array length value. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-12-IssuedAssets.md #### Defined in [LSP12IssuedAssets/getIssuedAssets/getIssuedAssets.ts:33](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP12IssuedAssets/getIssuedAssets/getIssuedAssets.ts#L33) --- ### removeIssuedAssets ▸ **removeIssuedAssets**(`issuer`, `signer?`): `Promise`\<`void`\> Remove the LSP12 Issued Assets of a issuer contract that supports ERC725Y. #### Parameters | Name | Type | Description | | :-------- | :----------------------- | :----------------------------------------- | | `issuer` | `BytesLike` \| `ERC725Y` | - | | `signer?` | `Signer` \| `Wallet` | The signer that will send the transaction. | #### Returns `Promise`\<`void`\> **`Since`** v0.0.2 **`Throws`** - When `issuerAddress` is not a valid address. - When the contract deployed at `issuerAddress` address does not support the `ERC725Y` interface id. - When there are no `LSP12IssuedAssets[]` in the issuer storage. - When the length for `LSP12IssuedAssets[]` is not a valid LSP2 array length value. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-12-IssuedAssets.md #### Defined in [LSP12IssuedAssets/removeIssuedAssets/removeIssuedAssets.ts:27](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP12IssuedAssets/removeIssuedAssets/removeIssuedAssets.ts#L27) --- --- sidebar_position: 8 --- ### deployUniversalProfile ▸ **deployUniversalProfile**(`signer`, `mainController`, `additionalDataKeys`, `additionalDataValues`, `additionalControllers`, `salt?`): `Promise`\<\{ `keyManagerAddress`: `string` ; `universalProfileAddress`: `string` }\> Deploy Universal Profile with Key Manager using LSP23 Linked Contracts Factory. #### Parameters | Name | Type | Description | | :---------------------- | :------------------- | :-------------------------------------------------------------------------------- | | `signer` | `Signer` \| `Wallet` | The signer used to deploy the contracts, needs to have native token for gas fees. | | `mainController` | `BytesLike` | The main controller for the Universal Profile. | | `additionalDataKeys` | `BytesLike`[] | Data keys that you want to set on deployment. | | `additionalDataValues` | `BytesLike`[] | Data values that you want to set on deployment. | | `additionalControllers` | `LSP6Controller`[] | Additional controllers for the deployed Universal Profile. | | `salt?` | `BytesLike` | - | #### Returns `Promise`\<\{ `keyManagerAddress`: `string` ; `universalProfileAddress`: `string` }\> The addresses of the Universal Profile & Key Manager. **`Since`** v0.0.2 #### Defined in [LSP23LinkedContractsFactory/deployUniversalProfile/deployUniversalProfile.ts:34](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP23LinkedContractsFactory/deployUniversalProfile/deployUniversalProfile.ts#L34) --- --- sidebar_position: 2 --- ### decodeAssetUrl ▸ **decodeAssetUrl**(`assetUrlValue`): `Object` Decode a JSONURL value content. #### Parameters | Name | Type | Description | | :-------------- | :---------- | :----------------------------------------------------- | | `assetUrlValue` | `BytesLike` | The encoded value as `{ "valueContent": "ASSETURL" }`. | #### Returns `Object` ```json { // The hash digest of the function used to hash the JSON file. "hashFunction": "string" // the hashed bytes value of the JSON file. "json": "string" // The URL where the JSON file is hosted. "url": "string" } ``` | Name | Type | | :------------- | :------- | | `hash` | `string` | | `hashFunction` | `string` | | `url` | `string` | **`Since`** v0.0.1 **`Throws`** When `assetUrlValue` his composed of less than 36 bytes. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts decodeAssetUrl("0x6f357c6a2a04850096912391bbb0966a624519e8f5d797df2a2c47425e892c25e00c053568747470733a2f2f676f6f676c652e636f6d2f") => { hashFunction: "0x6f357c6a", hash: "0x2a04850096912391bbb0966a624519e8f5d797df2a2c47425e892c25e00c0535", url: "https://google.com/" } ``` #### Defined in [LSP2ERC725YJSONSchema/decodeAssetUrl/decodeAssetUrl.ts:35](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/decodeAssetUrl/decodeAssetUrl.ts#L35) --- ### decodeJsonUrl ▸ **decodeJsonUrl**(`jsonUrlValue`): `Object` Decode a JSONURL value content. #### Parameters | Name | Type | Description | | :------------- | :---------- | :---------------------------------------------------- | | `jsonUrlValue` | `BytesLike` | The encoded value as `{ "valueContent": "JSONURL" }`. | #### Returns `Object` ```json { // The hash digest of the function used to hash the JSON file. "hashFunction": "string" // the hashed bytes value of the JSON file. "json": "string" // The URL where the JSON file is hosted. "url": "string" } ``` | Name | Type | | :------------- | :------- | | `hash` | `string` | | `hashFunction` | `string` | | `url` | `string` | **`Since`** v0.0.1 **`Throws`** When `jsonUrlValue` his composed of less than 36 bytes. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts decodeJsonUrl("0x6f357c6a4dade694d7dd4081f46073e99ce898a9b53cf6988452904de7db5cc704a4184968747470733a2f2f676f6f676c652e636f6d2f") => { hashFunction: "0x6f357c6a", hash: "0x4dade694d7dd4081f46073e99ce898a9b53cf6988452904de7db5cc704a41849", url: "https://google.com/" } ``` #### Defined in [LSP2ERC725YJSONSchema/decodeJsonUrl/decodeJsonUrl.ts:35](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/decodeJsonUrl/decodeJsonUrl.ts#L35) --- ### encodeAssetUrl ▸ **encodeAssetUrl**(`hashFunction`, `assetBytes`, `url`): `string` Generate a ASSETURL value content. #### Parameters | Name | Type | Description | | :------------- | :------- | :--------------------------------------- | | `hashFunction` | `string` | The function used to hash the JSON file. | | `assetBytes` | `string` | Bytes value of the JSON file. | | `url` | `string` | The URL where the JSON file is hosted. | #### Returns `string` The encoded value as an `ASSETURL`. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts encodeAssetUrl( "keccak256(utf8)", "{\"name\":\"USDStablecoin\",\"description\":\"Some random description about the token USD Stablecoin\"}", "https://google.com/" ) => "0x6f357c6a2a04850096912391bbb0966a624519e8f5d797df2a2c47425e892c25e00c053568747470733a2f2f676f6f676c652e636f6d2f" ``` #### Defined in [LSP2ERC725YJSONSchema/encodeAssetUrl/encodeAssetUrl.ts:25](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/encodeAssetUrl/encodeAssetUrl.ts#L25) --- ### encodeJsonUrl ▸ **encodeJsonUrl**(`hashFunction`, `json`, `url`): `string` Encode a JSONURL value content. #### Parameters | Name | Type | Description | | :------------- | :------- | :--------------------------------------- | | `hashFunction` | `string` | The function used to hash the JSON file. | | `json` | `string` | Bytes value of the JSON file. | | `url` | `string` | The URL where the JSON file is hosted. | #### Returns `string` The encoded value as an `JSONURL`. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts encodeJsonUrl( "keccak256(utf8)", "{\"name\":\"Tom\",\"description\":\"Some random description about Tom\"}", "https://google.com/" ) => "0x6f357c6a4dade694d7dd4081f46073e99ce898a9b53cf6988452904de7db5cc704a4184968747470733a2f2f676f6f676c652e636f6d2f" ``` #### Defined in [LSP2ERC725YJSONSchema/encodeJsonUrl/encodeJsonUrl.ts:25](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/encodeJsonUrl/encodeJsonUrl.ts#L25) --- ### generateArrayElementKeyAtIndex ▸ **generateArrayElementKeyAtIndex**(`arrayKey`, `index`): `string` Generates a data key of `{ "keyType": "Array" }` at a specific `index`. `arrayKey` can have the following values: 1. An array data key, 32 bytes hex value. 2. An array data key name of type `dataKeyName[]` that will be used to generate an array data key using `generateArrayKey(arrayKey)`. #### Parameters | Name | Type | Description | | :--------- | :------- | :---------------------------------------------------------------------------------- | | `arrayKey` | `string` | The Array data key from which to generate the Array data key at a specific `index`. | | `index` | `number` | The index number in the `arrayKey`. | #### Returns `string` The generated `bytes32` data key of key type Array at a specific `index`. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts generateSingletonKey(arrayDataKeyName, index) => `:` generateSingletonKey(arrayDataKey, index) => `:` ``` #### Defined in [LSP2ERC725YJSONSchema/generateArrayElementKeyAtIndex/generateArrayElementKeyAtIndex.ts:24](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/generateArrayElementKeyAtIndex/generateArrayElementKeyAtIndex.ts#L24) --- ### generateArrayKey ▸ **generateArrayKey**(`arrayKeyName`): `string` Generates a data key of `{ "keyType": "Array" }` by hashing `arrayKeyName`. #### Parameters | Name | Type | Description | | :------------- | :------- | :--------------------------------------------------------------------- | | `arrayKeyName` | `string` | The string that will be used to generate a data key of key type Array. | #### Returns `string` The generated `bytes32` data key of key type Array. **`Since`** v0.0.1 **`Throws`** `keyName` has less than 2 characters. **`Throws`** `keyName` does not include square brackets `"[]"` at the end of the string. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts generateArrayKey("RandomArrayDataKey[]") => keccak256("RandomArrayDataKey[]") = "0x6e9974ec39571e80dcc2ab1fac99097b03bb4617b071cd519a23d38f88f28ffb" ``` #### Defined in [LSP2ERC725YJSONSchema/generateArrayKey/generateArrayKey.ts:22](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/generateArrayKey/generateArrayKey.ts#L22) --- ### generateMappingKey ▸ **generateMappingKey**(`firstPart`, `lastPart`): `string` Generates a data key of `{ "keyType": "Mapping" }` that map `firstPart` to `lastPart`. `firstPart` can have the following values: 1. A 10 bytes hex value. 2. A hex value that will be hashed (first 10 bytes will be used). 3. A UTF8 string that will be hashed (first 10 bytes will be used). `lastPart` can have the following values: 1. An address. 1. A 20 bytes hex value. 1. A hex value that will be hashed (first 20 bytes will be used). 1. A UTF8 string that will be hashed (first 20 bytes will be used). #### Parameters | Name | Type | Description | | :---------- | :---------- | :--------------------------------------------------- | | `firstPart` | `BytesLike` | The word to retrieve the first 10 bytes of its hash. | | `lastPart` | `BytesLike` | The word to retrieve the first 10 bytes of its hash. | #### Returns `string` The generated `bytes32` data key of key type Mapping that map `firstPart` to a specific `lastPart`. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts generateMappingKey(firstWord, lastWord) =>`:<0000>:` generateMappingKey(firstWord, bytes20value) =>`:<0000>:` generateMappingKey(bytes10Value, lastWord) =>`:<0000>:` generateMappingKey(bytes10Value, bytes20value) =>`:<0000>:` ``` #### Defined in [LSP2ERC725YJSONSchema/generateMappingKey/generateMappingKey.ts:37](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/generateMappingKey/generateMappingKey.ts#L37) --- ### generateMappingWithGroupingKey ▸ **generateMappingWithGroupingKey**(`firstPart`, `middlePart`, `lastPart`): `string` Generates a data key of `{ "keyType": "MappingWithGrouping" }` that map `firstPart` to `middlePart` and to `lastPart`. `firstPart` can have the following values: 1. A 6 bytes hex value. 2. A hex value that will be hashed (first 6 bytes will be used). 3. A UTF8 string that will be hashed (first 6 bytes will be used). `middlePart` can have the following values: 1. A 4 bytes hex value. 2. A hex value that will be hashed (first 4 bytes will be used). 3. A UTF8 string that will be hashed (first 4 bytes will be used). `lastPart` can have the following values: 1. An address. 1. A 20 bytes hex value. 1. A hex value that will be hashed (first 20 bytes will be used). 1. A UTF8 string that will be hashed (first 20 bytes will be used). #### Parameters | Name | Type | Description | | :----------- | :---------- | :--------------------------------------------------- | | `firstPart` | `BytesLike` | The word to retrieve the first 6 bytes of its hash. | | `middlePart` | `BytesLike` | The word to retrieve the first 4 bytes of its hash. | | `lastPart` | `BytesLike` | The word to retrieve the first 20 bytes of its hash. | #### Returns `string` The generated `bytes32` data key of key type MappingWithGrouping that map a `firstWord` to a `secondWord` to a specific address `addr`. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts generateMappingWithGroupingKey(firstWord, middleWord, lastWord) => `::<0000>:` generateMappingWithGroupingKey(firstWord, middleWord, bytes20Value) => `::<0000>:` generateMappingWithGroupingKey(firstWord, bytes4Value, lastWord) => `::<0000>:` generateMappingWithGroupingKey(firstWord, bytes4Value, bytes20Value) => `::<0000>:` generateMappingWithGroupingKey(bytes6Value, middleWord, lastWord) => `::<0000>:` generateMappingWithGroupingKey(bytes6Value, middleWord, bytes20Value) => `::<0000>:` generateMappingWithGroupingKey(bytes6Value, bytes4Value, lastWord) => `::<0000>:` generateMappingWithGroupingKey(bytes6Value, bytes4Value, bytes20Value) => `::<0000>:` ``` #### Defined in [LSP2ERC725YJSONSchema/generateMappingWithGroupingKey/generateMappingWithGroupingKey.ts:51](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/generateMappingWithGroupingKey/generateMappingWithGroupingKey.ts#L51) --- ### generateSingletonKey ▸ **generateSingletonKey**(`keyName`): `string` Generates a data key of `{ "keyType": "Singleton" }` by hashing the string `keyName`. #### Parameters | Name | Type | Description | | :-------- | :------- | :--------------------------------------------------- | | `keyName` | `string` | The string to hash to generate a Singleton data key. | #### Returns `string` The generated `bytes32` data key of key type Singleton. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts generateSingletonKey("RandomDataKey") => keccak256("RandomKeyName") = "0xb0c92ac98a2a422f33a3e130e3fa6e922195f0a0a99199963814012351f906cb" ``` #### Defined in [LSP2ERC725YJSONSchema/generateSingletonKey/generateSingletonKey.ts:19](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/generateSingletonKey/generateSingletonKey.ts#L19) --- ### isCompactBytesArray ▸ **isCompactBytesArray**(`compactBytesArray`): `boolean` Verify if `data` is a valid array of value encoded as a `CompactBytesArray` according to the LSP2 `CompactBytesArray` valueType specification. #### Parameters | Name | Type | Description | | :------------------ | :---------- | :------------------------- | | `compactBytesArray` | `BytesLike` | The bytes value to verify. | #### Returns `boolean` `true` if the `data` is correctly encoded CompactBytesArray, `false` otherwise. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts isCompactBytesArray("0x0002cafe000abeefdeadbeef0000cafe") => true isCompactBytesArray("0x0002cafecafe000abeefdeadbeef0000cafe") => false isCompactBytesArray("0x0002") => false ``` #### Defined in [LSP2ERC725YJSONSchema/isCompactBytesArray/isCompactBytesArray.ts:21](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/isCompactBytesArray/isCompactBytesArray.ts#L21) --- ### isValidArrayLengthValue ▸ **isValidArrayLengthValue**(`arrayLength`): `boolean` Validates if the bytes `arrayLength` are exactly 16 bytes long, and are of the exact size of an LSP2 Array length value #### Parameters | Name | Type | Description | | :------------ | :---------- | :------------------------------------ | | `arrayLength` | `BytesLike` | Plain bytes that should be validated. | #### Returns `boolean` `true` if the value is 16 bytes long, `false` otherwise. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts isValidArrayLengthValue("0x00000000000000000000000000000001") => true isValidArrayLengthValue("0x00000000000000000000000000000a3b") => true isValidArrayLengthValue("0x000000000000000000000000004a") => false isValidArrayLengthValue("0x0000000000000000000000000000000000f60a") => false ``` #### Defined in [LSP2ERC725YJSONSchema/isValidArrayLengthValue/isValidArrayLengthValue.ts:22](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/isValidArrayLengthValue/isValidArrayLengthValue.ts#L22) --- ### removeElementFromArrayAndMap ▸ **removeElementFromArrayAndMap**(`erc725YContract`, `arrayKey`, `newArrayLength`, `removedElementIndexKey`, `removedElementIndex`, `removedElementMapKey`): `Promise`\<\{ `dataKeys`: `BytesLike`[] ; `dataValues`: `BytesLike`[] }\> Generates Data Key/Value pairs for removing an element from an LSP2 Array and a mapping Data Key. #### Parameters | Name | Type | Description | | :----------------------- | :----------------- | :------------------------------------------------------------ | | `erc725YContract` | `UniversalProfile` | The ERC725Y contract. | | `arrayKey` | `BytesLike` | The Data Key of Key Type Array. | | `newArrayLength` | `number` | The new Array Length for the `arrayKey`. | | `removedElementIndexKey` | `BytesLike` | The Data Key of Key Type Array Index for the removed element. | | `removedElementIndex` | `number` | the index of the removed element. | | `removedElementMapKey` | `BytesLike` | The Data Key of a mapping to be removed. | #### Returns `Promise`\<\{ `dataKeys`: `BytesLike`[] ; `dataValues`: `BytesLike`[] }\> A set of data keys & data values that can be used to update an array and map in ERC725Y storage. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts removeLastElementFromArrayAndMap(...) => { dataKeys: BytesLike[], dataValues: BytesLike[] } ``` #### Defined in [LSP2ERC725YJSONSchema/removeElementFromArrayAndMap/removeElementFromArrayAndMap.ts:32](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/removeElementFromArrayAndMap/removeElementFromArrayAndMap.ts#L32) --- ### removeLastElementFromArrayAndMap ▸ **removeLastElementFromArrayAndMap**(`arrayKey`, `newArrayLength`, `removedElementIndexKey`, `removedElementMapKey`): `Object` Generates Data Key/Value pairs for removing the last element from an LSP2 Array and a mapping Data Key. #### Parameters | Name | Type | Description | | :----------------------- | :---------- | :------------------------------------------------------------ | | `arrayKey` | `BytesLike` | The Data Key of Key Type Array. | | `newArrayLength` | `number` | The new Array Length for the `arrayKey`. | | `removedElementIndexKey` | `BytesLike` | The Data Key of Key Type Array Index for the removed element. | | `removedElementMapKey` | `BytesLike` | The Data Key of a mapping to be removed. | #### Returns `Object` A set of data keys & data values that can be used to update an array and map in ERC725Y storage. | Name | Type | | :----------- | :------------ | | `dataKeys` | `BytesLike`[] | | `dataValues` | `BytesLike`[] | **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md **`Example`** ```ts removeLastElementFromArrayAndMap(...) => { dataKeys: BytesLike[], dataValues: BytesLike[] } ``` #### Defined in [LSP2ERC725YJSONSchema/removeLastElementFromArrayAndMap/removeLastElementFromArrayAndMap.ts:22](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP2ERC725YJSONSchema/removeLastElementFromArrayAndMap/removeLastElementFromArrayAndMap.ts#L22) --- --- sidebar_position: 3 --- ### getProfileMetadata ▸ **getProfileMetadata**(`contract`, `provider?`): `Promise`\<`LSP3ProfileMetadataJSON`\> Returns a object of type LSP3ProfileMetadata. #### Parameters | Name | Type | | :---------- | :----------------------- | | `contract` | `BytesLike` \| `ERC725Y` | | `provider?` | `Provider` | #### Returns `Promise`\<`LSP3ProfileMetadataJSON`\> **`Since`** v0.0.1 **`Throws`** - When fails fetching the data from the stored url. - When the fetched data is not `LSP3ProfileMetadata`. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md **`Example`** ```ts getProfileMetadata(ERC725Y) => { LSP3Profile: { name: string; description: string; links: Link[]; tags: string[]; avatar: (Avatar | NFTBasedAvatar)[]; profileImage: (Image | NFTBasedImage)[]; backgroundImage: (Image | NFTBasedImage)[]; } } ``` #### Defined in [LSP3ProfileMetadata/getProfileMetadata/getProfileMetadata.ts:53](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP3ProfileMetadata/getProfileMetadata/getProfileMetadata.ts#L53) --- ### isProfileMetadata ▸ **isProfileMetadata**(`object`): object is LSP3ProfileMetadataJSON Returns `true` is the passed object is an LSP3 Profile Metadata, `false` otherwise. #### Parameters | Name | Type | Description | | :------- | :---- | :-------------------------------- | | `object` | `any` | The object that is to be checked. | #### Returns object is LSP3ProfileMetadataJSON **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md **`Example`** ```ts isProfileMetadata({ LSP3Profile: { name: "", description: "", links: [], tags: [] avatar: [], profileImage: [], backgroundImage: [], } }) => true isProfileMetadata({ description: "", links: [], name: "", tags: [] }) => false ``` #### Defined in [LSP3ProfileMetadata/isProfileMetadata/isProfileMetadata.ts:16](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP3ProfileMetadata/isProfileMetadata/isProfileMetadata.ts#L16) --- --- sidebar_position: 4 --- ### addDigitalAssetCreators ▸ **addDigitalAssetCreators**(`digitalAsset`, `newCreators`, `signer?`): `Promise`\<`void`\> Add LSP4 Creators to the digital asset contract that supports ERC725Y. #### Parameters | Name | Type | Description | | :------------- | :----------------------- | :----------------------------------------------------------------------------------- | | `digitalAsset` | `BytesLike` \| `ERC725Y` | - | | `newCreators` | `Issuer`[] | An array of creators which specifies the address and interface id of each creatotor. | | `signer?` | `Signer` \| `Wallet` | The signer that will send the transaction. | #### Returns `Promise`\<`void`\> **`Since`** v0.0.2 **`Throws`** - When `newCreators` is an empty array. - When `digitalAssetAddress` is not a valid address. - When the contract deployed at `digitalAssetAddress` address does not support the `ERC725Y` interface id. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md #### Defined in [LSP4DigitalAssetMetadata/addDigitalAssetCreators/addDigitalAssetCreators.ts:30](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP4DigitalAssetMetadata/addDigitalAssetCreators/addDigitalAssetCreators.ts#L30) --- ### authenticateDigitalAssetCreators ▸ **authenticateDigitalAssetCreators**(`digitalAsset`, `provider?`): `Promise`\<`DigitalAssetsCreators`\> Get the authenticated LSP4 Creators of the digital asset contract that supports ERC725Y. #### Parameters | Name | Type | Description | | :------------- | :----------------------- | :------------------ | | `digitalAsset` | `BytesLike` \| `ERC725Y` | - | | `provider?` | `Provider` | An ethers provider. | #### Returns `Promise`\<`DigitalAssetsCreators`\> An array of authenticated & unauthenticated Issuers. **`Since`** v0.0.2 **`Throws`** When `digitalAssetAddress` is not a valid address. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md #### Defined in [LSP4DigitalAssetMetadata/authenticateDigitalAssetCreators/authenticateDigitalAssetCreators.ts:27](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP4DigitalAssetMetadata/authenticateDigitalAssetCreators/authenticateDigitalAssetCreators.ts#L27) --- ### getAssetMetadata ▸ **getAssetMetadata**(`digitalAsset`, `provider?`): `Promise`\<`LSP4AssetMetadata`\> Returns a object of type LSP4AssetMetadata. #### Parameters | Name | Type | Description | | :------------- | :----------------------- | :---------------------------------- | | `digitalAsset` | `BytesLike` \| `ERC725Y` | The instance of a ERC725Y contract. | | `provider?` | `Provider` | - | #### Returns `Promise`\<`LSP4AssetMetadata`\> **`Since`** v0.0.2 **`Throws`** - When fails fetching the data from the stored url. - When the fetched data is not `LSP4AssetMetadata`. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md **`Example`** ```ts getAssetMetadata(ERC725Y) => { LSP4Metadata: { name: "", description: "", links: [], icon: [], assets: [], images: [] } } ``` #### Defined in [LSP4DigitalAssetMetadata/getAssetMetadata/getAssetMetadata.ts:45](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP4DigitalAssetMetadata/getAssetMetadata/getAssetMetadata.ts#L45) --- ### getDigitalAssetCreators ▸ **getDigitalAssetCreators**(`digitalAsset`, `provider?`): `Promise`\<`Issuer`[]\> Get the LSP4 Creators of a digital asset contract that supports ERC725Y. #### Parameters | Name | Type | Description | | :------------- | :----------------------- | :------------------ | | `digitalAsset` | `BytesLike` \| `ERC725Y` | - | | `provider?` | `Provider` | An ethers provider. | #### Returns `Promise`\<`Issuer`[]\> An array of Issuers. **`Since`** v0.0.2 **`Throws`** - When `digitalAssetAddress` is not a valid address. - When the contract deployed at `digitalAssetAddress` does not support the `ERC725Y` interface id. - When the length for `LSP4Creators[]` is not a valid LSP2 array length value. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md #### Defined in [LSP4DigitalAssetMetadata/getDigitalAssetCreators/getDigitalAssetCreators.ts:33](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP4DigitalAssetMetadata/getDigitalAssetCreators/getDigitalAssetCreators.ts#L33) --- ### isAssetMetadata ▸ **isAssetMetadata**(`object`): object is LSP4DigitalAssetMetadataJSON Returns `true` is the passed object is an LSP4 Asset Metadata, `false` otherwise. #### Parameters | Name | Type | Description | | :------- | :---- | :-------------------------------- | | `object` | `any` | The object that is to be checked. | #### Returns object is LSP4DigitalAssetMetadataJSON **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-3-Profile-Metadata.md **`Example`** ```ts isAssetMetadata({ LSP4Metadata: { description: "", links: [], images: [], assets: [] icon: [] } }) => true isAssetMetadata({ description: "", links: [], name: "", tags: [] }) => false ``` #### Defined in [LSP4DigitalAssetMetadata/isAssetMetadata/isAssetMetadata.ts:16](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP4DigitalAssetMetadata/isAssetMetadata/isAssetMetadata.ts#L16) --- ### removeDigitalAssetCreators ▸ **removeDigitalAssetCreators**(`digitalAsset`, `signer?`): `Promise`\<`void`\> Remove the LSP4 Creators of a digital asset contract that supports ERC725Y. #### Parameters | Name | Type | Description | | :------------- | :----------------------- | :----------------------------------------- | | `digitalAsset` | `BytesLike` \| `ERC725Y` | - | | `signer?` | `Signer` \| `Wallet` | The signer that will send the transaction. | #### Returns `Promise`\<`void`\> **`Since`** v0.0.2 **`Throws`** - When `digitalAssetAddress` is not a valid address. - When the contract deployed at `digitalAssetAddress` address does not support the `ERC725Y` interface id. - When there are no `LSP4Creators[]` in the digital asset storage. - When the length for `LSP4Creators[]` is not a valid LSP2 array length value. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-4-DigitalAsset-Metadata.md #### Defined in [LSP4DigitalAssetMetadata/removeDigitalAssetCreators/removeDigitalAssetCreators.ts:27](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP4DigitalAssetMetadata/removeDigitalAssetCreators/removeDigitalAssetCreators.ts#L27) --- --- sidebar_position: 5 --- ### generateReceivedAssetKeys ▸ **generateReceivedAssetKeys**(`erc725YContract`, `assetAddress`, `assetInterfaceId`): `Promise`\<\{ `lsp5DataKeys`: `BytesLike`[] ; `lsp5DataValues`: `BytesLike`[] }\> Generate an array of Data Key/Value pairs to be set on the receiver address after receiving assets. #### Parameters | Name | Type | Description | | :----------------- | :----------------- | :---------------------------------------------------------------------- | | `erc725YContract` | `UniversalProfile` | The contract instance of the asset receiver. | | `assetAddress` | `BytesLike` | The address of the asset being received (_e.g: an LSP7 or LSP8 token_). | | `assetInterfaceId` | `BytesLike` | The interfaceID of the asset being received. | #### Returns `Promise`\<\{ `lsp5DataKeys`: `BytesLike`[] ; `lsp5DataValues`: `BytesLike`[] }\> A set of LSP5 data keys & data values that can be used to update an array and map in ERC725Y storage. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-5-ReceivedAssets.md **`Example`** ```ts generateReceivedAssetKeys(...) => { lsp5DataKeys: BytesLike[], lsp5DataValues: BytesLike[] } ``` #### Defined in [LSP5ReceivedAssets/generateReceivedAssetKeys/generateReceivedAssetKeys.ts:32](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP5ReceivedAssets/generateReceivedAssetKeys/generateReceivedAssetKeys.ts#L32) --- ### generateSentAssetKeys ▸ **generateSentAssetKeys**(`erc725YContract`, `assetAddress`): `Promise`\<\{ `dataKeys`: `BytesLike`[] ; `dataValues`: `BytesLike`[] }\> Generate an array of Data Key/Value pairs to be set on the sender address after sending assets. #### Parameters | Name | Type | Description | | :---------------- | :----------------- | :------------------------------------------- | | `erc725YContract` | `UniversalProfile` | The contract instance of the asset sender. | | `assetAddress` | `BytesLike` | The address of the asset that is being sent. | #### Returns `Promise`\<\{ `dataKeys`: `BytesLike`[] ; `dataValues`: `BytesLike`[] }\> A set of LSP5 data keys & data values that can be used to update an array and map in ERC725Y storage. **`Since`** v0.0.1 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-5-ReceivedAssets.md **`Example`** ```ts generateSentAssetKeys(...) => { lsp5DataKeys: BytesLike[], lsp5DataValues: BytesLike[] } ``` #### Defined in [LSP5ReceivedAssets/generateSentAssetKeys/generateSentAssetKeys.ts:34](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP5ReceivedAssets/generateSentAssetKeys/generateSentAssetKeys.ts#L34) --- --- sidebar_position: 6 --- ### createValidityTimestamp ▸ **createValidityTimestamp**(`startingTimestamp`, `endingTimestamp`): `string` Create a `validityTimestamp` that can be used in `LSP6.executeRelayCall(...)` #### Parameters | Name | Type | Description | | :------------------ | :------------- | :--------------------------------------------------------- | | `startingTimestamp` | `BigNumberish` | The timestamp after which a relay call can be executed. | | `endingTimestamp` | `BigNumberish` | The timestamp after which a relay call cannot be executed. | #### Returns `string` A hex value of 32 bytes that contains both starting & ending timestamps. **`Since`** v0.0.1 **`Throws`** When the bytes value of either `startingTimestamp` or `endingTimestamp` exceeds 16 bytes. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md **`Example`** ```ts createValidityTimestamp(5, 10) => `0x000000000000000000000000000000050000000000000000000000000000000a` ``` #### Defined in [LSP6KeyManager/createValidityTimestamp/createValidityTimestamp.ts:21](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP6KeyManager/createValidityTimestamp/createValidityTimestamp.ts#L21) --- ### decodeAllowedCalls ▸ **decodeAllowedCalls**(`allowedCalls`): `Object` Decode AllowedCalls encoded as `{ "valueType": "bytes[CompactBytesArray]" }`. #### Parameters | Name | Type | Description | | :------------- | :---------- | :------------------------------------------------------------------------ | | `allowedCalls` | `BytesLike` | A list of allowed calls as `{ "valueType": "bytes[CompactBytesArray]" }`. | #### Returns `Object` The allowed interactions, addresses, functions and standards that were encoded. | Name | Type | | :-------------------- | :------------ | | `allowedAddresses` | `BytesLike`[] | | `allowedFunctions` | `BytesLike`[] | | `allowedInteractions` | `BytesLike`[] | | `allowedStandards` | `BytesLike`[] | **`Since`** v0.0.1 **`Throws`** - When the value of `allowedCalls` is not hex. - When the bytes length of any allowed call is different from 32. - When the length of an element reaches past the length of `allowedCalls` **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md **`Example`** ```ts decodeAllowedCalls("0x002000000002cafecafecafecafecafecafecafecafecafecafe24871b3d7f23690c002000000003cafecafecafecafecafecafecafecafecafecafe24871b3d44c028fe") => { allowedInteractions: ["0x00000002", "0x00000003"], allowedAddresses: ["0xcafecafecafecafecafecafecafecafecafecafe", "0xcafecafecafecafecafecafecafecafecafecafe"], allowedStandards: ["0x24871b3d", "0x24871b3d"], allowedFunctions: ["0x7f23690c", "0x44c028fe"], } decodeAllowedCalls("0x002000000002cafecafecafecafecafecafecafecafecafecafe24871b3d7f23690c") => { allowedInteractions: ["0x00000002"], allowedAddresses: ["0xcafecafecafecafecafecafecafecafecafecafe"], allowedStandards: ["0x24871b3d"], allowedFunctions: ["0x7f23690c"], } ``` #### Defined in [LSP6KeyManager/decodeAllowedCalls/decodeAllowedCalls.ts:37](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP6KeyManager/decodeAllowedCalls/decodeAllowedCalls.ts#L37) --- ### decodeAllowedERC725YDataKeys ▸ **decodeAllowedERC725YDataKeys**(`allowedERC725YDataKeys`): `BytesLike`[] Decode AllowedERC725YDataKeys encoded as `{ "valueType": "bytes[CompactBytesArray]" }`. #### Parameters | Name | Type | Description | | :----------------------- | :---------- | :------------------------------------------------------------------------ | | `allowedERC725YDataKeys` | `BytesLike` | A list of allowed calls as `{ "valueType": "bytes[CompactBytesArray]" }`. | #### Returns `BytesLike`[] The allowed ERC725Y data keys that were encoded. **`Since`** v0.0.1 **`Throws`** - When the value of `allowedERC725YDataKeys` is not hex. - When the bytes length of any allowed ERC725Y data key is 0 or bigger than 32. - When the length of an element reaches past the length of `allowedERC725YDataKeys` **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md **`Example`** ```ts decodeAllowedERC725YDataKeys("0x0002cafe000abeefdeadbeef0000cafe") => [ "0xcafe", "0xbeefdeadbeef0000cafe" ] ``` #### Defined in [LSP6KeyManager/decodeAllowedERC725YDataKeys/decodeAllowedERC725YDataKeys.ts:27](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP6KeyManager/decodeAllowedERC725YDataKeys/decodeAllowedERC725YDataKeys.ts#L27) --- ### decodePermissions ▸ **decodePermissions**(`permissions`, `decodedPermissionsType?`): `Set`\<`BytesLike` \| `bigint` \| `LSP6PermissionName`\> \| `boolean`[] Decode a hex value, containing a `BitArray` of permissions. The `AddressPermissions:Permissions:
` can be decoded using this function. #### Parameters | Name | Type | Description | | :------------------------ | :------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `permissions` | `BytesLike` | A hex value, containing a BitArray of permissions. | | `decodedPermissionsType?` | `"bigint"` \| `"boolean"` \| `"BytesLike"` \| `"LSP6PermissionName"` | Optional param, defaults to `LSP6PermissionName`. Can be used to specify the type of the return array. Options: - `BytesLike` - `bigint` - `boolean` - `LSP6PermissionName` | #### Returns `Set`\<`BytesLike` \| `bigint` \| `LSP6PermissionName`\> \| `boolean`[] An array of decoded permissions. **`Since`** v0.0.2 **`Throws`** **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md **`Example`** ```ts decodePermissions([ `0x0000000000000000000000000000000000000000000000000000000000040803` ]) => new Set([ CHANGEOWNER, ADDCONTROLLER, CALL, SETDATA ]) decodePermissions([ `0x0000000000000000000000000000000000000000000000000000000000040803`, 'LSP6PermissionName' ]) => new Set([ CHANGEOWNER, ADDCONTROLLER, CALL, SETDATA ]) decodePermissions([ `0x0000000000000000000000000000000000000000000000000000000000040803`, 'BytesLike' ]) => new Set([ '0x0000000000000000000000000000000000000000000000000000000000000001', '0x0000000000000000000000000000000000000000000000000000000000000002', '0x0000000000000000000000000000000000000000000000000000000000000800', '0x0000000000000000000000000000000000000000000000000000000000040000', ]) decodePermissions([ `0x0000000000000000000000000000000000000000000000000000000000040803`, 'bigint' ]) => new Set([ 1n, 2n, 2048n, 262144n ]) decodePermissions([ `0x0000000000000000000000000000000000000000000000000000000000000003`, 'boolean' ]) => [ true, true, false, false, false, false, false, false ] ``` #### Defined in [LSP6KeyManager/decodePermissions/decodePermissions.ts:53](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP6KeyManager/decodePermissions/decodePermissions.ts#L53) --- ### encodeAllowedCalls ▸ **encodeAllowedCalls**(`allowedInteractions`, `allowedAddresses`, `allowedStandards`, `allowedFunctions`): `string` Encode a list of data keys as `{ "valueType": "(bytes4,address,bytes4,bytes4)[CompactBytesArray]" }`. The result can be used for `AddressPermissions:AllowedCalls:
` #### Parameters | Name | Type | Description | | :-------------------- | :------------ | :------------------------------ | | `allowedInteractions` | `BytesLike`[] | A list of allowed interactions. | | `allowedAddresses` | `BytesLike`[] | A list of allowed addresses. | | `allowedStandards` | `BytesLike`[] | A list of allowed standards. | | `allowedFunctions` | `BytesLike`[] | A list of allowed functions. | #### Returns `string` The compacted array of allowed calls as `{ "valueType": "(bytes4,address,bytes4,bytes4)[CompactBytesArray]" }`. **`Since`** v0.0.1 **`Throws`** - When the arrays passed as parameters don't have the same length. - When one of `allowedInteractions[index]` has a bytes length different from 4. - When one of `allowedAddresses[index]` has a bytes length different from 20. - When one of `allowedStandards[index]` has a bytes length different from 4. - When one of `allowedFunctions[index]` has a bytes length different from 4. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md **`Example`** ```ts encodeAllowedCalls( ["0x00000002", "0x00000003"], ["0xcafecafecafecafecafecafecafecafecafecafe", "0xcafecafecafecafecafecafecafecafecafecafe"] ["0x24871b3d", "0x24871b3d"], ["0x7f23690c", "0x44c028fe"], ) => "0x002000000002cafecafecafecafecafecafecafecafecafecafe24871b3d7f23690c002000000003cafecafecafecafecafecafecafecafecafecafe24871b3d44c028fe" encodeAllowedCalls( ["0x00000002"], ["0xcafecafecafecafecafecafecafecafecafecafe"] ["0x24871b3d"], ["0x7f23690c"], ) => "0x002000000002cafecafecafecafecafecafecafecafecafecafe24871b3d7f23690c" ``` #### Defined in [LSP6KeyManager/encodeAllowedCalls/encodeAllowedCalls.ts:39](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP6KeyManager/encodeAllowedCalls/encodeAllowedCalls.ts#L39) --- ### encodeAllowedERC725YDataKeys ▸ **encodeAllowedERC725YDataKeys**(`dataKeys`): `string` Encode a list of data keys as `{ "valueType": "bytes[CompactBytesArray]" }`. The result can be user for `AddressPermissions:AllowedERC725YDataKeys:
` #### Parameters | Name | Type | Description | | :--------- | :------------ | :------------------- | | `dataKeys` | `BytesLike`[] | A list of data keys. | #### Returns `string` The compacted array of data keys as `{ "valueType": "bytes[CompactBytesArray]" }`. **`Since`** v0.0.1 **`Throws`** - When one of `dataKeys[index]` is not hex. - When one of `dataKeys[index]` has a length of 0 bytes or bigger thsn 32 bytes. **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md **`Example`** ```ts encodeAllowedERC725YDataKeys([ "0xcafe", "0xbeefdeadbeef0000cafe" ]) => "0x0002cafe000abeefdeadbeef0000cafe" ``` #### Defined in [LSP6KeyManager/encodeAllowedERC725YDataKeys/encodeAllowedERC725YDataKeys.ts:25](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP6KeyManager/encodeAllowedERC725YDataKeys/encodeAllowedERC725YDataKeys.ts#L25) --- ### encodePermissions ▸ **encodePermissions**(`permissions`): `string` Generate a `BitArray` of permissions. The result can be user for `AddressPermissions:Permissions:
`. #### Parameters | Name | Type | Description | | :------------ | :------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- | | `permissions` | (`string` \| `number` \| `bigint` \| `boolean`)[] | An array of LSP6 permissions, LSP6 permission names, numbers, booleans or any combination of the previously enumerated types. | #### Returns `string` A `BitArray` that can be use as LSP6 controller permissions. **`Since`** v0.0.2 **`See`** https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-6-KeyManager.md **`Example`** ```ts encodePermissions([ "0x0000000000000000000000000000000000000000000000000000000000000001", //CHANGEOWNER "0x0000000000000000000000000000000000000000000000000000000000000002", //ADDCONTROLLER "0x0000000000000000000000000000000000000000000000000000000000000800", //CALL "0x0000000000000000000000000000000000000000000000000000000000040000", //SETDATA ]) => `0x0000000000000000000000000000000000000000000000000000000000040803` encodePermissions([ true, // `0x0000000000000000000000000000000000000000000000000000000000000001` - CHANGEOWNER true, // `0x0000000000000000000000000000000000000000000000000000000000000002` - ADDCONTROLLER false, // `0x0000000000000000000000000000000000000000000000000000000000000000` - EDITPERMISSIONS true, // `0x0000000000000000000000000000000000000000000000000000000000000008` - ADDEXTENSIONS ]) => `0x000000000000000000000000000000000000000000000000000000000000000b` encodePermissions([ 1, // `0x0000000000000000000000000000000000000000000000000000000000000001` - CHANGEOWNER 2, // `0x0000000000000000000000000000000000000000000000000000000000000002` - ADDCONTROLLER 4, // `0x0000000000000000000000000000000000000000000000000000000000000004` - EDITPERMISSIONS ]) => `0x0000000000000000000000000000000000000000000000000000000000000007` ``` #### Defined in [LSP6KeyManager/encodePermissions/encodePermissions.ts:37](https://github.com/lukso-network/lsp-utils/blob/31b2f8b/src/LSP6KeyManager/encodePermissions/encodePermissions.ts#L37) --- --- sidebar_position: 1 --- # Getting Started :::caution This package is currently in the early stages of development. Please use it for testing or experimentation purposes only. ::: The `@lukso/lsp-utils` package allows you to interact with the LSPs in a easier way. It provides a set of utility functions. The package is meant to speed up the frontend/backend development using LSP smart contracts. - GitHub repo: http://github.com/lukso-network/lsp-utils - NPM: https://www.npmjs.com/package/@lukso/lsp-utils ## Modules - [IPFS](./IPFS.md) - [LSP12IssuedAssets](./LSP12IssuedAssets.md) - [LSP23LinkedContractsFactory](./LSP23LinkedContractsFactory.md) - [LSP2ERC725YJSONSchema](./LSP2ERC725YJSONSchema.md) - [LSP3ProfileMetadata](./LSP3ProfileMetadata.md) - [LSP4DigitalAssetMetadata](./LSP4DigitalAssetMetadata.md) - [LSP5ReceivedAssets](./LSP5ReceivedAssets.md) - [LSP6KeyManager](./LSP6KeyManager.md) ## Installation ### General package ```bash npm install @lukso/lsp-utils ``` ### Specific package ```bash npm install @lukso/lsp-utils/LSP2 ``` ## Usage ```ts import { generateArrayElementKeyAtIndex } from '@lukso/lsp-utils'; const indexDataKey = generateArrayElementKeyAtIndex('ArrayName[]', 1); ``` ```ts import { generateMappingKey } from '@lukso/lsp-utils/LSP2'; const mappingDataKey = generateMappingKey( 'FirstMappingPart', 'SecondMappingPart', ); ``` --- --- sidebar_position: 1 title: 'Getting Started' --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Getting Started The `@up-provider` library lets dApps run as mini-apps on Grid and allows parent applications to one-click-connect to your mini-app. ## Installation ```bash npm install @lukso/up-provider ``` ## Usage in mini-apps Below are the examples of how to use the `up-provider` with different libraries: ```js import { createClientUPProvider } from '@lukso/up-provider'; import { createWalletClient, createPublicClient, custom } from 'viem'; import { lukso } from 'viem/chains'; // Construct the up-provider const provider = createClientUPProvider(); // Create public client if you need direct connection to RPC const publicClient = createPublicClient({ chain: lukso, transport: http(), }); // Create wallet client to connect to provider const walletClient = createWalletClient({ chain: lukso, transport: custom(provider), }); ``` ```js import { createClientUPProvider } from '@lukso/up-provider' import { type Eip1193Provider, ethers } from 'ethers' // Create the up-provider const provider = createClientUPProvider() // Wrap provider into ethers for usage. const browserProvider = new ethers.BrowserProvider(upProvider as unknown as Eip1193Provider) ``` ```js import { createClientUPProvider } from '@lukso/up-provider'; import Web3, { type EthExecutionAPI, type SupportedProviders } from 'web3'; // Create the up-provider const provider = createClientUPProvider(); // Wrap provider into web3 for usage. const web3 = new Web3(provider as SupportedProviders); ``` ## Resources - [GitHub repo](https://github.com/lukso-network/tools-up-provider/) - [NPM package](https://www.npmjs.com/package/@lukso/up-provider) - [Try out the example mini-app on your grid!](https://nextjs.miniapp-example.lukso.tech/) --- --- sidebar_position: 2 title: 'Grid Providers' --- :::info About Grid Providers Developers can use Grid Providers to host and connect mini-apps on their pages. ::: # Grid Providers Mini-apps can be hosted on a parent page by passing UP connections to a parent provider like `window.ethereum`. ```js import { UPClientChannel, createUPProviderConnector } from '@lukso/up-provider'; // Pass in the provider you want the page to use. const providerConnector = createUPProviderConnector(originalProvider, [ 'https://rpc.mainnet.lukso.network', ]); // or later on call // globalProvider.setupProvider(originalProvider, ['https://rpc.mainnet.lukso.network']) providerConnector.on('channelCreated', ({ channel, id }) => { // Called when an iframe connects. // then channel can control the connection. // Usually you would store this in a ref and use it within a dialog to control the connection. // for example channel.enabled = true; // The addresses and chainId it will cause addressChanged and chainChanged events on the client provider. channel.setAllowedAccounts([profileAddress, ...extraAddresses]); }); ``` --- --- title: 🏭 Node Docker Factory sidebar_position: 7 --- # Node Docker Factory [Docker Factory](https://docker-factory.lukso.tech) is a web app that allows you to easily create a custom docker-compose file to connect to a LUKSO network. Simply select your desired clients, add the additional options, copy your generated docker-compose file and run it. For more information visit the [Docker Factory](https://docker-factory.lukso.tech) website. --- --- title: 🔍 Explorers & Debug Tools sidebar_position: 2 --- # 🔍 Explorers & Debug Tools ## Block Explorers LUKSO uses the open-source [Blockscout Explorer](https://github.com/blockscout/blockscout) fork to inspect blockchain and transaction data. LUKSO Mainnet - [LUKSO Mainnet Execution Explorer](https://explorer.lukso.network/) - [LUKSO Mainnet Consensus Explorer](https://explorer.consensus.mainnet.lukso.network/) LUKSO Testnet - [LUKSO Testnet Execution Explorer](https://explorer.execution.testnet.lukso.network) - [LUKSO Testnet Consensus Explorer](https://explorer.consensus.testnet.lukso.network) ## ERC725 Inspect [ERC725 Inspect 📝🔍](https://erc725-inspect.lukso.tech/?network=lukso+mainnet) ([GitHub](https://github.com/lukso-network/tools-erc725-inspect)) is a web app that allows you to inspect the data key/values of an [ERC725Y](https://github.com/ERC725Alliance/ERC725/blob/main/docs/ERC-725.md#erc725x) compatible smart contract.
## Txs.app [Txs.app](https://txs.app) is a web app that deconstruct transactions on the LUKSO network. It displays interactions between Universal Profiles and smart contracts in plain human readable way, instead of using hex addresses and calldatas.
--- --- id: tools title: Tools sidebar_position: 1 --- import ReferenceCard from '@site/src/components/ReferenceCard'; import CodeBlock from '@theme/CodeBlock'; import styles from './tools.module.scss'; import SolidityLogo from '@site/static/img/tools/solidity-logo.png'; import FoundryLogo from '@site/static/img/tools/foundry-logo.png'; import EnvioLogo from '@site/static/img/tools/envio_logo.png'; import API3Logo from '@site/static/img/tools/api3-logo.png'; import DIALogo from '@site/static/img/tools/dia_logo.png'; import DappnodeLogo from '@site/static/img/tools/dappnode_logo.png'; import RemixLogo from '@site/static/img/tools/remix-ide.png'; import Gateway from '@site/static/img/tools/gateway-logo.png'; import ERC725 from '@site/static/img/tools/erc725-tools.png'; # Tools Explore the different tools available for developers to build dApps, smart contracts and protocols more easily on LUKSO. ## ERC725 Tools Inspector tool for developers to easily retrieve the list of metadata and permission from Universal Profile and Digital Assets, as well as encoding and decoding data. ## APIs
Deploy Universal Profiles easily, execute gas-free transactions up to a free monthly gas quota. Query easily any information about Universal Profiles and LSP7/8 Digital Assets. Available RPC endpoints for the Universal Profile Browser Extension 🧩.

## Smart Contracts
The reference Solidity implementation of the LUKSO LSP Standards. Available as whole umbrella package or individual packages for specific LSPs. Foundry repository template with pre-installed `@lukso/lsp-smart-contracts` package and example contracts ready to use. Write and deploy LSP smart contracts quickly and easily with the Remix IDE, a ready-to-use browser-based development environment.

## Javascript libraries
```bash npm install @erc725/erc725.js ``` Fetch any metadata easily from Universal Profiles, Tokens and NFTs. Includes helper functions to encode and prepare metadata before setting. ```bash npm install @lukso/lsp-utils ``` High level helper functions to `getProfileMetadata(...)`, `decodeAllowedCalls(...)`, `decodeAllowedERC725YDataKeys(...)` to read / encode metadata efficiently and avoid dealing with low level encoding / decoding. ```bash npm install @lukso/eip191-signer.js ``` Sign EIP-191 messages with a private key, to be used for preparing gas-less transactions for the relayer. ```bash npm install @lukso/up-provider ``` The @up-provider package helps building an Universal Everything integrated mini-apps for Grid. Universal Profile Integration for Web3-Onboard to easily integrate Universal Profiles in your dApp. Skeleton repository to create a transaction relayer service compliant with the [LSP15 Standard Transaction Relay Service API](../standards/accounts/lsp15-transaction-relayer-api.md). Create docker compose file to connect to LUKSO network.

## Management Tools
Manage controller keys on your Universal Profile. Migrate your profile to a new device, import into a new browser extension, or manually authorize a controller with specific permissions, Allowed Calls, and Allowed Data Keys.

## Explorers
Network explorer for the LUKSO networks. Visualize transactions happening live in the LUKSO network decoded in a human readable manner.
## Integrated partners :::caution Please note that the format of the data indexed by Envio might change in the future. This is also currently a free feature that might become a paid service in the future. ::: Third-party services and tools that are integrated with LUKSO to provide additional functionalities and services.
Indexer with playground to query data for Universal Profiles and Digital Assets in graphql. Oracle with different data feeds available for LUKSO. Start running your own validator to stake and earn rewards. Verifiable Random Function (VRF) coming to LUKSO, and it will be powered by Gateway.
--- --- id: integrations title: 🪢 Integrations sidebar_position: 5 --- # 🪢 Integrations > ⛓️ **Looking to integrate LUKSO? or already integrating?**
> Feel free to reach out to [growth@lukso.io](mailto:growth@lukso.io) if you are looking to be featured on this page. A list of services and projects that integrated the LUKSO network or deliver ecosystem tools. ## RPC Providers 🔏 :::info List of RPC URLs All the RPC URLs are listed under the [**Networks**](../networks/mainnet/parameters.md#3rd-party-rpc-providers) section. :::
Description & Features
Thirdweb provides a toolkit suite that includes public network endpoints, statistics, and several SDK integrations with plug-and-play components and hooks.
NOWNodes provides public RPC endpoints.
Envio is a indexing framework and data infrastructure provider speed-optimized for querying real-time and historical data.
SigmaCore RPC endpoint is powered by Sigmatic.
## Oracles 🔮
  Description & Features
DIA is a cross-chain oracle provider that directly aggregates market data from a wide range of sources. Its first-party data sourcing is thorough, enabling unparalleled transparency and customizability for resilient price feeds for 20,000+ assets including ERC20s, NFTs, RWAs, LSTs, BRC20s and more.

The DIA oracle on LUKSO is free of use, production-ready and comes with a predefined list of feeds.
Gateway is coming soon to LUKSO for supporting Verifiable Random Functions (VRF), allowing for generating randomization on-chain.
## Data Indexing 🗂️
  Description & Features
Envio is a feature-rich indexing framework and data infrastructure provider speed-optimized for querying real-time and historical data.
## On Ramp Providers 💳
  Description & Features
Transak is a crypto on-ramp marketplace that can be integrated easily by developers using their API and SDK, to enable to purchase crypto easily on a website and UI.
Ramp Network is a fiat-to-crypto and crypto-to-fiat gateway for web3 applications. It supports local payment methods globally, ensuring fast and secure transactions.​
## Staking Services 🪙
  Description & Features
Dappnode provides physical node machines and client software images for easy validator onboarding and maintenance.
Stakingverse Offers the following staking services for the LUKSO blockchain:
Universal.Page provides staking solutions through their Staking Vault.
## Toolings 🔧
  Description
Cookbook provides bundled smart contract libraries that can be directly used within Visual Studio Code, Foundry, Harthat, or Remix. Their webpage also features a ChatGPT integration to help learn and deploy LSPs.
Thirdweb provides a toolkit suite that includes public network endpoints, statistics, and several SDK integrations with plug-and-play components and hooks. Within the contract explorer, developers can search and deploy LSPs using their SDK or non-code web interface.
--- --- sidebar_position: 4 --- # Constants The [`constants.ts`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/packages/lsp-smart-contracts/constants.ts) file exposes many useful variables. ```ts import { INTERFACE_IDS, ERC1271, OPERATIONS, SupportedStandards, ERC725YDataKeys, PERMISSIONS, ALL_PERMISSIONS, LSP8_TOKEN_ID_TYPES, LSP25_VERSION, ErrorSelectors, EventSigHashes, FunctionSelectors, ContractsDocs, StateVariables, } from '@lukso/lsp-smart-contracts'; ``` The following additional typescript types are also available, including types for the JSON format of the LSP3 Profile and LSP4 Digital Asset metadata. ```ts import { LSP2ArrayKey, LSPSupportedStandard, LSP6PermissionName, LSP3ProfileMetadataJSON, LSP3ProfileMetadata, LSP4DigitalAssetMetadataJSON, LSP4DigitalAssetMetadata, ImageMetadata, LinkMetadata, AssetMetadata, } from '@lukso/lsp-smart-contracts'; ``` You can find the [interface IDs](../../../contracts/interface-ids) of the smart contracts in or more information in the [`README.md`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/README.md). --- --- sidebar_position: 2 --- # Contracts ABI You can import the [LUKSO smart contracts](../../contracts/introduction.md) ABIs from the `/artifacts` folder: ```javascript import LSP0ERC725Account from '@lukso/lsp-smart-contracts/artifacts/LSP0ERC725Account.json'; import LSP6KeyManager from '@lukso/lsp-smart-contracts/artifacts/LSP6KeyManager.json'; import LSP9Vault from '@lukso/lsp-smart-contracts/artifacts/LSP9Vault.json'; // etc. const accountContract = new web3.contract(LSP0ERC725Account.abi, "") ``` --- --- sidebar_position: 1 --- # Getting Started - [GitHub: `lukso-network/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts) - [NPM: `@lukso/lsp-smart-contracts`](https://www.npmjs.com/package/@lukso/lsp-smart-contracts) This library gives you an easy access to all LUKSO smart contracts in Solidity, JSON ABIs, constants, etc. ## Install ```bash npm install @lukso/lsp-smart-contracts ``` :::tip You can find more information and examples on our [smart contract implementation page](../../contracts/introduction.md). ::: --- --- sidebar_position: 3 --- # Solidity Contracts The solidity sources of the [LUKSO smart contracts](../../contracts/introduction.md) are available in the `/contracts` folder. ```solidity import "@lukso/lsp-smart-contracts/contracts/LSP0ERC725Account/LSP0ERC725Account.sol"; contract MyAccount is LSP0ERC725Account { constructor(address _newOwner) LSP0ERC725Account(_newOwner) { } } ``` --- --- sidebar_position: 5 --- # Working with LSPs on Remix IDE This guide will walk you through the process of building and deploying LSP smart contracts using [Remix IDE](https://remix.ethereum.org/). ## Setting Up Dependencies First, create a `package.json` file with the required LSP smart contract dependencies to the root of your project: ```json { "dependencies": { "@erc725/smart-contracts-v8": "npm:@erc725/smart-contracts@8.0.0", "@erc725/smart-contracts": "^7.0.0", "@openzeppelin/contracts": "^4.9.3", "@lukso/lsp1-contracts": "~0.15.0", "@lukso/lsp2-contracts": "~0.15.0", "@lukso/lsp14-contracts": "~0.15.0", "@lukso/lsp17contractextension-contracts": "~0.15.0", "@lukso/lsp20-contracts": "~0.15.0" } } ``` ## Deploying using the Universal Profile browser extension To deploy your smart contract using the Universal Profile browser extension: - Click on the _Customize this list_ option in the Environment field - Activate the option of Injected Provider - Universal Profile under the _Deploy using a Browser Extension_. ## Verifying the Contract To verify your contract on the LUKSO Testnet: 1. **Enable Contract Verification** - Open the _Plugin Manager_ in Remix - Activate the _Contract Verification_ tool - The verification icon will appear in the left menu 2. **Configure Blockscout API** - Navigate to the Settings tab - Add the LUKSO Testnet Blockscout API: ``` https://explorer.execution.testnet.lukso.network/api ``` 3. **Verify Contract** - Go to the Verify tab - Fill in the following details: - Chain: LUKSO Testnet (4201) - Contract Address: _Your deployed contract address_ - Contract Name: _Select your contract's Solidity file_ - Enter the same constructor parameters used during deployment - Ensure Blockscout is selected - Click the "Verify" button After verification, your contract will be visible and verified on the LUKSO Testnet explorer. --- --- title: 🔑 Authorize Controller sidebar_position: 1 --- # Authorize Controller
The [Authorize Controller](https://authorize.universalprofile.cloud/) tool lets you manage controller keys on your Universal Profile. Use it to grant permissions to new controllers, migrate your profile to a new device, or import your profile into a new browser extension. 🔗 **[authorize.universalprofile.cloud](https://authorize.universalprofile.cloud/)** :::info Keep Your Initial Controller Key Safe The controller key your Universal Profile was originally created with is important — it's required if you ever want to deploy your profile across multiple networks. This key lives in the device where you first created your profile (the mobile app or the browser extension). **Back it up** using the backup feature in your app: - **UP Browser Extension** — use the built-in backup feature to export your key - **UP Mobile App** — backup feature coming soon ::: ## Use Cases ### Migrate to a New Device If you're setting up a new computer or phone and want to access your existing Universal Profile: 1. Install the [Universal Profile Browser Extension](https://chromewebstore.google.com/detail/universal-profiles/abpickdkkbnbcoepogfhkhennhfhehfn) on the new device 2. Open the Authorize tool on your **old device** (where you still have access) 3. Connect your Universal Profile 4. Enter the new extension's controller address and select the permissions you want to grant 5. Confirm the transaction — your profile is now accessible from both devices ### Import into Browser Extension When you have a Universal Profile that was created outside the browser extension (e.g., via a dApp or programmatically), you can import it: 1. Open the Authorize tool and connect via **WalletConnect** or the **UP Browser Extension** 2. Enter the controller address from your browser extension 3. Grant the necessary permissions 4. Your profile will now appear in the extension ### Manually Authorize a Controller For advanced users who need to grant specific permissions to any address: 1. Connect your Universal Profile 2. Enter the controller address 3. Select individual permissions (e.g., `CALL`, `SETDATA`, `TRANSFERVALUE`) 4. Optionally configure **Allowed Calls** to restrict which contracts the controller can interact with 5. Optionally configure **Allowed Data Keys** to restrict which ERC725Y data keys the controller can modify 6. Confirm the transaction ## Features - **Connect via UP Browser Extension or WalletConnect** — use whichever wallet has access to your profile - **Permission selector** — pick exactly which [LSP6 permissions](../../standards/access-control/lsp6-key-manager.md) to grant - **Allowed Calls** — restrict a controller to specific contracts, interfaces, or functions - **Allowed Data Keys** — restrict which data keys a controller can read or write - **Smart array management** — reuses empty slots in the controller array to save gas ## How It Works The tool writes data to your Universal Profile's [ERC725Y](../../standards/erc725.md) storage using `setDataBatch` on the [LSP0 ERC725Account](../../standards/accounts/lsp0-erc725account.md). It sets: - The controller's address in the `AddressPermissions[]` array - The controller's permissions under `AddressPermissions:Permissions:
` - Optionally, `AddressPermissions:AllowedCalls:
` and `AddressPermissions:AllowedERC725YDataKeys:
` All of this is managed by the profile's [LSP6 Key Manager](../../standards/access-control/lsp6-key-manager.md), which enforces the permissions on every transaction.