Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: set LSP8 TokenId Type on deployment / initialization #712

Merged
merged 9 commits into from
Sep 27, 2023
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import {
ERC725YDataKeys,
PERMISSIONS,
ALL_PERMISSIONS,
LSP8_TOKEN_ID_TYPES,
LSP25_VERSION,
ErrorSelectors,
EventSigHashes,
Expand Down
18 changes: 18 additions & 0 deletions constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ export const ERC725YDataKeys = {
// AddressPermissions:AllowedCalls:<address> + bytes2(0)
'AddressPermissions:AllowedCalls': '0x4b80742de2bf393a64c70000',
},
LSP8: {
LSP8TokenIdType: '0x715f248956de7ce65e94d9d836bfead479f7e70d69b718d47bfe7b00e05b4fe4',
},
LSP9: {
SupportedStandards_LSP9: SupportedStandards.LSP9Vault.key,
},
Expand Down Expand Up @@ -371,6 +374,21 @@ export const LSP1_TYPE_IDS = {
'0xe32c7debcb817925ba4883fdbfc52797187f28f73f860641dab1a68d9b32902c',
};

// LSP8
// ----------

/**
* @dev list of LSP8 Token ID types that can be used to create different types of NFTs.
* @see for details see: https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidtype
*/
export const LSP8_TOKEN_ID_TYPES = {
NUMBER: 0,
STRING: 1,
UNIQUE_ID: 2,
HASH: 3,
ADDRESS: 4,
};

// LSP25
// ----------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ abstract contract LSP4DigitalAssetMetadata is ERC725Y {

/**
* @dev The ERC725Y data keys `LSP4TokenName` and `LSP4TokenSymbol` cannot be changed
* via this function once the digital asset contract has been deployed.
* via this function once the digital asset contract has been deployed.
*
* @dev Save gas by emitting the {DataChanged} event with only the first 256 bytes of dataValue
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ abstract contract LSP4DigitalAssetMetadataInitAbstract is ERC725YInitAbstract {

/**
* @dev the ERC725Y data keys `LSP4TokenName` and `LSP4TokenSymbol` cannot be changed
* via this function once the digital asset contract has been deployed.
* via this function once the digital asset contract has been deployed.
*
* @dev Save gas by emitting the {DataChanged} event with only the first 256 bytes of dataValue
*/
Expand Down
11 changes: 11 additions & 0 deletions contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ bytes4 constant _INTERFACEID_LSP8 = 0x1ae9ba1f;

// --- ERC725Y Data Keys

// keccak256('LSP8TokenIdType')
bytes32 constant _LSP8_TOKENID_TYPE_KEY = 0x715f248956de7ce65e94d9d836bfead479f7e70d69b718d47bfe7b00e05b4fe4;

// bytes10(keccak256('LSP8MetadataAddress')) + bytes2(0)
bytes12 constant _LSP8_METADATA_ADDRESS_KEY_PREFIX = 0x73dcc7c3c4096cdc7f8a0000;

Expand All @@ -22,3 +25,11 @@ bytes32 constant _TYPEID_LSP8_TOKENSRECIPIENT = 0x0b084a55ebf70fd3c06fd755269dac

// keccak256('LSP8Tokens_OperatorNotification')
bytes32 constant _TYPEID_LSP8_TOKENOPERATOR = 0x8a1c15a8799f71b547e08e2bcb2e85257e81b0a07eee2ce6712549eef1f00970;

// --- Types of token IDs

uint256 constant _LSP8_TOKENID_TYPE_NUMBER = 0;
uint256 constant _LSP8_TOKENID_TYPE_STRING = 1;
uint256 constant _LSP8_TOKENID_TYPE_UNIQUE_ID = 2;
uint256 constant _LSP8_TOKENID_TYPE_HASH = 3;
uint256 constant _LSP8_TOKENID_TYPE_ADDRESS = 4;
7 changes: 7 additions & 0 deletions contracts/LSP8IdentifiableDigitalAsset/LSP8Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,10 @@ error LSP8TokenOwnerCannotBeOperator();
* @notice LSP8 contract cannot receive native tokens.
*/
error LSP8TokenContractCannotHoldValue();

/**
* @dev Reverts when trying to edit the data key `LSP8TokenIdType` after the identifiable digital asset contract has been deployed.
* The `LSP8TokenIdType` data key is located inside the ERC725Y Data key-value store of the identifiable digital asset contract.
* It can be set only once inside the constructor/initializer when the identifiable digital asset contract is being deployed.
*/
error LSP8TokenIdTypeNotEditable();
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ import {LSP17Extendable} from "../LSP17ContractExtension/LSP17Extendable.sol";
import {LSP2Utils} from "../LSP2ERC725YJSONSchema/LSP2Utils.sol";

// constants
import {_INTERFACEID_LSP8} from "./LSP8Constants.sol";
import {LSP8TokenContractCannotHoldValue} from "./LSP8Errors.sol";
import {_INTERFACEID_LSP8, _LSP8_TOKENID_TYPE_KEY} from "./LSP8Constants.sol";

// errors
import {
LSP8TokenContractCannotHoldValue,
LSP8TokenIdTypeNotEditable
} from "./LSP8Errors.sol";

import {
_LSP17_EXTENSION_PREFIX
Expand Down Expand Up @@ -51,16 +56,32 @@ abstract contract LSP8IdentifiableDigitalAsset is
LSP17Extendable
{
/**
* @notice Sets the token-Metadata
* @notice Deploying a LSP8IdentifiableDigitalAsset with name `name_`, symbol `symbol_`, owned by address `newOwner_`
* with tokenId type `tokenIdType_`.
*
* @dev Deploy a `LSP8IdentifiableDigitalAsset` contract and set the tokenId type inside the ERC725Y storage of the contract.
* This will also set the token `name_` and `symbol_` under the ERC725Y data keys `LSP4TokenName` and `LSP4TokenSymbol`.
*
* @param name_ The name of the token
* @param symbol_ The symbol of the token
* @param newOwner_ The owner of the the token-Metadata
CJ42 marked this conversation as resolved.
Show resolved Hide resolved
* @param tokenIdType_ The type of tokenIds (= NFTs) that this contract will create.
* Available options are: NUMBER = `0`; STRING = `1`; UNIQUE_ID = `2`; HASH = `3`; ADDRESS = `4`.
*
* @custom:warning Make sure the tokenId type provided on deployment is correct, as it can only be set once
* and cannot be changed in the ERC725Y storage after the contract has been deployed.
*/
constructor(
string memory name_,
string memory symbol_,
address newOwner_
) LSP4DigitalAssetMetadata(name_, symbol_, newOwner_) {}
address newOwner_,
uint256 tokenIdType_
) LSP4DigitalAssetMetadata(name_, symbol_, newOwner_) {
LSP4DigitalAssetMetadata._setData(
_LSP8_TOKENID_TYPE_KEY,
abi.encode(tokenIdType_)
);
}

// fallback function

Expand Down Expand Up @@ -190,4 +211,19 @@ abstract contract LSP8IdentifiableDigitalAsset is
super.supportsInterface(interfaceId) ||
LSP17Extendable._supportsInterfaceInERC165Extension(interfaceId);
}

/**
* @inheritdoc LSP4DigitalAssetMetadata
* @dev The ERC725Y data key `_LSP8_TOKENID_TYPE_KEY` cannot be changed
* once the identifiable digital asset contract has been deployed.
*/
function _setData(
bytes32 dataKey,
bytes memory dataValue
) internal virtual override {
if (dataKey == _LSP8_TOKENID_TYPE_KEY) {
revert LSP8TokenIdTypeNotEditable();
}
LSP4DigitalAssetMetadata._setData(dataKey, dataValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ import {LSP17Extendable} from "../LSP17ContractExtension/LSP17Extendable.sol";
import {LSP2Utils} from "../LSP2ERC725YJSONSchema/LSP2Utils.sol";

// constants
import {_INTERFACEID_LSP8} from "./LSP8Constants.sol";
import {LSP8TokenContractCannotHoldValue} from "./LSP8Errors.sol";
import {_INTERFACEID_LSP8, _LSP8_TOKENID_TYPE_KEY} from "./LSP8Constants.sol";

// errors
import {
LSP8TokenContractCannotHoldValue,
LSP8TokenIdTypeNotEditable
} from "./LSP8Errors.sol";

import {
_LSP17_EXTENSION_PREFIX
Expand Down Expand Up @@ -50,16 +55,35 @@ abstract contract LSP8IdentifiableDigitalAssetInitAbstract is
LSP8IdentifiableDigitalAssetCore,
LSP17Extendable
{
/**
* @dev Initialize a `LSP8IdentifiableDigitalAsset` contract and set the tokenId type inside the ERC725Y storage of the contract.
* This will also set the token `name_` and `symbol_` under the ERC725Y data keys `LSP4TokenName` and `LSP4TokenSymbol`.
*
* @param name_ The name of the token
* @param symbol_ The symbol of the token
* @param newOwner_ The owner of the the token-Metadata
* @param tokenIdType_ The type of tokenIds (= NFTs) that this contract will create.
* Available options are: NUMBER = `0`; STRING = `1`; UNIQUE_ID = `2`; HASH = `3`; ADDRESS = `4`.
*
* @custom:warning Make sure the tokenId type provided on deployment is correct, as it can only be set once
* and cannot be changed in the ERC725Y storage after the contract has been initialized.
*/
function _initialize(
string memory name_,
string memory symbol_,
address newOwner_
) internal virtual override onlyInitializing {
address newOwner_,
uint256 tokenIdType_
) internal virtual onlyInitializing {
LSP4DigitalAssetMetadataInitAbstract._initialize(
name_,
symbol_,
newOwner_
);

LSP4DigitalAssetMetadataInitAbstract._setData(
_LSP8_TOKENID_TYPE_KEY,
abi.encode(tokenIdType_)
);
}

// fallback function
Expand Down Expand Up @@ -190,4 +214,19 @@ abstract contract LSP8IdentifiableDigitalAssetInitAbstract is
super.supportsInterface(interfaceId) ||
LSP17Extendable._supportsInterfaceInERC165Extension(interfaceId);
}

/**
* @inheritdoc LSP4DigitalAssetMetadataInitAbstract
* @dev The ERC725Y data key `_LSP8_TOKENID_TYPE_KEY` cannot be changed
* once the identifiable digital asset contract has been deployed.
*/
function _setData(
bytes32 dataKey,
bytes memory dataValue
) internal virtual override {
if (dataKey == _LSP8_TOKENID_TYPE_KEY) {
revert LSP8TokenIdTypeNotEditable();
}
LSP4DigitalAssetMetadataInitAbstract._setData(dataKey, dataValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
} from "../../LSP4DigitalAssetMetadata/LSP4Compatibility.sol";
import {
LSP8IdentifiableDigitalAsset,
LSP4DigitalAssetMetadata,
ERC725YCore
} from "../LSP8IdentifiableDigitalAsset.sol";
import {
Expand Down Expand Up @@ -74,8 +73,9 @@ abstract contract LSP8CompatibleERC721 is
constructor(
string memory name_,
string memory symbol_,
address newOwner_
) LSP8IdentifiableDigitalAsset(name_, symbol_, newOwner_) {}
address newOwner_,
uint256 tokenIdType_
) LSP8IdentifiableDigitalAsset(name_, symbol_, newOwner_, tokenIdType_) {}

/**
* @inheritdoc LSP8IdentifiableDigitalAsset
Expand Down Expand Up @@ -407,12 +407,12 @@ abstract contract LSP8CompatibleERC721 is
}

/**
* @inheritdoc LSP4DigitalAssetMetadata
* @inheritdoc LSP8IdentifiableDigitalAsset
*/
function _setData(
bytes32 key,
bytes memory value
) internal virtual override(LSP4DigitalAssetMetadata, ERC725YCore) {
) internal virtual override(LSP8IdentifiableDigitalAsset, ERC725YCore) {
super._setData(key, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
} from "../../LSP4DigitalAssetMetadata/LSP4Compatibility.sol";
import {
LSP8IdentifiableDigitalAssetInitAbstract,
LSP4DigitalAssetMetadataInitAbstract,
ERC725YCore
} from "../LSP8IdentifiableDigitalAssetInitAbstract.sol";
import {
Expand Down Expand Up @@ -75,12 +74,14 @@ abstract contract LSP8CompatibleERC721InitAbstract is
function _initialize(
string memory name_,
string memory symbol_,
address newOwner_
address newOwner_,
uint256 tokenIdType_
) internal virtual override onlyInitializing {
LSP8IdentifiableDigitalAssetInitAbstract._initialize(
name_,
symbol_,
newOwner_
newOwner_,
tokenIdType_
);
}

Expand Down Expand Up @@ -415,15 +416,15 @@ abstract contract LSP8CompatibleERC721InitAbstract is
}

/**
* @inheritdoc LSP4DigitalAssetMetadataInitAbstract
* @inheritdoc LSP8IdentifiableDigitalAssetInitAbstract
*/
function _setData(
bytes32 key,
bytes memory value
)
internal
virtual
override(LSP4DigitalAssetMetadataInitAbstract, ERC725YCore)
override(LSP8IdentifiableDigitalAssetInitAbstract, ERC725YCore)
{
super._setData(key, value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ contract LSP8CompatibleERC721Mintable is LSP8CompatibleERC721 {
constructor(
string memory name_,
string memory symbol_,
address newOwner_
) LSP8CompatibleERC721(name_, symbol_, newOwner_) {}
address newOwner_,
uint256 tokenIdType_
) LSP8CompatibleERC721(name_, symbol_, newOwner_, tokenIdType_) {}

/**
* @notice Minting tokenId `tokenId` for address `to` with the additional data `data` (Note: allow non-LSP1 recipient is set to `force`).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ contract LSP8CompatibleERC721MintableInit is
function initialize(
string memory name_,
string memory symbol_,
address newOwner_
address newOwner_,
uint256 tokenIdType_
) external virtual initializer {
LSP8CompatibleERC721MintableInitAbstract._initialize(
name_,
symbol_,
newOwner_
newOwner_,
tokenIdType_
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ contract LSP8CompatibleERC721MintableInitAbstract is
function _initialize(
string memory name_,
string memory symbol_,
address newOwner_
address newOwner_,
uint256 tokenIdType_
) internal virtual override onlyInitializing {
LSP8CompatibleERC721InitAbstract._initialize(name_, symbol_, newOwner_);
LSP8CompatibleERC721InitAbstract._initialize(
name_,
symbol_,
newOwner_,
tokenIdType_
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ contract LSP8Mintable is LSP8IdentifiableDigitalAsset, ILSP8Mintable {
constructor(
string memory name_,
string memory symbol_,
address newOwner_
) LSP8IdentifiableDigitalAsset(name_, symbol_, newOwner_) {}
address newOwner_,
uint256 tokenIdType_
) LSP8IdentifiableDigitalAsset(name_, symbol_, newOwner_, tokenIdType_) {}

/**
* @notice Minting tokenId `tokenId` for address `to` with the additional data `data` (Note: allow non-LSP1 recipient is set to `force`).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ contract LSP8MintableInit is LSP8MintableInitAbstract {
function initialize(
string memory name_,
string memory symbol_,
address newOwner_
address newOwner_,
uint256 tokenIdType_
) external virtual initializer {
LSP8MintableInitAbstract._initialize(name_, symbol_, newOwner_);
LSP8MintableInitAbstract._initialize(
name_,
symbol_,
newOwner_,
tokenIdType_
);
}
}
Loading
Loading