diff --git a/bun.lockb b/bun.lockb index 12d79d4..129a82e 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/key-manager/.env.example b/key-manager/.env.example new file mode 100644 index 0000000..fb80cc2 --- /dev/null +++ b/key-manager/.env.example @@ -0,0 +1,2 @@ +PRIVATE_KEY=0x... +UP_ADDR=0x... \ No newline at end of file diff --git a/key-manager/execute-relay-call.ts b/key-manager/execute-relay-call.ts index d0374b8..cfe1582 100644 --- a/key-manager/execute-relay-call.ts +++ b/key-manager/execute-relay-call.ts @@ -12,7 +12,7 @@ const universalProfileAddress = '0x...'; const recipientAddress = '0x...'; // Setup the Universal Profile controller account -const controllerPrivateKey = '0x...'; +const controllerPrivateKey = process.env.PRIVATE_KEY || ''; const controllerAccount = new ethers.Wallet(controllerPrivateKey).connect( provider, ); diff --git a/key-manager/grant-permissions.ts b/key-manager/grant-permissions.ts new file mode 100644 index 0000000..7e2f6fb --- /dev/null +++ b/key-manager/grant-permissions.ts @@ -0,0 +1,90 @@ +import { ethers } from 'ethers'; +import { ERC725 } from '@erc725/erc725.js'; +import LSP6Schema from '@erc725/erc725.js/schemas/LSP6KeyManager.json'; +import UniversalProfileArtifact from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; + +const myUniversalProfileAddress = process.env.UP_ADDR || ''; + +const RPC_ENDPOINT = 'https://4201.rpc.thirdweb.com'; +const provider = new ethers.JsonRpcProvider(RPC_ENDPOINT); + +// Initialize erc725.js with the permission data keys from LSP6 Key Manager +const erc725 = new ERC725( + LSP6Schema, + myUniversalProfileAddress, + RPC_ENDPOINT, + {}, +); + +// Create the permissions for the beneficiary address +const beneficiaryPermissions = erc725.encodePermissions({ + SETDATA: true, +}); + +// EOA address of the new controller +const myBeneficiaryAddress = '0xcafecafecafecafecafecafecafecafecafecafe'; + +// Retrieve the current controllers of the Universal Profile +const addressPermissionsArray = await erc725.getData('AddressPermissions[]'); +let currentControllerAddresses = null; +let currentControllerLength = 0; + +if (Array.isArray(addressPermissionsArray.value)) { + currentControllerAddresses = addressPermissionsArray.value; + currentControllerLength = currentControllerAddresses.length; +} + +// Encode the key-value pairs of the controller permission +const permissionData = erc725.encodeData([ + // the permission of the beneficiary address + { + keyName: 'AddressPermissions:Permissions:
', + dynamicKeyParts: myBeneficiaryAddress, + value: beneficiaryPermissions, + }, + // The new incremented list of permissioned controllers addresses + { + keyName: 'AddressPermissions[]', + value: [myBeneficiaryAddress], + startingIndex: currentControllerLength, + totalArrayLength: currentControllerLength + 1, + }, +]); + +// Private key to sign the transaction +const PRIVATE_KEY = process.env.PRIVATE_KEY || ''; + +// Existing UP controller +const controller = new ethers.Wallet(PRIVATE_KEY).connect(provider); + +// instantiate the Universal Profile +const myUniversalProfile = new ethers.Contract( + myUniversalProfileAddress, + UniversalProfileArtifact.abi, +); + +try { + // Execute the transaction + await myUniversalProfile + .connect(controller) + // @ts-expect-error Ethers BaseContract does not pick dynamic types from ABIs + .setData(permissionData.keys, permissionData.values); + + const updatedPermissions = await erc725.getData({ + keyName: 'AddressPermissions:Permissions:
', + dynamicKeyParts: myBeneficiaryAddress, + }); + + if (updatedPermissions && typeof updatedPermissions.value === 'string') { + console.log( + `The beneficiary address ${myBeneficiaryAddress} has the following permissions:`, + erc725.decodePermissions(updatedPermissions.value), + ); + } else { + console.error( + `No permissions for beneficiary address ${myBeneficiaryAddress} found`, + ); + } +} catch (error) { + console.error('Could not execute the controller update:', error); +} diff --git a/key-manager/set-permissions.ts b/key-manager/set-permissions.ts deleted file mode 100644 index 4567918..0000000 --- a/key-manager/set-permissions.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { ethers } from 'ethers'; -import { - PERMISSIONS, - ERC725YDataKeys, -} from '@lukso/lsp-smart-contracts/constants'; -import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; - -// Connect to the LUKSO Testnet -const RPC_ENDPOINT = 'https://4201.rpc.thirdweb.com'; -const provider = new ethers.JsonRpcProvider(RPC_ENDPOINT); - -const myUniversalProfileAddress = '0x9fc7e5095A054dfA3c6b237E0e5d686638394248'; -const myKeyManagerAddress = '0x87fa9105cA247897Acb4F12Ddf6EC3CEF23F6059'; - -const walletPrivateKey = - '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'; // Replace with your wallet's private key -const wallet = new ethers.Wallet(walletPrivateKey, provider); - -const universalProfile = new ethers.Contract( - myUniversalProfileAddress, - UniversalProfile.abi, - wallet, -); - -// EOA address of an exemplary person -const bobAddress = '0xcafecafecafecafecafecafecafecafecafecafe'; -const bobPermissions = PERMISSIONS.SETDATA; - -// give the permission SETDATA to Bob -async function setPermission() { - try { - const permissionData = [ - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - bobAddress.substring(2), // allow Bob to setData on your UP - ERC725YDataKeys.LSP6['AddressPermissions[]'].length, // length of AddressPermissions[] - ERC725YDataKeys.LSP6['AddressPermissions[]'].index + - '00000000000000000000000000000001', // add Bob's address into the list of permissions - ]; - - const permissionParams = [ - bobPermissions, - 3, // 3 because UP owner + Universal Receiver Delegate permission have already been set on profile creation - bobAddress, - ]; - - const tx = await universalProfile.setDataBatch.populateTransaction( - permissionData, - permissionParams, - ); - - const txResponse = await wallet.sendTransaction({ - to: myKeyManagerAddress, - data: tx.data, - gasLimit: 300000, - }); - - await txResponse.wait(); - console.log('Permission set successfully.'); - } catch (error) { - console.error('Error:', error); - } -} - -setPermission(); diff --git a/package.json b/package.json index 5115883..d4c0b9f 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,7 @@ "lint:fix": "eslint . --fix" }, "devDependencies": { - "@erc725/erc725.js": "^0.24.1", - "@lukso/eip191-signer.js": "^0.2.2", + "@erc725/erc725.js": "^0.24.2", "@lukso/lsp-smart-contracts": "^0.14.0", "@typescript-eslint/eslint-plugin": "^6.20.0", "@typescript-eslint/parser": "^6.20.0",