From c1fc193f4cc65d16143df477696962e7ce14cc84 Mon Sep 17 00:00:00 2001 From: CJ42 Date: Mon, 3 Jul 2023 17:53:24 +0100 Subject: [PATCH 1/2] docs: update LSP7 Natspecs of public functions --- .../LSP7DigitalAsset/ILSP7DigitalAsset.sol | 160 ++++++++++-------- .../LSP7DigitalAsset/LSP7DigitalAsset.sol | 6 +- .../LSP7DigitalAsset/LSP7DigitalAssetCore.sol | 156 ++++++++++------- contracts/LSP7DigitalAsset/LSP7Errors.sol | 12 +- 4 files changed, 193 insertions(+), 141 deletions(-) diff --git a/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol b/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol index 6a977e7de..39182ebe0 100644 --- a/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol +++ b/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol @@ -15,14 +15,13 @@ interface ILSP7DigitalAsset is IERC165, IERC725Y { // --- Events /** - * @dev Emitted when `amount` tokens is transferred from `from` to `to`. - * @param operator The address of operator sending tokens - * @param from The address which tokens are sent - * @param to The receiving address - * @param amount The amount of tokens transferred - * @param allowNonLSP1Recipient When set to TRUE, `to` may be any address but - * when set to FALSE `to` must be a contract that supports LSP1 UniversalReceiver - * @param data Additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses + * @dev Emitted when the `from` transferred successfully `amount` of tokens to `to`. + * @param operator The address of the operator that executed the transfer. + * @param from The address which tokens were sent from (balance decreased by `-amount`). + * @param to The address that received the tokens (balance increased by `+amount`). + * @param amount The amount of tokens transferred. + * @param allowNonLSP1Recipient if the transferred enforced the `to` recipient address to be a contract that implements the LSP1 standard or not. + * @param data Any additional data included by the caller during the transfer, and sent in the LSP1 hooks to the `from` and `to` addresses. */ event Transfer( address indexed operator, @@ -46,7 +45,7 @@ interface ILSP7DigitalAsset is IERC165, IERC725Y { ); /** - * @dev Emitted when `tokenOwner` disables `operator` for `amount` tokens. + * @dev Emitted when `tokenOwner` disables `operator` for `amount` tokens and set its {`authorizedAmountFor(...)`} to `0`. * @param operator The address revoked from operating * @param tokenOwner The token owner */ @@ -55,78 +54,83 @@ interface ILSP7DigitalAsset is IERC165, IERC725Y { // --- Token queries /** - * @dev Returns the number of decimals used to get its user representation - * If the contract represents a NFT then 0 SHOULD be used, otherwise 18 is the common value + * @dev 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 wiil be `0`. Otherwise `18` is the common value. * - * NOTE: This information is only used for _display_ purposes: it in + * @custom:notice This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {balanceOf} and {transfer}. + * + * @return the number of decimals. If `0` is returned, the asset is non-divisible. */ function decimals() external view returns (uint8); /** - * @dev Returns the number of existing tokens. - * @return The number of existing tokens + * @dev Returns the number of existing tokens that have been minted in this contract. + * @return The number of existing tokens. */ function totalSupply() external view returns (uint256); // --- Token owner queries /** - * @dev Returns the number of tokens owned by `tokenOwner`. - * @param tokenOwner The address to query - * @return The number of tokens owned by this address + * @dev Get the number of tokens owned by `tokenOwner`. + * If the token is divisible (the `{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 + * ``` + * + * @param tokenOwner The address of the token holder to query the balance for. + * @return The amount of tokens owned by `tokenOwner`. */ function balanceOf(address tokenOwner) external view returns (uint256); // --- Operator functionality /** - * @param operator The address to authorize as an operator. - * @param amount The amount of tokens operator has access to. - * @dev Sets `amount` as the amount of tokens `operator` address has access to from callers tokens. - * - * To avoid front-running and Allowance Double-Spend Exploit when - * increasing or decreasing the authorized amount of an operator, - * it is advised to: - * 1. call {revokeOperator} first, and - * 2. then re-call {authorizeOperator} with the new amount + * @dev Sets an `amount` of tokens that an `operator` has access from the caller's balance (allowance). See {authorizedAmountFor}. * - * for more information, see: - * https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/ - * - * - * See {authorizedAmountFor}. - * - * Requirements + * @param operator The address to authorize as an operator. + * @param amount The allowance amount of tokens operator has access to. * + * @custom:requirements * - `operator` cannot be the zero address. * - * Emits an {AuthorizedOperator} event. + * @custom:events {AuthorizedOperator} when allowance is given to a new operator or + * an existing operator's allowance is updated. */ function authorizeOperator(address operator, uint256 amount) external; /** - * @param operator The address to revoke as an operator. - * @dev Removes `operator` address as an operator of callers tokens. - * - * See {authorizedAmountFor}. + * @dev Removes the `operator` address as an operator of callers tokens, disallowing it to send any amount of tokens + * on behalf of the token owner (the caller of the function `msg.sender`). See also {authorizedAmountFor}. * - * Requirements + * @param operator The address to revoke as an operator. * + * @custom:requirements + * - `operator` cannot be calling address. * - `operator` cannot be the zero address. * - * Emits a {RevokedOperator} event. + * @custom:events {RevokedOperator} event with address of the operator being revoked for the caller (token holder). */ function revokeOperator(address operator) external; /** - * @param operator The address to query operator status for. - * @param tokenOwner The token owner. - * @return The amount of tokens `operator` address has access to from `tokenOwner`. - * @dev Returns amount of tokens `operator` address has access to from `tokenOwner`. - * Operators can send and burn tokens on behalf of their owners. The tokenOwner is their own - * operator. + * @dev Get the amount of tokens `operator` address has access to from `tokenOwner`. + * Operators can send and burn tokens on behalf of their owners. + * + * @param operator The operator's address to query the authorized amount for. + * @param tokenOwner The token owner that `operator` has allowance on. + * + * @return The amount of tokens the `operator`'s address has access on the `tokenOwner`'s balance. + * + * @custom:info If this function is called with the same address for `operator` and `tokenOwner`, it will simply read the `tokenOwner`'s balance + * (since a tokenOwner is its own operator). */ function authorizedAmountFor( address operator, @@ -136,25 +140,35 @@ interface ILSP7DigitalAsset is IERC165, IERC725Y { // --- Transfer functionality /** - * @param from The sending address. - * @param to The receiving address. - * @param amount The amount of tokens to transfer. - * @param allowNonLSP1Recipient When set to TRUE, to may be any address but - * when set to FALSE to must be a contract that supports LSP1 UniversalReceiver - * @param data Additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. - * - * @dev Transfers `amount` of tokens from `from` to `to`. The `allowNonLSP1Recipient` parameter will be used - * when notifying the token sender and receiver. + * @dev Transfers an `amount` of tokens from the `from` address to the `to` address and notify both sender and recipients via the LSP1 {`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}). * - * Requirements: + * @param from The sender address. + * @param to The recipient address. + * @param amount The amount of tokens to transfer. + * @param allowNonLSP1Recipient 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. + * @param data Any additional data the caller wants included in the emitted event, and sent in the hooks of the `from` and `to` addresses. * + * @custom:requirements * - `from` cannot be the zero address. * - `to` cannot be the zero address. - * - `amount` tokens must be owned by `from`. - * - If the caller is not `from`, it must be an operator for `from` with access to at least - * `amount` tokens. + * - `from` and `to` cannot be the same address (`from` cannot send tokens to itself). + * - `from` MUST have a balance of at least `amount` tokens. + * - If the caller is not `from`, it must be an operator for `from` with an allowance of at least `amount` of tokens. + * + * @custom:events + * - {Transfer} event when tokens get successfully transferred. + * - if the transfer is triggered by an operator, either the {AuthorizedOperator} event will be emitted with the updated allowance or the {RevokedOperator} + * event will be emitted if the operator has no more allowance left. + * + * @custom:hint The `allowNonLSP1Recipient` parameter **MUST be set to `true`** to transfer tokens to Externally Owned Accounts (EOAs) + * or contracts that do not implement the LSP1 Universal Receiver Standard. Otherwise the function will revert making the transfer fail. * - * Emits a {Transfer} event. + * @custom:info if the `to` address is a contract that implements LSP1, it will always be notified via its `universalReceiver(...)` function, regardless if `allowNonLSP1Recipient` is set to `true` or `false`. + * + * @custom:warning Be aware that when either the sender or the recipient can have logic that revert in their `universalReceiver(...)` function when being notified. + * This even if the `allowNonLSP1Recipient` was set to `true`. */ function transfer( address from, @@ -165,26 +179,24 @@ interface ILSP7DigitalAsset is IERC165, IERC725Y { ) external; /** - * @param from The list of sending addresses. - * @param to The list of receiving addresses. - * @param amount The amount of tokens to transfer. - * @param allowNonLSP1Recipient When set to TRUE, to may be any address but - * when set to FALSE to must be a contract that supports LSP1 UniversalReceiver - * @param data Additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. + * @dev Same as {`transfer(...)`} but transfer multiple tokens based on the arrays of `from`, `to`, `amount`. * - * @dev Transfers many tokens based on the list `from`, `to`, `amount`. If any transfer fails - * the call will revert. + * @custom:info If any transfer in the batch fail or revert, the whole call will revert. * - * Requirements: + * @param from An array of sending addresses. + * @param to An array of receiving addresses. + * @param amount An array of amount of tokens to transfer for each `from -> to` transfer. + * @param allowNonLSP1Recipient 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. + * @param data An array of additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses. * - * - `from`, `to`, `amount` lists are the same length. + * @custom:requirements + * - `from`, `to`, `amount` lists MUST be of the same length. * - no values in `from` can be the zero address. * - no values in `to` can be the zero address. - * - each `amount` tokens must be owned by `from`. - * - If the caller is not `from`, it must be an operator for `from` with access to at least - * `amount` tokens. + * - each `amount` tokens MUST be owned by `from`. + * - for each transfer, if the caller is not `from`, it MUST be an operator for `from` with access to at least `amount` tokens. * - * Emits {Transfer} events. + * @custom:events {Transfer} event **for each token transfer**. */ function transferBatch( address[] memory from, diff --git a/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol b/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol index 42ff10fcc..abf0ce915 100644 --- a/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol +++ b/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol @@ -15,10 +15,10 @@ import {LSP7DigitalAssetCore} from "./LSP7DigitalAssetCore.sol"; import {_INTERFACEID_LSP7} from "./LSP7Constants.sol"; /** - * @title LSP7DigitalAsset contract + * @title Implementation of a LSP7 Digital Asset, a contract that represents a fungible token. * @author Matthew Stevens - * @dev Implementation of a LSP7 compliant contract. * + * @dev 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} * For a generic mechanism, see {LSP7Mintable}. @@ -44,7 +44,7 @@ abstract contract LSP7DigitalAsset is } /** - * @dev See {IERC165-supportsInterface}. + * @inheritdoc IERC165 */ function supportsInterface( bytes4 interfaceId diff --git a/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol b/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol index 205919325..d8424e07e 100644 --- a/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol +++ b/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol @@ -29,8 +29,8 @@ import { * * This contract implement the core logic of the functions for the {ILSP7DigitalAsset} interface. * - * Similar to ERC20, the non-standard {decreaseAllowance} and {increaseAllowance} - * functions have been added to mitigate the well-known issues around setting allowances. + * Similar to ERC20, the non-standard {increaseAllowance} and {decreaseAllowance} functions + * have been added to mitigate the well-known issues around setting allowances. */ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { // --- Storage @@ -78,15 +78,14 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { /** * @inheritdoc ILSP7DigitalAsset * - * @dev To avoid front-running and Allowance Double-Spend Exploit when - * increasing or decreasing the authorized amount of an operator, - * it is advised to: - * 1. call {revokeOperator} first, and - * 2. then re-call {authorizeOperator} with the new amount + * @custom:danger To avoid front-running and Allowance Double-Spend Exploit when + * increasing or decreasing the authorized amount of an operator, it is advised to: * - * for more information, see: - * https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/ + * 1. either call {`revokeOperator`} first, and then re-call {`authorizeOperator`} with the new amount. + * 2. or use the non-standard functions {`increaseAllowance`} or {`decreaseAllowance`}. * + * For more information, see: + * https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/ */ function authorizeOperator( address operator, @@ -185,20 +184,24 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { } /** - * @notice Increase the allowance of `operator` by +`addedAmount` - * @dev Atomically increases the allowance granted to `operator` by the caller. + * @custom:info This is a non-standard function, not part of the LSP7 standard interface. + * It has been added in the LSP7 contract implementation so that it can be used as a prevention mechanism + * against double spending allowance vulnerability. * - * This is an alternative approach to {authorizeOperator} that can be used as a mitigation - * for problems described in {ILSP7DigitalAsset}. + * @notice Increase the allowance of `operator` by +`addedAmount` * - * Emits an {AuthorizedOperator} event indicating the updated allowance. + * @dev Atomically increases the allowance granted to `operator` by the caller. + * This is an alternative approach to {`authorizeOperator(...)`} that can be used as a mitigation + * for the double spending allowance problem. * * @param operator the operator to increase the allowance for `msg.sender` * @param addedAmount the additional amount to add on top of the current operator's allowance * - * @dev Requirements: + * @custom:requirements * - `operator` cannot be the same address as `msg.sender` * - `operator` cannot be the zero address. + * + * @custom:events {AuthorizedOperator} indicating the updated allowance */ function increaseAllowance( address operator, @@ -212,22 +215,27 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { } /** + * @custom:info This is a non-standard function, not part of the LSP7 standard interface. + * It has been added in the LSP7 contract implementation so that it can be used as a prevention mechanism + * against the double spending allowance vulnerability. + * * @notice Decrease the allowance of `operator` by -`substractedAmount` + * * @dev Atomically decreases the allowance granted to `operator` by the caller. - * This is an alternative approach to {authorizeOperator} that can be used as a mitigation - * for problems described in {ILSP7DigitalAsset} + * This is an alternative approach to {`authorizeOperator(...)`} that can be used as a mitigation + * for the double spending allowance problem. * - * Emits: - * - an {AuthorizedOperator} event indicating the updated allowance after decreasing it. - * - a {RevokeOperator} event if `substractedAmount` is the full allowance, - * indicating `operator` does not have any allowance left for `msg.sender`. + * @custom:events + * - {AuthorizedOperator} event indicating the updated allowance after decreasing it. + * - {RevokeOperator} event if `substractedAmount` is the full allowance, + * indicating `operator` does not have any alauthorizedAmountForlowance left for `msg.sender`. * * @param operator the operator to decrease allowance for `msg.sender` * @param substractedAmount the amount to decrease by in the operator's allowance. * - * @dev Requirements: + * @custom:requirements * - `operator` cannot be the zero address. - * - operator` must have allowance for the caller of at least `substractedAmount`. + * - `operator` must have allowance for the caller of at least `substractedAmount`. */ function decreaseAllowance( address operator, @@ -248,17 +256,16 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { } /** - * @dev Changes token `amount` the `operator` has access to from `tokenOwner` tokens. If the - * amount is zero then the operator is being revoked, otherwise the operator amount is being - * modified. + * @dev Changes token `amount` the `operator` has access to from `tokenOwner` tokens. + * If the amount is zero then the operator is being revoked, otherwise the operator amount is being modified. * - * See {authorizedAmountFor}. - * - * Emits either {AuthorizedOperator} or {RevokedOperator} event. - * - * Requirements + * @custom:events + * - {RevokedOperator} event when operator's allowance is set to `0`. + * - {AuthorizedOperator} event when operator's allowance is set to any other amount. * + * @custom:requirements * - `operator` cannot be the zero address. + * - `operator` cannot be the same address as `tokenOwner`. */ function _updateOperator( address tokenOwner, @@ -283,13 +290,17 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { } /** - * @dev Mints `amount` tokens and transfers it to `to`. + * @dev Mints `amount` of tokens and transfers it to `to`. * - * Requirements: + * @param to the address to mint tokens for. + * @param amount the amount of tokens to mint. + * @param allowNonLSP1Recipient a boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. + * @param data Additional data the caller wants included in the emitted {`Transfer`} event, and sent in the LSP1 hook to the `to` address. * + * @custom:requirements * - `to` cannot be the zero address. * - * Emits a {Transfer} event. + * @custom:events {`Transfer`} event with `address(0)` as `from`. */ function _mint( address to, @@ -324,16 +335,27 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { } /** - * @dev Destroys `amount` tokens. + * @dev 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`} + * function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive + * all the parameters in the calldata packed encoded. * - * Requirements: + * Any logic in the {`_beforeTokenTransfer`} function will run before updating the balances. * + * @param from the address to burn tokens from its balance. + * @param amount the amount of tokens to burn. + * @param data Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. + * + * @custom: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`. + * + * @custom:requirements * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens. * - If the caller is not `from`, it must be an operator for `from` with access to at least * `amount` tokens. * - * Emits a {Transfer} event. + * @custom:events {Transfer} event with `address(0)` as the `to` address */ function _burn( address from, @@ -367,7 +389,7 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { _beforeTokenTransfer(from, address(0), amount); - // tokens being burned + // tokens being burnt _existingTokens -= amount; _tokenOwnerBalances[from] -= amount; @@ -384,17 +406,27 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { } /** - * @dev Transfers `amount` tokens from `from` to `to`. + * @dev Transfer tokens from `from` to `to` by decreasing the balance of `from` by `-amount` and increasing the balance + * of `to` by `+amount`. * - * Requirements: + * Both the sender and recipient will be notified of the token transfer through the LSP1 {`universalReceiver`} + * function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive + * all the parameters in the calldata packed encoded. * - * - `to` cannot be the zero address. + * Any logic in the {`_beforeTokenTransfer`} function will run before updating the balances. + * + * @param from the address to decrease the balance. + * @param to the address to increase the balance. + * @param amount the amount of tokens to transfer from `from` to `to`. + * @param allowNonLSP1Recipient a boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. + * @param data Additional data the caller wants included in the emitted event, and sent in the LSP1 hook to the `from` and `to` address. + * + * @custom:requirements * - `from` cannot be the zero address. - * - `from` must have at least `amount` tokens. - * - If the caller is not `from`, it must be an operator for `from` with access to at least - * `amount` tokens. + * - `to` cannot be the zero address. + * - `from` must have at least `amount` of tokens. * - * Emits a {Transfer} event. + * @custom:events {Transfer} event. */ function _transfer( address from, @@ -428,16 +460,12 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { } /** - * @dev Hook that is called before any token transfer. This includes minting - * and burning. + * @dev Hook that is called before any token transfer, including minting and burning. + * Allows to run custom logic before updating balances and notifiying sender/recipient by overriding this function. * - * Calling conditions: - * - * - When `from` and `to` are both non-zero, ``from``'s `amount` tokens will be - * transferred to `to`. - * - When `from` is zero, `amount` tokens will be minted for `to`. - * - When `to` is zero, ``from``'s `amount` tokens will be burned. - * - `from` and `to` are never both zero. + * @param from The sender address + * @param to The recipient address + * @param amount The amount of token to transfer */ function _beforeTokenTransfer( address from, @@ -446,8 +474,12 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { ) internal virtual {} /** - * @dev An attempt is made to notify the token sender about the `amount` tokens changing owners using - * LSP1 interface. + * @dev Attempt to notify the token sender `from` about the `amount` of tokens being transferred. + * This is done by calling its {`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. + + * @param from The address to call the {`universalReceiver`} function on. + * @param lsp1Data the data to be sent to the `from` address in the `universalReceiver` call. */ function _notifyTokenSender( address from, @@ -467,10 +499,16 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { } /** - * @dev An attempt is made to notify the token receiver about the `amount` tokens changing owners - * using LSP1 interface. When allowNonLSP1Recipient is FALSE the token receiver MUST support LSP1. + * @dev Attempt to notify the token receiver `to` about the `amount` tokens being received. + * This is done by calling its {`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 `allowNonLSP1Recipient` boolean flag. + * - if `allowNonLSP1Recipient` is set to `true`, nothing will happen and no notification will be sent. + * - if `allowNonLSP1Recipient` is set to `false, the transaction will revert. * - * The receiver may revert when the token being sent is not wanted. + * @param to The address to call the {`universalReceiver`} function on. + * @param allowNonLSP1Recipient a boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. + * @param lsp1Data the data to be sent to the `to` address in the `universalReceiver` call. */ function _notifyTokenReceiver( address to, diff --git a/contracts/LSP7DigitalAsset/LSP7Errors.sol b/contracts/LSP7DigitalAsset/LSP7Errors.sol index 308cf4dfc..b01947b81 100644 --- a/contracts/LSP7DigitalAsset/LSP7Errors.sol +++ b/contracts/LSP7DigitalAsset/LSP7Errors.sol @@ -29,7 +29,10 @@ error LSP7AmountExceedsAuthorizedAmount( error LSP7CannotUseAddressZeroAsOperator(); /** - * @dev reverts when one tries to send tokens to or from the zero address. + * @dev reverts when trying to: + * - mint tokens to the zero address. + * - burn tokens from the zero address. + * - transfer tokens from or to the zero address. */ error LSP7CannotSendWithAddressZero(); @@ -39,7 +42,7 @@ error LSP7CannotSendWithAddressZero(); error LSP7CannotSendToSelf(); /** - * @dev reverts when the parameters used for `transferBatch` have different lengths. + * @dev reverts when the array parameters used in {transferBatch} have different lengths. */ error LSP7InvalidTransferBatch(); @@ -52,8 +55,7 @@ error LSP7NotifyTokenReceiverContractMissingLSP1Interface( ); /** - * @dev reverts if the `tokenReceiver` is an EOA - * when minting or transferring tokens with `bool allowNonLSP1Recipient` set as `false`. + * @dev reverts if the `tokenReceiver` is an EOA when minting or transferring tokens with `bool allowNonLSP1Recipient` set as `false`. */ error LSP7NotifyTokenReceiverIsEOA(address tokenReceiver); @@ -63,6 +65,6 @@ error LSP7NotifyTokenReceiverIsEOA(address tokenReceiver); error LSP7TokenOwnerCannotBeOperator(); /** - * @dev Reverts when trying to decrease an operator's allowance to more than his current allowance + * @dev Reverts when trying to decrease an operator's allowance to more than its current allowance. */ error LSP7DecreasedAllowanceBelowZero(); From 1b648cfea9550eb8cbb542105ed39f2c9ab33868 Mon Sep 17 00:00:00 2001 From: CJ42 Date: Tue, 4 Jul 2023 19:11:28 +0100 Subject: [PATCH 2/2] add auto generated docs for LSP7DigitalAsset.md --- .../LSP7DigitalAsset/ILSP7DigitalAsset.sol | 2 +- .../LSP7DigitalAsset/LSP7DigitalAssetCore.sol | 30 +- .../LSP7DigitalAsset/LSP7DigitalAsset.md | 1302 +++++++++++++++++ 3 files changed, 1318 insertions(+), 16 deletions(-) create mode 100644 docs/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md diff --git a/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol b/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol index 39182ebe0..a17060c78 100644 --- a/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol +++ b/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol @@ -76,7 +76,7 @@ interface ILSP7DigitalAsset is IERC165, IERC725Y { /** * @dev Get the number of tokens owned by `tokenOwner`. - * If the token is divisible (the `{decimals}` function returns `18`), the amount returned should be divided + * If the token is divisible (the {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:_ diff --git a/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol b/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol index d8424e07e..ee8937ba2 100644 --- a/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol +++ b/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol @@ -81,8 +81,8 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { * @custom:danger To avoid front-running and Allowance Double-Spend Exploit when * increasing or decreasing the authorized amount of an operator, it is advised to: * - * 1. either call {`revokeOperator`} first, and then re-call {`authorizeOperator`} with the new amount. - * 2. or use the non-standard functions {`increaseAllowance`} or {`decreaseAllowance`}. + * 1. either call {revokeOperator} first, and then re-call {authorizeOperator} with the new amount. + * 2. or use the non-standard functions {increaseAllowance} or {decreaseAllowance}. * * For more information, see: * https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/ @@ -191,7 +191,7 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { * @notice Increase the allowance of `operator` by +`addedAmount` * * @dev Atomically increases the allowance granted to `operator` by the caller. - * This is an alternative approach to {`authorizeOperator(...)`} that can be used as a mitigation + * This is an alternative approach to {authorizeOperator} that can be used as a mitigation * for the double spending allowance problem. * * @param operator the operator to increase the allowance for `msg.sender` @@ -222,7 +222,7 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { * @notice Decrease the allowance of `operator` by -`substractedAmount` * * @dev Atomically decreases the allowance granted to `operator` by the caller. - * This is an alternative approach to {`authorizeOperator(...)`} that can be used as a mitigation + * This is an alternative approach to {authorizeOperator} that can be used as a mitigation * for the double spending allowance problem. * * @custom:events @@ -295,12 +295,12 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { * @param to the address to mint tokens for. * @param amount the amount of tokens to mint. * @param allowNonLSP1Recipient a boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. - * @param data Additional data the caller wants included in the emitted {`Transfer`} event, and sent in the LSP1 hook to the `to` address. + * @param data Additional data the caller wants included in the emitted {Transfer} event, and sent in the LSP1 hook to the `to` address. * * @custom:requirements * - `to` cannot be the zero address. * - * @custom:events {`Transfer`} event with `address(0)` as `from`. + * @custom:events {Transfer} event with `address(0)` as `from`. */ function _mint( address to, @@ -337,11 +337,11 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { /** * @dev 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`} + * Both the sender and recipient will be notified of the token transfer through the LSP1 {universalReceiver} * function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive * all the parameters in the calldata packed encoded. * - * Any logic in the {`_beforeTokenTransfer`} function will run before updating the balances. + * Any logic in the {_beforeTokenTransfer} function will run before updating the balances. * * @param from the address to burn tokens from its balance. * @param amount the amount of tokens to burn. @@ -409,11 +409,11 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { * @dev 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`} + * Both the sender and recipient will be notified of the token transfer through the LSP1 {universalReceiver} * function, if they are contracts that support the LSP1 interface. Their `universalReceiver` function will receive * all the parameters in the calldata packed encoded. * - * Any logic in the {`_beforeTokenTransfer`} function will run before updating the balances. + * Any logic in the {_beforeTokenTransfer} function will run before updating the balances. * * @param from the address to decrease the balance. * @param to the address to increase the balance. @@ -475,10 +475,10 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { /** * @dev Attempt to notify the token sender `from` about the `amount` of tokens being transferred. - * This is done by calling its {`universalReceiver`} function with the `_TYPEID_LSP7_TOKENSSENDER` as typeId, if `from` is a contract that supports the LSP1 interface. + * This is done by calling its {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. - * @param from The address to call the {`universalReceiver`} function on. + * @param from The address to call the {universalReceiver} function on. * @param lsp1Data the data to be sent to the `from` address in the `universalReceiver` call. */ function _notifyTokenSender( @@ -500,15 +500,15 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { /** * @dev Attempt to notify the token receiver `to` about the `amount` tokens being received. - * This is done by calling its {`universalReceiver`} function with the `_TYPEID_LSP7_TOKENSRECIPIENT` as typeId, if `to` is a contract that supports the LSP1 interface. + * This is done by calling its {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 `allowNonLSP1Recipient` boolean flag. * - if `allowNonLSP1Recipient` is set to `true`, nothing will happen and no notification will be sent. * - if `allowNonLSP1Recipient` is set to `false, the transaction will revert. * - * @param to The address to call the {`universalReceiver`} function on. + * @param to The address to call the {universalReceiver} function on. * @param allowNonLSP1Recipient a boolean that describe if transfer to a `to` address that does not support LSP1 is allowed or not. - * @param lsp1Data the data to be sent to the `to` address in the `universalReceiver` call. + * @param lsp1Data the data to be sent to the `to` address in the `universalReceiver(...)` call. */ function _notifyTokenReceiver( address to, diff --git a/docs/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md b/docs/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md new file mode 100644 index 000000000..eecfc5fbb --- /dev/null +++ b/docs/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md @@ -0,0 +1,1302 @@ + + + +# LSP7DigitalAsset + +:::info Standard Specifications + +[`LSP-7-DigitalAsset`](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md) + +::: +:::info Solidity implementation + +[`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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. + +### authorizeOperator + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#authorizeoperator) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `authorizeOperator(address,uint256)` +- Function selector: `0x47980aa3` + +::: + +:::danger + +To avoid front-running and Allowance Double-Spend Exploit when increasing or decreasing the authorized amount of an operator, it is advised to: 1. either call {revokeOperator} first, and then re-call {authorizeOperator} with the new amount. 2. or use the non-standard functions {increaseAllowance} or {decreaseAllowance}. For more information, see: https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/ + +::: + +```solidity +function authorizeOperator( + address operator, + uint256 amount +) external nonpayable; +``` + +Sets an `amount` of tokens that an `operator` has access from the caller's balance (allowance). See [`authorizedAmountFor`](#authorizedamountfor). + +#### Parameters + +| Name | Type | Description | +| ---------- | :-------: | ------------------------------------------------------ | +| `operator` | `address` | The address to authorize as an operator. | +| `amount` | `uint256` | The allowance amount of tokens operator has access to. | + +
+ +### authorizedAmountFor + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#authorizedamountfor) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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/tree/main/LSPs/LSP-7-DigitalAsset.md#balanceof) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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`. | + +
+ +### decimals + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#decimals) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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 wiil 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/tree/main/LSPs/LSP-7-DigitalAsset.md#decreaseallowance) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `decreaseAllowance(address,uint256)` +- Function selector: `0xa457c2d7` + +::: + +:::info + +This is a non-standard function, not part of the LSP7 standard interface. It has been added in the LSP7 contract implementation so that it can be used as a prevention mechanism against the double spending allowance vulnerability. + +::: + +```solidity +function decreaseAllowance( + address operator, + uint256 substractedAmount +) external nonpayable; +``` + +_Decrease the allowance of `operator` by -`substractedAmount`_ + +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. + +
+ +**Requirements:** + +- `operator` cannot be the zero address. +- `operator` must have allowance for the caller of at least `substractedAmount`. + +
+ +
+ +**Emitted events:** + +- [`AuthorizedOperator`](#authorizedoperator) event indicating the updated allowance after decreasing it. +- [`RevokeOperator`](#revokeoperator) event if `substractedAmount` is the full allowance, indicating `operator` does not have any alauthorizedAmountForlowance left for `msg.sender`. + +
+ +#### Parameters + +| Name | Type | Description | +| ------------------- | :-------: | ------------------------------------------------------ | +| `operator` | `address` | the operator to decrease allowance for `msg.sender` | +| `substractedAmount` | `uint256` | the amount to decrease by in the operator's allowance. | + +
+ +### getData + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#getdata) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `getData(bytes32)` +- Function selector: `0x54f6127f` + +::: + +```solidity +function getData(bytes32 dataKey) external view returns (bytes dataValue); +``` + +_Gets singular data at a given `dataKey`_ + +#### Parameters + +| Name | Type | Description | +| --------- | :-------: | ------------------------------- | +| `dataKey` | `bytes32` | The key which value to retrieve | + +#### Returns + +| Name | Type | Description | +| ----------- | :-----: | -------------------------- | +| `dataValue` | `bytes` | The data stored at the key | + +
+ +### getDataBatch + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#getdatabatch) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `getDataBatch(bytes32[])` +- Function selector: `0xdedff9c6` + +::: + +```solidity +function getDataBatch( + bytes32[] dataKeys +) external view returns (bytes[] dataValues); +``` + +_Gets array of data for multiple given keys_ + +#### 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 | + +
+ +### increaseAllowance + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#increaseallowance) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `increaseAllowance(address,uint256)` +- Function selector: `0x39509351` + +::: + +:::info + +This is a non-standard function, not part of the LSP7 standard interface. It has been added in the LSP7 contract implementation so that it can be used as a prevention mechanism against double spending allowance vulnerability. + +::: + +```solidity +function increaseAllowance( + address operator, + uint256 addedAmount +) 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. + +
+ +**Requirements:** + +- `operator` cannot be the same address as `msg.sender` +- `operator` cannot be the zero address. + +
+ +
+ +**Emitted events:** + +- [`AuthorizedOperator`](#authorizedoperator) indicating the updated allowance + +
+ +#### 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 | + +
+ +### owner + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#owner) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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/tree/main/LSPs/LSP-7-DigitalAsset.md#renounceownership) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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/tree/main/LSPs/LSP-7-DigitalAsset.md#revokeoperator) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `revokeOperator(address)` +- Function selector: `0xfad8b32a` + +::: + +```solidity +function revokeOperator(address operator) external nonpayable; +``` + +Removes the `operator` address as an operator of callers tokens, disallowing it to send any amount of tokens on behalf of the token owner (the caller of the function `msg.sender`). See also [`authorizedAmountFor`](#authorizedamountfor). + +#### Parameters + +| Name | Type | Description | +| ---------- | :-------: | ------------------------------------- | +| `operator` | `address` | The address to revoke as an operator. | + +
+ +### setData + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#setdata) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `setData(bytes32,bytes)` +- Function selector: `0x7f23690c` + +::: + +```solidity +function setData(bytes32 dataKey, bytes dataValue) external payable; +``` + +_Sets singular data for a given `dataKey`_ + +#### Parameters + +| Name | Type | Description | +| ----------- | :-------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `dataKey` | `bytes32` | The key to retrieve stored value | +| `dataValue` | `bytes` | The value to set SHOULD only be callable by the owner of the contract set via ERC173 The function is marked as payable to enable flexibility on child contracts If the function is not intended to receive value, an additional check should be implemented to check that value equal 0. Emits a {DataChanged} event. | + +
+ +### setDataBatch + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#setdatabatch) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `setDataBatch(bytes32[],bytes[])` +- Function selector: `0x97902421` + +::: + +```solidity +function setDataBatch(bytes32[] dataKeys, bytes[] dataValues) external payable; +``` + +Sets array of data for multiple given `dataKeys` SHOULD only be callable by the owner of the contract set via ERC173 The function is marked as payable to enable flexibility on child contracts If the function is not intended to receive value, an additional check should be implemented to check that value equal + +0. Emits a [`DataChanged`](#datachanged) event. + +#### Parameters + +| Name | Type | Description | +| ------------ | :---------: | ---------------------------------------- | +| `dataKeys` | `bytes32[]` | The array of data keys for values to set | +| `dataValues` | `bytes[]` | The array of values to set | + +
+ +### supportsInterface + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#supportsinterface) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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/tree/main/LSPs/LSP-7-DigitalAsset.md#totalsupply) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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/tree/main/LSPs/LSP-7-DigitalAsset.md#transfer) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `transfer(address,address,uint256,bool,bytes)` +- Function selector: `0x760d9bba` + +::: + +```solidity +function transfer( + address from, + address to, + uint256 amount, + bool allowNonLSP1Recipient, + 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. | +| `allowNonLSP1Recipient` | `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/tree/main/LSPs/LSP-7-DigitalAsset.md#transferbatch) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Function signature: `transferBatch(address[],address[],uint256[],bool[],bytes[])` +- Function selector: `0x2d7667c9` + +::: + +```solidity +function transferBatch( + address[] from, + address[] to, + uint256[] amount, + bool[] allowNonLSP1Recipient, + 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. | +| `allowNonLSP1Recipient` | `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/tree/main/LSPs/LSP-7-DigitalAsset.md#transferownership) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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); +``` + +
+ +### \_setData + +```solidity +function _setData(bytes32 dataKey, bytes dataValue) internal nonpayable; +``` + +Save gas by emitting the [`DataChanged`](#datachanged) event with only the first 256 bytes of dataValue + +
+ +### \_updateOperator + +```solidity +function _updateOperator( + address tokenOwner, + address operator, + uint256 amount +) internal nonpayable; +``` + +Changes token `amount` the `operator` has access to from `tokenOwner` tokens. +If the amount is zero then the operator is being revoked, otherwise the operator amount is being modified. + +
+ +### \_mint + +```solidity +function _mint( + address to, + uint256 amount, + bool allowNonLSP1Recipient, + 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. | +| `allowNonLSP1Recipient` | `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} event, and sent in the LSP1 hook to the `to` address. | + +
+ +### \_burn + +:::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. +Any logic in the [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. + +
+ +**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. | + +
+ +### \_transfer + +```solidity +function _transfer( + address from, + address to, + uint256 amount, + bool allowNonLSP1Recipient, + 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. +Any logic in the [`_beforeTokenTransfer`](#_beforetokentransfer) function will run before updating the balances. + +
+ +**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`. | +| `allowNonLSP1Recipient` | `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 +) internal nonpayable; +``` + +Hook that is called before any token transfer, including minting and burning. +Allows to run custom logic before updating balances and notifiying 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 | + +
+ +### \_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} function on. | +| `lsp1Data` | `bytes` | the data to be sent to the `from` address in the `universalReceiver` call. | + +
+ +### \_notifyTokenReceiver + +```solidity +function _notifyTokenReceiver( + address to, + bool allowNonLSP1Recipient, + 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 `allowNonLSP1Recipient` boolean flag. + +- if `allowNonLSP1Recipient` is set to `true`, nothing will happen and no notification will be sent. + +- if `allowNonLSP1Recipient` is set to `false, the transaction will revert. + +#### Parameters + +| Name | Type | Description | +| ----------------------- | :-------: | --------------------------------------------------------------------------------------------------- | +| `to` | `address` | The address to call the {universalReceiver} function on. | +| `allowNonLSP1Recipient` | `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. | + +
+ +## Events + +### AuthorizedOperator + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#authorizedoperator) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Event signature: `AuthorizedOperator(address,address,uint256)` +- Event topic hash: `0xd66aff874162a96578e919097b6f6d153dfd89a5cec41bb331fdb0c4aec16e2c` + +::: + +```solidity +event AuthorizedOperator(address indexed operator, address indexed tokenOwner, uint256 indexed amount); +``` + +Emitted when `tokenOwner` enables `operator` for `tokenId`. + +#### 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` | + +
+ +### DataChanged + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#datachanged) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Event signature: `DataChanged(bytes32,bytes)` +- Event topic hash: `0xece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b2` + +::: + +```solidity +event DataChanged(bytes32 indexed dataKey, bytes dataValue); +``` + +_Emitted when data at a key is changed_ + +#### Parameters + +| Name | Type | Description | +| ----------------------- | :-------: | ------------------------------------ | +| `dataKey` **`indexed`** | `bytes32` | The data key which data value is set | +| `dataValue` | `bytes` | The data value to set | + +
+ +### OwnershipTransferred + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#ownershiptransferred) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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` | - | + +
+ +### RevokedOperator + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#revokedoperator) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Event signature: `RevokedOperator(address,address)` +- Event topic hash: `0x50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa1` + +::: + +```solidity +event RevokedOperator(address indexed operator, address indexed tokenOwner); +``` + +Emitted when `tokenOwner` disables `operator` for `tokenId`. + +#### Parameters + +| Name | Type | Description | +| -------------------------- | :-------: | ---------------------------------- | +| `operator` **`indexed`** | `address` | The address revoked from operating | +| `tokenOwner` **`indexed`** | `address` | The token owner | + +
+ +### Transfer + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#transfer) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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 allowNonLSP1Recipient, bytes data); +``` + +Emitted when `tokenId` token is transferred from `from` to `to`. + +#### Parameters + +| Name | Type | Description | +| ------------------------ | :-------: | ---------------------------------------------------------------------------------------------------------------------------- | +| `operator` **`indexed`** | `address` | The address of operator sending tokens | +| `from` **`indexed`** | `address` | The address which tokens are sent | +| `to` **`indexed`** | `address` | The receiving address | +| `amount` | `uint256` | The amount of tokens transferred. | +| `allowNonLSP1Recipient` | `bool` | When set to TRUE, `to` may be any address but when set to FALSE `to` must be a contract that supports LSP1 UniversalReceiver | +| `data` | `bytes` | Additional data the caller wants included in the emitted event, and sent in the hooks to `from` and `to` addresses | + +
+ +## Errors + +### ERC725Y_DataKeysValuesEmptyArray + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvaluesemptyarray) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Error signature: `ERC725Y_DataKeysValuesEmptyArray()` +- Error hash: `0x97da5f95` + +::: + +```solidity +error ERC725Y_DataKeysValuesEmptyArray(); +``` + +reverts when one of the array parameter provided to `setDataBatch` is an empty array + +
+ +### ERC725Y_DataKeysValuesLengthMismatch + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#erc725y_datakeysvalueslengthmismatch) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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 lists of data keys and data values when calling setDataBatch. + +
+ +### ERC725Y_MsgValueDisallowed + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#erc725y_msgvaluedisallowed) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Error signature: `ERC725Y_MsgValueDisallowed()` +- Error hash: `0xf36ba737` + +::: + +```solidity +error ERC725Y_MsgValueDisallowed(); +``` + +reverts when sending value to the `setData(..)` functions + +
+ +### LSP4TokenNameNotEditable + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokennamenoteditable) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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. 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. + +
+ +### LSP4TokenSymbolNotEditable + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp4tokensymbolnoteditable) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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. 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. + +
+ +### LSP7AmountExceedsAuthorizedAmount + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsauthorizedamount) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7amountexceedsbalance) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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` | - | + +
+ +### LSP7CannotSendToSelf + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotsendtoself) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Error signature: `LSP7CannotSendToSelf()` +- Error hash: `0xb9afb000` + +::: + +```solidity +error LSP7CannotSendToSelf(); +``` + +reverts when specifying the same address for `from` or `to` in a token transfer. + +
+ +### LSP7CannotSendWithAddressZero + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotsendwithaddresszero) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotuseaddresszeroasoperator) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol) +- Error signature: `LSP7CannotUseAddressZeroAsOperator()` +- Error hash: `0x6355e766` + +::: + +```solidity +error LSP7CannotUseAddressZeroAsOperator(); +``` + +reverts when trying to set the zero address as an operator. + +
+ +### LSP7DecreasedAllowanceBelowZero + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreasedallowancebelowzero) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7invalidtransferbatch) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceivercontractmissinglsp1interface) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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 allowNonLSP1Recipient` set as `false`. + +#### Parameters + +| Name | Type | Description | +| --------------- | :-------: | ----------- | +| `tokenReceiver` | `address` | - | + +
+ +### LSP7NotifyTokenReceiverIsEOA + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7notifytokenreceiveriseoa) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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 allowNonLSP1Recipient` set as `false`. + +#### Parameters + +| Name | Type | Description | +| --------------- | :-------: | ----------- | +| `tokenReceiver` | `address` | - | + +
+ +### LSP7TokenOwnerCannotBeOperator + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7tokenownercannotbeoperator) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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. + +