Skip to content

Commit

Permalink
Merge branch 'main' into add-base-uri-script
Browse files Browse the repository at this point in the history
  • Loading branch information
fhildeb authored Mar 5, 2024
2 parents 3080ad8 + 9f7317a commit c5cd9a2
Show file tree
Hide file tree
Showing 4 changed files with 264 additions and 2 deletions.
98 changes: 98 additions & 0 deletions digital-assets/tokenIdFormat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { ethers } from 'ethers';
import lsp8Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json';
import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts';

const SAMPLE_LSP8_ASSET = '0x8734600968c7e7193BB9B1b005677B4edBaDcD18';
const RPC_URL = 'https://rpc.testnet.lukso.gateway.fm';

const provider = new ethers.JsonRpcProvider(RPC_URL);

// Create contract instance
const myAssetContract = new ethers.Contract(
SAMPLE_LSP8_ASSET,
lsp8Artifact.abi,
provider,
);

// Sample Token ID of the contract
// Could be 1, my-token-id, 0x123, etc.
const myTokenId = '1';

// https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformat
async function getTokenIdFormat() {
try {
const tokenIdFormat = parseInt(
// https://docs.lukso.tech/tools/erc725js/classes/ERC725#getdata
await myAssetContract.getData(ERC725YDataKeys.LSP8['LSP8TokenIdFormat']),
16,
);
return tokenIdFormat;
} catch (err) {
console.error(
'Could not retrieve LSP8TokenIdFormat. Please provide an LSP8 asset address.',
);
return null;
}
}

// Get the global token ID format of the asset
let tokenIdFormat = await getTokenIdFormat();
console.log('Global ID Format: ', tokenIdFormat);

// Convert a token ID according to LSP8TokenIdFormat
// https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenidformat
const convertTokenId = (tokenID: string, tokenIdFormat: number) => {
switch (tokenIdFormat) {
// TokenID is Number
case 0:
case 100:
// uint256 - Number (Left padded)
return ethers.zeroPadValue('0x0' + BigInt(tokenID).toString(16), 32);
// TokenID is String
case 1:
case 101:
// string - String (Right padded)
return ethers.encodeBytes32String(tokenID).padEnd(32, '0');
// TokenID is Address
case 2:
case 102:
// address - Smart Contract (Left padded)
return ethers.zeroPadValue(tokenID, 32);
// TokenID is Byte Value
case 3:
case 103:
// bytes32 - Unique Bytes (Right padded)
return ethers
.hexlify(ethers.getBytes(tokenID).slice(0, 32))
.padEnd(66, '0');
// TokenID is Hash Digest
case 4:
case 104:
// bytes32 - Hash Digest (No padding)
return tokenID;
}
};

