Get List of Permissioned Addresses
You can find the scripts of this guide within our lukso-playground
repository.
This guide shows how to retrieve the list of addresses that have some permissions on a Universal Profile. We commonly call these addresses controllers.
Alongside each controller, we will also retrieve their associated permissions. All of this will involve 3 steps:
- retrieve all controller addresses of a Universal Profile.
- retrieve the encoded permissions of each controller.
- decode these permissions in a human readable way
Setupβ
We will use the erc725.js
library to easily query and decode the AddressPermissions[]
and AddressPermissions:Permissions:<controller-address>
data keys on the Universal Profile.
npm install @erc725/erc725.js
Step 1 - Instantiate erc725.jsβ
First let's initialize erc725.js and connect it to a specific Universal Profile address on LUKSO Testnet. This will enable us to query its storage easily.
import { ERC725 } from '@erc725/erc725.js';
// This contains the schemas of the data keys:
// - AddressPermissions[] -> list of controllers
// - `AddressPermission:Permissions:<controller-address> -> permission of a specific controller
import LSP6Schema from '@erc725/erc725.js/schemas/LSP6KeyManager.json';
// Sample Profile Address
const UNIVERSAL_PROFILE = '0xEda145b45f76EDB44F112B0d46654044E7B8F319';
// Instantiate erc725.js with a Universal Profile address on Testnet
const erc725 = new ERC725(
LSP6Schema,
UNIVERSAL_PROFILE,
'https://rpc.testnet.lukso.network',
);
Step 2 - Get the list of controllersβ
You can now simply query the AddressPermissions[]
data key with the getData('AddressPermissions[]')
function from erc725.js. This will return you an array of addresses.
async function getPermissionedAddresses() {
// Get the list of addresses that have permissions on the Universal Profile
const controllerAddresses = await erc725.getData('AddressPermissions[]');
if (!controllerAddresses) {
console.log('No controllers listed under this Universal Profile ');
} else {
console.log(controllerAddresses);
// {
// key: '0xdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e3',
// name: 'AddressPermissions[]',
// value: [
// '0x5F606b5b237623463a90F63230F9b929321dbCBa',
// '0xa1061408e55c971fD129eF5561dFB953d598dAD7'
// ]
// }
}
}
Step 3 - Get controller's permissionsβ
Now that we have all the controller's addresses, You can retrieve the permissions of each individual controller by querying the data key AddressPermissions:Permissions:<controller-address>
. This involves 2 steps:
- Get the raw encoded
bytes32
permission for the controller. - Decode this permission value to get an object listing which permissions are set or not for this controller.
3.1 - Get the encoded permission of the controller.β
Let's first understand how to query the controller's permission!
You will have to replace the <controller-address>
part with the actual address of the controller. Therefore the data key for the controller address 0xcafecafecafecafecafecafecafecafecafecafe
will look as follow:
// human readable
`AddressPermissions:Permissions:<controller-address>`
// in hex
0x4b80742de2bf82acb3630000<controller-address>
// final data key with actual controller address 0xcafecafe...
0x4b80742de2bf82acb3630000cafecafecafecafecafecafecafecafecafecafe
Thankfully, erc725.js manages all this complexity for us! Simply use the getData(...)
function and pass the controller address as option to the dynamicKeyPart
. See the code snippet below:
async function getPermissionedAddresses() {
// ...
if (Array.isArray(controllerAddresses.value)) {
// Get the permissions of each controller of the UP
for (let i = 0; i < controllerAddresses.value.length; i++) {
const address = controllerAddresses.value[i] as string;
const permissionsValue = await erc725.getData({
keyName: 'AddressPermissions:Permissions:<address>',
dynamicKeyParts: address,
});
console.log(permissionsValue);
// {
// key: '0x4b80742de2bf82acb3630000a1061408e55c971fd129ef5561dfb953d598dad7',
// name: 'AddressPermissions:Permissions:a1061408e55c971fD129eF5561dFB953d598dAD7',
// value: '0x0000000000000000000000000000000000000000000000000000000000000008'
// }
}
}
}
3.2 - Decode the permissionβ
The value
above 0x0000...0008
in the object does not give us a lot of information. This is because permissions are encoded as a BitArray
.
Luckily, we don't need to understand the complexity behind the scene to understand the permissions that are set. After retrieving these encoded permission values, we can use again the decodePermissions(...)
function from the erc725.js library to decode them easily.
The function returns an object showing which permissions the controller has with true
or false
.
async function getPermissionedAddresses() {
// ...
if (Array.isArray(controllerAddresses.value)) {
// ...
// Decode the permission of each address
const decodedPermissions = erc725.decodePermissions(permissionsValue.value as string);
// Display the permission in a readable format
console.log(
`Decoded permission for ${address} = ` + JSON.stringify(decodedPermissions, null, 2),
);
// Decoded permission for 0x5F606b5b237623463a90F63230F9b929321dbCBa = {
// "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,
// }
}
}
getPermissionedAddresses();