From f4b21ebe716473c53fabc22423108ac95b22cf7b Mon Sep 17 00:00:00 2001 From: Yamen Merhi Date: Wed, 28 Feb 2024 14:37:48 +0200 Subject: [PATCH] feat!: allow Operator to revoke himself (#893) * feat!: allow operator to revoke himself * test: add test for operator revoking himself * refactor!: change LSP7 interfaceId * chore: fix parameter and generate natspec * chore: do suggested changes --------- Co-authored-by: Jean Cvllr <31145285+CJ42@users.noreply.github.com> --- constants.ts | 2 +- .../LSP7DigitalAsset/ILSP7DigitalAsset.sol | 10 +- contracts/LSP7DigitalAsset/LSP7Constants.sol | 2 +- .../LSP7DigitalAsset/LSP7DigitalAssetCore.sol | 35 +++- contracts/LSP7DigitalAsset/LSP7Errors.sol | 23 ++- .../LSP8Errors.sol | 14 +- .../LSP8IdentifiableDigitalAssetCore.sol | 20 ++- docs/_interface_ids_table.mdx | 2 +- .../LSP7DigitalAsset/LSP7DigitalAsset.md | 95 ++++++++--- .../extensions/LSP7Burnable.md | 95 ++++++++--- .../extensions/LSP7CappedSupply.md | 95 ++++++++--- .../LSP7DigitalAsset/presets/LSP7Mintable.md | 95 ++++++++--- .../LSP8IdentifiableDigitalAsset.md | 50 +++--- .../extensions/LSP8Burnable.md | 50 +++--- .../extensions/LSP8CappedSupply.md | 50 +++--- .../extensions/LSP8Enumerable.md | 50 +++--- .../presets/LSP8Mintable.md | 50 +++--- .../LSP7DigitalAsset.behaviour.ts | 154 +++++++++++++----- .../LSP8IdentifiableDigitalAsset.behaviour.ts | 56 ++++--- 19 files changed, 657 insertions(+), 291 deletions(-) diff --git a/constants.ts b/constants.ts index 0ddf873d9..c2b1402b9 100644 --- a/constants.ts +++ b/constants.ts @@ -29,7 +29,7 @@ export const INTERFACE_IDS = { LSP1UniversalReceiver: '0x6bb56a14', LSP1UniversalReceiverDelegate: '0xa245bbda', LSP6KeyManager: '0x23f34c62', - LSP7DigitalAsset: '0xb3c4928f', + LSP7DigitalAsset: '0xc52d6008', LSP8IdentifiableDigitalAsset: '0x3a271706', LSP9Vault: '0x28af17e6', LSP11BasicSocialRecovery: '0x049a28f1', diff --git a/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol b/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol index 2a30c935a..1fafbe646 100644 --- a/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol +++ b/contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol @@ -122,21 +122,23 @@ interface ILSP7DigitalAsset is IERC165, IERC725Y { ) external; /** - * @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}. + * @dev 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 * * @param operator The address to revoke as an operator. + * @param tokenOwner The address of the token owner. * @param notify Boolean indicating whether to notify the operator or not. * @param operatorNotificationData The data to notify the operator about via LSP1. * * @custom:requirements - * - `operator` cannot be calling address. + * - caller MUST be `operator` or `tokenOwner` * - `operator` cannot be the zero address. * * @custom:events {OperatorRevoked} event with address of the operator being revoked for the caller (token holder). */ function revokeOperator( address operator, + address tokenOwner, bool notify, bytes memory operatorNotificationData ) external; @@ -184,6 +186,7 @@ interface ILSP7DigitalAsset is IERC165, IERC725Y { * indicating `operator` does not have any alauthorizedAmountForlowance left for `msg.sender`. * * @param operator The operator to decrease allowance for `msg.sender` + * @param tokenOwner The address of the token owner. * @param subtractedAmount The amount to decrease by in the operator's allowance. * * @custom:requirements @@ -192,6 +195,7 @@ interface ILSP7DigitalAsset is IERC165, IERC725Y { */ function decreaseAllowance( address operator, + address tokenOwner, uint256 subtractedAmount, bytes memory operatorNotificationData ) external; diff --git a/contracts/LSP7DigitalAsset/LSP7Constants.sol b/contracts/LSP7DigitalAsset/LSP7Constants.sol index 6bcc63db9..b56398da2 100644 --- a/contracts/LSP7DigitalAsset/LSP7Constants.sol +++ b/contracts/LSP7DigitalAsset/LSP7Constants.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.4; // --- ERC165 interface ids -bytes4 constant _INTERFACEID_LSP7 = 0xb3c4928f; +bytes4 constant _INTERFACEID_LSP7 = 0xc52d6008; // --- Token Hooks diff --git a/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol b/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol index f396cd570..9ca4798f9 100644 --- a/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol +++ b/contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol @@ -20,7 +20,6 @@ import {LSP1Utils} from "../LSP1UniversalReceiver/LSP1Utils.sol"; // errors import { - LSP7CannotSendToSelf, LSP7AmountExceedsAuthorizedAmount, LSP7InvalidTransferBatch, LSP7AmountExceedsBalance, @@ -31,7 +30,9 @@ import { LSP7NotifyTokenReceiverContractMissingLSP1Interface, LSP7NotifyTokenReceiverIsEOA, OperatorAllowanceCannotBeIncreasedFromZero, - LSP7BatchCallFailed + LSP7BatchCallFailed, + LSP7RevokeOperatorNotAuthorized, + LSP7DecreaseAllowanceNotAuthorized } from "./LSP7Errors.sol"; // constants @@ -173,11 +174,20 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { */ function revokeOperator( address operator, + address tokenOwner, bool notify, bytes memory operatorNotificationData ) public virtual override { + if (msg.sender != tokenOwner && msg.sender != operator) { + revert LSP7RevokeOperatorNotAuthorized( + msg.sender, + tokenOwner, + operator + ); + } + _updateOperator( - msg.sender, + tokenOwner, operator, 0, notify, @@ -186,7 +196,7 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { if (notify) { bytes memory lsp1Data = abi.encode( - msg.sender, + tokenOwner, 0, operatorNotificationData ); @@ -254,10 +264,19 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { */ function decreaseAllowance( address operator, + address tokenOwner, uint256 subtractedAmount, bytes memory operatorNotificationData ) public virtual override { - uint256 currentAllowance = authorizedAmountFor(operator, msg.sender); + if (msg.sender != tokenOwner && msg.sender != operator) { + revert LSP7DecreaseAllowanceNotAuthorized( + msg.sender, + tokenOwner, + operator + ); + } + + uint256 currentAllowance = authorizedAmountFor(operator, tokenOwner); if (currentAllowance < subtractedAmount) { revert LSP7DecreasedAllowanceBelowZero(); } @@ -266,7 +285,7 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { unchecked { newAllowance = currentAllowance - subtractedAmount; _updateOperator( - msg.sender, + tokenOwner, operator, newAllowance, true, @@ -275,7 +294,7 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { } bytes memory lsp1Data = abi.encode( - msg.sender, + tokenOwner, newAllowance, operatorNotificationData ); @@ -295,8 +314,6 @@ abstract contract LSP7DigitalAssetCore is ILSP7DigitalAsset { bool force, bytes memory data ) public virtual override { - if (from == to) revert LSP7CannotSendToSelf(); - if (msg.sender != from) { _spendAllowance({ operator: msg.sender, diff --git a/contracts/LSP7DigitalAsset/LSP7Errors.sol b/contracts/LSP7DigitalAsset/LSP7Errors.sol index 62fa06908..3a247a3f0 100644 --- a/contracts/LSP7DigitalAsset/LSP7Errors.sol +++ b/contracts/LSP7DigitalAsset/LSP7Errors.sol @@ -36,11 +36,6 @@ error LSP7CannotUseAddressZeroAsOperator(); */ error LSP7CannotSendWithAddressZero(); -/** - * @dev reverts when specifying the same address for `from` or `to` in a token transfer. - */ -error LSP7CannotSendToSelf(); - /** * @dev reverts when the array parameters used in {transferBatch} have different lengths. */ @@ -88,3 +83,21 @@ error OperatorAllowanceCannotBeIncreasedFromZero(address operator); * @notice Batch call failed. */ error LSP7BatchCallFailed(uint256 callIndex); + +/** + * @dev Reverts when the call to revoke operator is not authorized. + */ +error LSP7RevokeOperatorNotAuthorized( + address caller, + address tokenOwner, + address operator +); + +/** + * @dev Reverts when the call to decrease allowance is not authorized. + */ +error LSP7DecreaseAllowanceNotAuthorized( + address caller, + address tokenOwner, + address operator +); diff --git a/contracts/LSP8IdentifiableDigitalAsset/LSP8Errors.sol b/contracts/LSP8IdentifiableDigitalAsset/LSP8Errors.sol index 472ce6016..a74dc36d3 100644 --- a/contracts/LSP8IdentifiableDigitalAsset/LSP8Errors.sol +++ b/contracts/LSP8IdentifiableDigitalAsset/LSP8Errors.sol @@ -33,11 +33,6 @@ error LSP8CannotUseAddressZeroAsOperator(); */ error LSP8CannotSendToAddressZero(); -/** - * @dev Reverts when specifying the same address for `from` and `to` in a token transfer. - */ -error LSP8CannotSendToSelf(); - /** * @dev Reverts when `operator` is not an operator for the `tokenId`. */ @@ -112,3 +107,12 @@ error LSP8TokenOwnerChanged( address oldOwner, address newOwner ); + +/** + * @dev Reverts when the call to revoke operator is not authorized. + */ +error LSP8RevokeOperatorNotAuthorized( + address caller, + address tokenOwner, + bytes32 tokenId +); diff --git a/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol b/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol index 89f57b15d..2846c4ac0 100644 --- a/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol +++ b/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol @@ -36,13 +36,13 @@ import { LSP8NonExistingOperator, LSP8CannotSendToAddressZero, LSP8TokenIdAlreadyMinted, - LSP8CannotSendToSelf, LSP8NotifyTokenReceiverContractMissingLSP1Interface, LSP8NotifyTokenReceiverIsEOA, LSP8TokenIdsDataLengthMismatch, LSP8TokenIdsDataEmptyArray, LSP8BatchCallFailed, - LSP8TokenOwnerChanged + LSP8TokenOwnerChanged, + LSP8RevokeOperatorNotAuthorized } from "./LSP8Errors.sol"; // constants @@ -293,8 +293,14 @@ abstract contract LSP8IdentifiableDigitalAssetCore is ) public virtual override { address tokenOwner = tokenOwnerOf(tokenId); - if (tokenOwner != msg.sender) { - revert LSP8NotTokenOwner(tokenOwner, tokenId, msg.sender); + if (msg.sender != tokenOwner) { + if (operator != msg.sender) { + revert LSP8RevokeOperatorNotAuthorized( + msg.sender, + tokenOwner, + tokenId + ); + } } if (operator == address(0)) { @@ -315,7 +321,7 @@ abstract contract LSP8IdentifiableDigitalAssetCore is if (notify) { bytes memory lsp1Data = abi.encode( - msg.sender, + tokenOwner, tokenId, false, // unauthorized operatorNotificationData @@ -625,10 +631,6 @@ abstract contract LSP8IdentifiableDigitalAssetCore is bool force, bytes memory data ) internal virtual { - if (from == to) { - revert LSP8CannotSendToSelf(); - } - address tokenOwner = tokenOwnerOf(tokenId); if (tokenOwner != from) { revert LSP8NotTokenOwner(tokenOwner, tokenId, from); diff --git a/docs/_interface_ids_table.mdx b/docs/_interface_ids_table.mdx index acba017e9..036a13f80 100644 --- a/docs/_interface_ids_table.mdx +++ b/docs/_interface_ids_table.mdx @@ -8,7 +8,7 @@ | **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 predfined permissions. | -| **LSP7DigitalAsset** | `0xb3c4928f` | Interface of the LSP7 - Digital Asset standard, a fungible digital asset. | +| **LSP7DigitalAsset** | `0xc52d6008` | 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. | diff --git a/docs/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md b/docs/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md index 691daae1a..7766d68b5 100644 --- a/docs/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md +++ b/docs/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md @@ -250,14 +250,15 @@ Returns the number of decimals used to get its user representation. If the asset - 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,bytes)` -- Function selector: `0x7b204c4e` +- Function signature: `decreaseAllowance(address,address,uint256,bytes)` +- Function selector: `0x78381670` ::: ```solidity function decreaseAllowance( address operator, + address tokenOwner, uint256 subtractedAmount, bytes operatorNotificationData ) external nonpayable; @@ -272,6 +273,7 @@ Atomically decreases the allowance granted to `operator` by the caller. This is | 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` | - | @@ -459,26 +461,28 @@ Leaves the contract without owner. It will not be possible to call `onlyOwner` f - 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,bool,bytes)` -- Function selector: `0x4521748e` +- Function signature: `revokeOperator(address,address,bool,bytes)` +- Function selector: `0x30d0dc37` ::: ```solidity function revokeOperator( address operator, + address tokenOwner, bool notify, bytes operatorNotificationData ) 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). +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. | @@ -1561,25 +1565,6 @@ Reverts when a batch call failed.
-### 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 @@ -1624,6 +1609,37 @@ 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/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreaseallowancenotauthorized) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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 @@ -1714,6 +1730,37 @@ reverts if the `tokenReceiver` is an EOA when minting or transferring tokens wit
+### LSP7RevokeOperatorNotAuthorized + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7revokeoperatornotauthorized) +- Solidity implementation: [`LSP7DigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/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 diff --git a/docs/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.md b/docs/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.md index ac6cbe517..6650eee99 100644 --- a/docs/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.md +++ b/docs/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.md @@ -275,14 +275,15 @@ Returns the number of decimals used to get its user representation. If the asset - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#decreaseallowance) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.sol) -- Function signature: `decreaseAllowance(address,uint256,bytes)` -- Function selector: `0x7b204c4e` +- Function signature: `decreaseAllowance(address,address,uint256,bytes)` +- Function selector: `0x78381670` ::: ```solidity function decreaseAllowance( address operator, + address tokenOwner, uint256 subtractedAmount, bytes operatorNotificationData ) external nonpayable; @@ -297,6 +298,7 @@ Atomically decreases the allowance granted to `operator` by the caller. This is | 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` | - | @@ -484,26 +486,28 @@ Leaves the contract without owner. It will not be possible to call `onlyOwner` f - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.sol) -- Function signature: `revokeOperator(address,bool,bytes)` -- Function selector: `0x4521748e` +- Function signature: `revokeOperator(address,address,bool,bytes)` +- Function selector: `0x30d0dc37` ::: ```solidity function revokeOperator( address operator, + address tokenOwner, bool notify, bytes operatorNotificationData ) 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). +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. | @@ -1586,25 +1590,6 @@ Reverts when a batch call failed.
-### LSP7CannotSendToSelf - -:::note References - -- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotsendtoself) -- Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.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 @@ -1649,6 +1634,37 @@ 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/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreaseallowancenotauthorized) +- Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.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 @@ -1739,6 +1755,37 @@ reverts if the `tokenReceiver` is an EOA when minting or transferring tokens wit
+### LSP7RevokeOperatorNotAuthorized + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7revokeoperatornotauthorized) +- Solidity implementation: [`LSP7Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.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 diff --git a/docs/contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.md b/docs/contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.md index 9d9823443..c70451ebe 100644 --- a/docs/contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.md +++ b/docs/contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.md @@ -248,14 +248,15 @@ Returns the number of decimals used to get its user representation. If the asset - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#decreaseallowance) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.sol) -- Function signature: `decreaseAllowance(address,uint256,bytes)` -- Function selector: `0x7b204c4e` +- Function signature: `decreaseAllowance(address,address,uint256,bytes)` +- Function selector: `0x78381670` ::: ```solidity function decreaseAllowance( address operator, + address tokenOwner, uint256 subtractedAmount, bytes operatorNotificationData ) external nonpayable; @@ -270,6 +271,7 @@ Atomically decreases the allowance granted to `operator` by the caller. This is | 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` | - | @@ -457,26 +459,28 @@ Leaves the contract without owner. It will not be possible to call `onlyOwner` f - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.sol) -- Function signature: `revokeOperator(address,bool,bytes)` -- Function selector: `0x4521748e` +- Function signature: `revokeOperator(address,address,bool,bytes)` +- Function selector: `0x30d0dc37` ::: ```solidity function revokeOperator( address operator, + address tokenOwner, bool notify, bytes operatorNotificationData ) 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). +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. | @@ -1560,25 +1564,6 @@ Reverts when a batch call failed.
-### LSP7CannotSendToSelf - -:::note References - -- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotsendtoself) -- Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.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 @@ -1665,6 +1650,37 @@ Reverts when setting `0` for the [`tokenSupplyCap`](#tokensupplycap). The max to
+### LSP7DecreaseAllowanceNotAuthorized + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreaseallowancenotauthorized) +- Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.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 @@ -1755,6 +1771,37 @@ reverts if the `tokenReceiver` is an EOA when minting or transferring tokens wit
+### LSP7RevokeOperatorNotAuthorized + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7revokeoperatornotauthorized) +- Solidity implementation: [`LSP7CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/extensions/LSP7CappedSupply.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 diff --git a/docs/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md b/docs/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md index 00e9cb8e7..eb1a125ae 100644 --- a/docs/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md +++ b/docs/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md @@ -281,14 +281,15 @@ Returns the number of decimals used to get its user representation. If the asset - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#decreaseallowance) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/presets/LSP7Mintable.sol) -- Function signature: `decreaseAllowance(address,uint256,bytes)` -- Function selector: `0x7b204c4e` +- Function signature: `decreaseAllowance(address,address,uint256,bytes)` +- Function selector: `0x78381670` ::: ```solidity function decreaseAllowance( address operator, + address tokenOwner, uint256 subtractedAmount, bytes operatorNotificationData ) external nonpayable; @@ -303,6 +304,7 @@ Atomically decreases the allowance granted to `operator` by the caller. This is | 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` | - | @@ -523,26 +525,28 @@ Leaves the contract without owner. It will not be possible to call `onlyOwner` f - Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#revokeoperator) - Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/presets/LSP7Mintable.sol) -- Function signature: `revokeOperator(address,bool,bytes)` -- Function selector: `0x4521748e` +- Function signature: `revokeOperator(address,address,bool,bytes)` +- Function selector: `0x30d0dc37` ::: ```solidity function revokeOperator( address operator, + address tokenOwner, bool notify, bytes operatorNotificationData ) 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). +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. | @@ -1625,25 +1629,6 @@ Reverts when a batch call failed.
-### LSP7CannotSendToSelf - -:::note References - -- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7cannotsendtoself) -- Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/presets/LSP7Mintable.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 @@ -1688,6 +1673,37 @@ 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/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7decreaseallowancenotauthorized) +- Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/presets/LSP7Mintable.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 @@ -1778,6 +1794,37 @@ reverts if the `tokenReceiver` is an EOA when minting or transferring tokens wit
+### LSP7RevokeOperatorNotAuthorized + +:::note References + +- Specification details: [**LSP-7-DigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-7-DigitalAsset.md#lsp7revokeoperatornotauthorized) +- Solidity implementation: [`LSP7Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP7DigitalAsset/presets/LSP7Mintable.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 diff --git a/docs/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md b/docs/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md index 708d6a325..227f072ba 100644 --- a/docs/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md +++ b/docs/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md @@ -1730,25 +1730,6 @@ Reverts when trying to send token to the zero address.
-### LSP8CannotSendToSelf - -:::note References - -- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoself) -- Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.sol) -- Error signature: `LSP8CannotSendToSelf()` -- Error hash: `0x5d67d6c1` - -::: - -```solidity -error LSP8CannotSendToSelf(); -``` - -Reverts when specifying the same address for `from` and `to` in a token transfer. - -
- ### LSP8CannotUseAddressZeroAsOperator :::note References @@ -1969,6 +1950,37 @@ Reverts when `operator` is already authorized for the `tokenId`.
+### LSP8RevokeOperatorNotAuthorized + +:::note References + +- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) +- Solidity implementation: [`LSP8IdentifiableDigitalAsset.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/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 diff --git a/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md b/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md index 56f4230c9..86f50029d 100644 --- a/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md +++ b/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md @@ -1756,25 +1756,6 @@ Reverts when trying to send token to the zero address.
-### LSP8CannotSendToSelf - -:::note References - -- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoself) -- Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.sol) -- Error signature: `LSP8CannotSendToSelf()` -- Error hash: `0x5d67d6c1` - -::: - -```solidity -error LSP8CannotSendToSelf(); -``` - -Reverts when specifying the same address for `from` and `to` in a token transfer. - -
- ### LSP8CannotUseAddressZeroAsOperator :::note References @@ -1995,6 +1976,37 @@ Reverts when `operator` is already authorized for the `tokenId`.
+### LSP8RevokeOperatorNotAuthorized + +:::note References + +- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) +- Solidity implementation: [`LSP8Burnable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.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 diff --git a/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.md b/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.md index 372210480..7315d4377 100644 --- a/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.md +++ b/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.md @@ -1730,25 +1730,6 @@ Reverts when trying to send token to the zero address.
-### LSP8CannotSendToSelf - -:::note References - -- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoself) -- Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.sol) -- Error signature: `LSP8CannotSendToSelf()` -- Error hash: `0x5d67d6c1` - -::: - -```solidity -error LSP8CannotSendToSelf(); -``` - -Reverts when specifying the same address for `from` and `to` in a token transfer. - -
- ### LSP8CannotUseAddressZeroAsOperator :::note References @@ -2011,6 +1992,37 @@ Reverts when `operator` is already authorized for the `tokenId`.
+### LSP8RevokeOperatorNotAuthorized + +:::note References + +- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) +- Solidity implementation: [`LSP8CappedSupply.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.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 diff --git a/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md b/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md index 9495edf7f..e73d15af1 100644 --- a/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md +++ b/docs/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md @@ -1758,25 +1758,6 @@ Reverts when trying to send token to the zero address.
-### LSP8CannotSendToSelf - -:::note References - -- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoself) -- Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.sol) -- Error signature: `LSP8CannotSendToSelf()` -- Error hash: `0x5d67d6c1` - -::: - -```solidity -error LSP8CannotSendToSelf(); -``` - -Reverts when specifying the same address for `from` and `to` in a token transfer. - -
- ### LSP8CannotUseAddressZeroAsOperator :::note References @@ -1997,6 +1978,37 @@ Reverts when `operator` is already authorized for the `tokenId`.
+### LSP8RevokeOperatorNotAuthorized + +:::note References + +- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) +- Solidity implementation: [`LSP8Enumerable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.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 diff --git a/docs/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md b/docs/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md index 1a1c1ee76..fca4e87b5 100644 --- a/docs/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md +++ b/docs/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md @@ -1796,25 +1796,6 @@ Reverts when trying to send token to the zero address.
-### LSP8CannotSendToSelf - -:::note References - -- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8cannotsendtoself) -- Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.sol) -- Error signature: `LSP8CannotSendToSelf()` -- Error hash: `0x5d67d6c1` - -::: - -```solidity -error LSP8CannotSendToSelf(); -``` - -Reverts when specifying the same address for `from` and `to` in a token transfer. - -
- ### LSP8CannotUseAddressZeroAsOperator :::note References @@ -2035,6 +2016,37 @@ Reverts when `operator` is already authorized for the `tokenId`.
+### LSP8RevokeOperatorNotAuthorized + +:::note References + +- Specification details: [**LSP-8-IdentifiableDigitalAsset**](https://github.com/lukso-network/lips/tree/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8revokeoperatornotauthorized) +- Solidity implementation: [`LSP8Mintable.sol`](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.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 diff --git a/tests/LSP7DigitalAsset/LSP7DigitalAsset.behaviour.ts b/tests/LSP7DigitalAsset/LSP7DigitalAsset.behaviour.ts index 4761dfc0f..dff9137d8 100644 --- a/tests/LSP7DigitalAsset/LSP7DigitalAsset.behaviour.ts +++ b/tests/LSP7DigitalAsset/LSP7DigitalAsset.behaviour.ts @@ -446,10 +446,16 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise { it('should revert', async () => { + const tokenOwner = context.accounts.owner.address; const subtractedAmount = ethers.BigNumber.from('1'); await expect( - context.lsp7.decreaseAllowance(ethers.constants.AddressZero, subtractedAmount, '0x'), + context.lsp7.decreaseAllowance( + ethers.constants.AddressZero, + tokenOwner, + subtractedAmount, + '0x', + ), ).to.be.revertedWithCustomError( context.lsp7, // Since we can never grant allowance for address(0), address(0) will always have 0 allowance @@ -469,7 +475,7 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise Promise { + it("should decrease the operator's allowance by the `subtractedAmount` + emit `OperatorAuthorizationChanged` event", async () => { + const operator = context.accounts.operator.address; + const tokenOwner = context.accounts.owner.address; + + const subtractedAmount = ethers.BigNumber.from('1'); + + const allowanceBefore = await context.lsp7.authorizedAmountFor(operator, tokenOwner); + + const tx = await context.lsp7 + .connect(context.accounts.operator) + .decreaseAllowance(operator, tokenOwner, subtractedAmount, '0x'); const expectedNewAllowance = allowanceBefore.sub(subtractedAmount); @@ -505,7 +541,12 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise Promise { it('should revert', async () => { + const tokenOwner = context.accounts.owner.address; const subtractedAmount = ethers.BigNumber.from('1'); await expect( - context.lsp7.decreaseAllowance(context.accounts.owner.address, subtractedAmount, '0x'), + context.lsp7.decreaseAllowance( + context.accounts.owner.address, + tokenOwner, + subtractedAmount, + '0x', + ), ).to.be.revertedWithCustomError(context.lsp7, 'LSP7TokenOwnerCannotBeOperator'); }); }); @@ -540,7 +587,12 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise Promise Promise { + const operator = context.accounts.operator.address; + const tokenOwner = context.accounts.owner.address; + const amount = context.initialSupply; + + // pre-conditions + await context.lsp7.authorizeOperator(operator, amount, '0x'); + expect(await context.lsp7.authorizedAmountFor(operator, tokenOwner)).to.equal(amount); + + expect(await context.lsp7.getOperatorsOf(tokenOwner)).to.deep.equal([operator]); + + // effects + const tx = await context.lsp7 + .connect(context.accounts.operator) + .revokeOperator(operator, tokenOwner, false, '0x'); + await expect(tx) .to.emit(context.lsp7, 'OperatorRevoked') .withArgs(operator, tokenOwner, false, '0x'); @@ -598,10 +678,11 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise { it('should revert', async () => { + const tokenOwner = context.accounts.owner.address; const operator = ethers.constants.AddressZero; await expect( - context.lsp7.revokeOperator(operator, false, '0x'), + context.lsp7.revokeOperator(operator, tokenOwner, false, '0x'), ).to.be.revertedWithCustomError(context.lsp7, 'LSP7CannotUseAddressZeroAsOperator'); }); }); @@ -611,7 +692,7 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise Promise Promise { const operatorThatReverts: TokenReceiverWithLSP1Revert = await new TokenReceiverWithLSP1Revert__factory(context.accounts.owner).deploy(); + const tokenOwner = context.accounts.owner.address; const operator = operatorThatReverts.address; await context.lsp7.authorizeOperator(operator, 1, '0x'); await operatorThatReverts.addLSP1Support(); - await expect(context.lsp7.revokeOperator(operator, false, '0xaabbccdd')).to.emit( - context.lsp7, - 'OperatorRevoked', - ); + await expect( + context.lsp7.revokeOperator(operator, tokenOwner, false, '0xaabbccdd'), + ).to.emit(context.lsp7, 'OperatorRevoked'); }); }); @@ -1050,7 +1132,7 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise context.accounts.operator); describe('when `from` and `to` address are the same', () => { - it('should revert', async () => { + it('should pass', async () => { const operator = context.accounts.operator; const txParams = { @@ -1067,17 +1149,15 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise Promise Promise context.accounts.operator); describe('when `to` and `from` are the same address', () => { - it('should revert', async () => { + it('should pass', async () => { const operator = context.accounts.operator; const txParams = { from: [context.accounts.owner.address, context.accounts.owner.address], @@ -1641,12 +1721,8 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise Promise { const revokeOperatorCalldata = context.lsp7.interface.encodeFunctionData( 'revokeOperator', - [context.accounts.tokenReceiver.address, true, '0x'], + [context.accounts.tokenReceiver.address, context.accounts.owner.address, true, '0x'], ); await expect( @@ -2335,7 +2411,7 @@ export const shouldBehaveLikeLSP7 = (buildContext: () => Promise { + describe('when operator is not the zero address', () => { + it('should succeed', async () => { + const operator = context.accounts.operator.address; + const tokenOwner = context.accounts.owner.address; + const tokenId = mintedTokenId; + + // pre-conditions + await context.lsp8.authorizeOperator(operator, tokenId, '0x'); + expect(await context.lsp8.isOperatorFor(operator, tokenId)).to.be.true; + + // effects + const tx = await context.lsp8 + .connect(context.accounts.operator) + .revokeOperator(operator, tokenId, false, '0x'); + + await expect(tx) + .to.emit(context.lsp8, 'OperatorRevoked') + .withArgs(operator, tokenOwner, tokenId, false, '0x'); + + // post-conditions + expect(await context.lsp8.isOperatorFor(operator, tokenId)).to.be.false; + }); + }); + }); }); describe('isOperatorFor', () => { @@ -920,30 +946,6 @@ export const shouldBehaveLikeLSP8 = ( }); }); }); - - describe("when `from == to` address (= sending to tokenId's owner itself)", () => { - it('should revert', async () => { - const txParams = { - from: context.accounts.owner.address, - to: context.accounts.owner.address, - tokenId: mintedTokenId, - force, - data, - }; - - await expect( - context.lsp8 - .connect(operator) - .transfer( - txParams.from, - txParams.to, - txParams.tokenId, - txParams.force, - txParams.data, - ), - ).to.be.revertedWithCustomError(context.lsp8, 'LSP8CannotSendToSelf'); - }); - }); }); describe('when force=false', () => { @@ -1055,7 +1057,7 @@ export const shouldBehaveLikeLSP8 = ( txParams.force, txParams.data, ), - ).to.be.revertedWithCustomError(context.lsp8, 'LSP8CannotSendToSelf'); + ).to.be.revertedWithCustomError(context.lsp8, 'LSP8NotifyTokenReceiverIsEOA'); }); }); });