// Convert the token ID based on the token ID format
if (tokenIdFormat !== null) {
let byte32TokenId = convertTokenId(myTokenId, tokenIdFormat);
console.log('Parsed Byte32 Token ID: ', byte32TokenId);

// If token ID format is mixed
if (tokenIdFormat >= 100) {
tokenIdFormat = parseInt(
// Retrieve token ID format for the individual token ID
// https://docs.lukso.tech/contracts/contracts/LSP8IdentifiableDigitalAsset/#getdatafortokenid
await myAssetContract.getDataForTokenId(
byte32TokenId,
ERC725YDataKeys.LSP8['LSP8TokenIdFormat'],
),
16,
);
// Convert the token ID based on the individual token ID format
byte32TokenId = convertTokenId(myTokenId, tokenIdFormat);
console.log('Individual Token ID Format: ', tokenIdFormat);
} else {
console.log('Asset has a global Token ID Format');
}
}
8 changes: 8 additions & 0 deletions smart-contracts-hardhat/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const LSP23_FACTORY_ADDRESS_TESTNET = '0x2300000A84D25dF63081feAa37ba6b62C4c89a30';
export const LSP23_POST_DEPLOYMENT_MODULE_ADDRESS_TESTNET =
'0x000000000066093407b6704B89793beFfD0D8F00';
export const UNIVERSAL_PROFILE_IMPLEMENTATION_ADDRESS_TESTNET =
'0x3024D38EA2434BA6635003Dc1BDC0daB5882ED4F';
export const LSP6_KEY_MANAGER_IMPLEMENTATION_ADDRESS_TESTNET =
'0x2Fe3AeD98684E7351aD2D408A43cE09a738BF8a4';
export const LSP1_UNIVERSAL_RECEIVER_ADDRESS_TESTNET = '0x7870C5B8BC9572A8001C3f96f7ff59961B23500D';
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ async function deployTokenWithMetadata() {

// Create the transaction payload for setting storage data
// https://docs.lukso.tech/contracts/contracts/ERC725/#setdata
const lsp4StorageBytecode = token.interface.encodeFunctionData('setData', [
const setLSP4MetadataPayload = token.interface.encodeFunctionData('setData', [
metadataKey,
encodedLSP4Metadata.values[0],
]);
Expand All @@ -82,7 +82,7 @@ async function deployTokenWithMetadata() {
[0, 0], // Value is empty for both operations
[
tokenBytecodeWithConstructor, // Payload for contract deployment
lsp4StorageBytecode, // Payload for setting a data key on the deployed contract
setLSP4MetadataPayload, // Payload for setting a data key on the deployed contract
],
);

Expand Down
156 changes: 156 additions & 0 deletions smart-contracts-hardhat/scripts/deployUniversalProfiileWithLSP23.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// libs
import { ethers } from 'hardhat';
import { AbiCoder } from 'ethers';
import { ERC725 } from '@erc725/erc725.js';

// LSPs Smart Contracts artifacts

import LSP23FactoryArtifact from '@lukso/lsp-smart-contracts/artifacts/LSP23LinkedContractsFactory.json';
import UniversalProfileInitArtifact from '@lukso/lsp-smart-contracts/artifacts/UniversalProfileInit.json';

// ERC725.js Metadata schemas

import LSP1UniversalReceiverDelegateSchemas from '@erc725/erc725.js/schemas/LSP1UniversalReceiverDelegate.json';
import LSP3ProfileMetadataSchemas from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json';
import LSP6KeyManagerSchemas from '@erc725/erc725.js/schemas/LSP6KeyManager.json';

// Constants
import {
LSP23_FACTORY_ADDRESS_TESTNET,
UNIVERSAL_PROFILE_IMPLEMENTATION_ADDRESS_TESTNET,
LSP23_POST_DEPLOYMENT_MODULE_ADDRESS_TESTNET,
LSP6_KEY_MANAGER_IMPLEMENTATION_ADDRESS_TESTNET,
LSP1_UNIVERSAL_RECEIVER_ADDRESS_TESTNET,
} from '../global';

// Constants that needs to be overwritten
const MAIN_CONTROLLER_EOA = '0x3303Ce3b8644D566271DD2Eb54292d32F1458968';
const SALT = '0x5eed5eed5eed5eed5eed5eed5eed5eed5eed5eed5eed5eed5eed5eed5eed5eed';

async function main() {
// Interacting with the LSP23Factory contract
const lsp23FactoryContract = await ethers.getContractAtFromArtifact(
LSP23FactoryArtifact,
LSP23_FACTORY_ADDRESS_TESTNET,
);

// Interacting with the UniversalProfileImplementation contract
const universalProfileImplementationContract = await ethers.getContractAtFromArtifact(
UniversalProfileInitArtifact,
UNIVERSAL_PROFILE_IMPLEMENTATION_ADDRESS_TESTNET,
);

// create the init structs of LSP23 Linked Contracts Factory
const universalProfileInitStruct = {
salt: SALT,
fundingAmount: 0,
implementationContract: UNIVERSAL_PROFILE_IMPLEMENTATION_ADDRESS_TESTNET,
initializationCalldata: universalProfileImplementationContract.interface.encodeFunctionData(
'initialize',
[LSP23_POST_DEPLOYMENT_MODULE_ADDRESS_TESTNET],
), // this will call the `initialize(...)` function of the Universal Profile and set the LSP23_POST_DEPLOYMENT_MODULE as `owner()`
};

const keyManagerInitStruct = {
fundingAmount: 0,
implementationContract: LSP6_KEY_MANAGER_IMPLEMENTATION_ADDRESS_TESTNET,
addPrimaryContractAddress: true, // this will append the primary contract address to the init calldata
initializationCalldata: '0xc4d66de8', // `initialize(address)` function selector
extraInitializationParams: '0x',
};

// instantiate the erc725.js class
const erc725 = new ERC725([
...LSP6KeyManagerSchemas,
...LSP3ProfileMetadataSchemas,
...LSP1UniversalReceiverDelegateSchemas,
]);

// create the LSP3Metadata data value
const lsp3DataValue = {
verification: {
method: 'keccak256(utf8)',
data: '0x6d6d08aafb0ee059e3e4b6b3528a5be37308a5d4f4d19657d26dd8a5ae799de0',
},
url: 'ipfs://QmPRoJsaYcNqQiUrQxE7ajTRaXwHyAU29tHqYNctBmK64w', // this is an example of Metadata stored on IPFS
};

// create the permissions data keys - value pairs to be set
const setDataKeysAndValues = erc725.encodeData([
{ keyName: 'LSP3Profile', value: lsp3DataValue }, // LSP3Metadata data key and value
{
keyName: 'LSP1UniversalReceiverDelegate',
value: LSP1_UNIVERSAL_RECEIVER_ADDRESS_TESTNET,
}, // Universal Receiver data key and value
{
keyName: 'AddressPermissions:Permissions:<address>',
dynamicKeyParts: [LSP1_UNIVERSAL_RECEIVER_ADDRESS_TESTNET],
value: erc725.encodePermissions({
REENTRANCY: true,
SUPER_SETDATA: true,
}),
}, // Universal Receiver Delegate permissions data key and value
{
keyName: 'AddressPermissions:Permissions:<address>',
dynamicKeyParts: [MAIN_CONTROLLER_EOA],
value: erc725.encodePermissions({
CHANGEOWNER: true,
ADDCONTROLLER: true,
EDITPERMISSIONS: true,
ADDEXTENSIONS: true,
CHANGEEXTENSIONS: true,
ADDUNIVERSALRECEIVERDELEGATE: true,
CHANGEUNIVERSALRECEIVERDELEGATE: true,
REENTRANCY: false,
SUPER_TRANSFERVALUE: true,
TRANSFERVALUE: true,
SUPER_CALL: true,
CALL: true,
SUPER_STATICCALL: true,
STATICCALL: true,
SUPER_DELEGATECALL: false,
DELEGATECALL: false,
DEPLOY: true,
SUPER_SETDATA: true,
SETDATA: true,
ENCRYPT: true,
DECRYPT: true,
SIGN: true,
EXECUTE_RELAY_CALL: true,
}), // Main Controller permissions data key and value
},
// length of the Address Permissions array and their respective indexed keys and values
{
keyName: 'AddressPermissions[]',
value: [LSP1_UNIVERSAL_RECEIVER_ADDRESS_TESTNET, MAIN_CONTROLLER_EOA],
},
]);

const abiCoder = new AbiCoder();
const types = ['bytes32[]', 'bytes[]']; // types of the parameters

const initializeEncodedBytes = abiCoder.encode(types, [
setDataKeysAndValues.keys,
setDataKeysAndValues.values,
]);

// deploy the Universal Profile and its Key Manager
const [upAddress, keyManagerAddress] = await lsp23FactoryContract.deployERC1167Proxies.staticCall(
universalProfileInitStruct,
keyManagerInitStruct,
LSP23_POST_DEPLOYMENT_MODULE_ADDRESS_TESTNET,
initializeEncodedBytes,
);
console.log('Universal Profile address:', upAddress);
console.log('Key Manager address:', keyManagerAddress);

const tx = await lsp23FactoryContract.deployERC1167Proxies(
universalProfileInitStruct,
keyManagerInitStruct,
LSP23_POST_DEPLOYMENT_MODULE_ADDRESS_TESTNET,
initializeEncodedBytes,
);
await tx.wait();
}

main();

0 comments on commit c5cd9a2

Please sign in to comment.