-
Notifications
You must be signed in to change notification settings - Fork 29
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
feat: add ALL_PERMISSIONS flag to encoding #384
Changes from all commits
8a518eb
ff19b0e
a63b82d
8ecbc25
dfdd027
3bd4b93
0b7a93b
b050aeb
269a540
ebea7f5
0c75f63
4401e62
22c5e1a
303720a
714495f
44ab226
0d0064d
6ef86bc
ed3522b
fbca5c4
88b0e03
3ec90bf
866ba2c
b3027c6
89c41e5
100d42b
20198f4
2aaeeb1
e4c09c7
4c5860d
d9e647c
42e105e
6982b23
4635125
51c29c5
3b688a9
3a2d725
9b80d75
fc0ee1a
636d4c9
489a9e7
de6452e
9d08111
b1bb164
1562a9d
4cda9b9
120d5ee
86301ca
90f735c
3720b17
330cb7d
3994b72
1dd59bf
9cda880
b35001f
8adad51
53c1a51
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,7 @@ import 'isomorphic-fetch'; | |
|
||
import { | ||
ERC725Y_INTERFACE_IDS, | ||
LSP6_DEFAULT_PERMISSIONS, | ||
SUPPORTED_VERIFICATION_METHOD_STRINGS, | ||
} from './constants/constants'; | ||
import { decodeKey } from './lib/decodeData'; | ||
|
@@ -1192,6 +1193,7 @@ describe('Running @erc725/erc725.js tests...', () => { | |
SIGN: true, | ||
EXECUTE_RELAY_CALL: false, | ||
ERC4337_PERMISSION: false, | ||
ALL_PERMISSIONS: false, | ||
}, | ||
hex: '0x00000000000000000000000000000000000000000000000000000000003f3f7f', | ||
}, | ||
|
@@ -1221,6 +1223,7 @@ describe('Running @erc725/erc725.js tests...', () => { | |
SIGN: false, | ||
EXECUTE_RELAY_CALL: false, | ||
ERC4337_PERMISSION: false, | ||
ALL_PERMISSIONS: false, | ||
}, | ||
hex: '0x0000000000000000000000000000000000000000000000000000000000000000', | ||
}, | ||
|
@@ -1250,6 +1253,7 @@ describe('Running @erc725/erc725.js tests...', () => { | |
SIGN: true, | ||
EXECUTE_RELAY_CALL: false, | ||
ERC4337_PERMISSION: false, | ||
ALL_PERMISSIONS: false, | ||
}, | ||
hex: '0x0000000000000000000000000000000000000000000000000000000000200a00', | ||
}, | ||
|
@@ -1279,6 +1283,7 @@ describe('Running @erc725/erc725.js tests...', () => { | |
SIGN: false, | ||
EXECUTE_RELAY_CALL: false, | ||
ERC4337_PERMISSION: false, | ||
ALL_PERMISSIONS: false, | ||
}, | ||
hex: '0x0000000000000000000000000000000000000000000000000000000000040800', | ||
}, | ||
|
@@ -1308,6 +1313,7 @@ describe('Running @erc725/erc725.js tests...', () => { | |
SIGN: false, | ||
EXECUTE_RELAY_CALL: false, | ||
ERC4337_PERMISSION: false, | ||
ALL_PERMISSIONS: false, | ||
}, | ||
hex: '0x0000000000000000000000000000000000000000000000000000000000040004', | ||
}, | ||
|
@@ -1337,6 +1343,7 @@ describe('Running @erc725/erc725.js tests...', () => { | |
SIGN: false, | ||
EXECUTE_RELAY_CALL: false, | ||
ERC4337_PERMISSION: false, | ||
ALL_PERMISSIONS: false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be worth adding some extra tests to tests that when all permission is set and others are set to false, it removes them, etc... More cases There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes ideally we can randomize them like i did for some tests i added. I find it not efficient to do one test at a time. Will think about it |
||
}, | ||
hex: '0x0000000000000000000000000000000000000000000000000000000000000a00', | ||
}, | ||
|
@@ -1376,13 +1383,120 @@ describe('Running @erc725/erc725.js tests...', () => { | |
}); | ||
}); | ||
|
||
describe('Randomized Permissions Encoding', () => { | ||
function convertToPermissionBits(permissions: { [key: string]: string }) { | ||
const permissionBits = {}; | ||
Object.entries(permissions).forEach(([key, hexValue]) => { | ||
// Convert hex to binary, then find the position of the '1' bit | ||
const bitPosition = BigInt(hexValue).toString(2).length - 1; | ||
permissionBits[key] = bitPosition; | ||
}); | ||
return permissionBits; | ||
} | ||
|
||
// remove LSP6_DEFAULT_PERMISSIONS.ALL_PERMISSIONS from LSP6_DEFAULT_PERMISSIONS | ||
const ALL_PERMISSIONS_WITHOUT_ALL_PERMISSIONS = Object.keys( | ||
LSP6_DEFAULT_PERMISSIONS, | ||
).reduce((acc, key) => { | ||
if (key !== 'ALL_PERMISSIONS') { | ||
acc[key] = LSP6_DEFAULT_PERMISSIONS[key]; | ||
} | ||
return acc; | ||
}, {}); | ||
|
||
// Use the function to generate permissionBits | ||
const permissionBits = convertToPermissionBits( | ||
ALL_PERMISSIONS_WITHOUT_ALL_PERMISSIONS, | ||
); | ||
|
||
// Function to generate a random permissions object | ||
const generateRandomPermissions = () => { | ||
return Object.keys(permissionBits).reduce((acc, key) => { | ||
// Randomly assign true or false | ||
acc[key] = Math.random() < 0.5; | ||
return acc; | ||
}, {}); | ||
}; | ||
|
||
// Function to calculate expected hex based on permissions | ||
const calculateExpectedHex = (permissions) => { | ||
let basePermissions = BigInt(0); | ||
Object.entries(permissions).forEach(([key, value]) => { | ||
if (value) { | ||
const bitPosition = permissionBits[key]; | ||
basePermissions |= BigInt(1) << BigInt(bitPosition); | ||
} | ||
}); | ||
// Convert to hex string, properly padded | ||
return `0x${basePermissions.toString(16).padStart(64, '0')}`; | ||
}; | ||
|
||
// Run the randomized test multiple times | ||
const numberOfTests = 100; // Number of random tests | ||
for (let i = 0; i < numberOfTests; i++) { | ||
it(`Randomized test #${i + 1}`, () => { | ||
const randomPermissions = generateRandomPermissions(); | ||
const encoded = ERC725.encodePermissions(randomPermissions); | ||
const expectedHex = calculateExpectedHex(randomPermissions); | ||
assert.strictEqual( | ||
encoded, | ||
expectedHex, | ||
`Failed at randomized test #${i + 1}`, | ||
); | ||
}); | ||
} | ||
}); | ||
|
||
describe('all permissions', () => { | ||
it('should encode ALL_PERMISSIONS correctly', () => { | ||
const permissions = { ALL_PERMISSIONS: true }; | ||
const encoded = ERC725.encodePermissions(permissions); | ||
|
||
assert.strictEqual( | ||
encoded, | ||
LSP6_DEFAULT_PERMISSIONS.ALL_PERMISSIONS, | ||
'Encoded permissions do not match expected value for ALL_PERMISSIONS', | ||
); | ||
}); | ||
|
||
it('should ignore individual permissions when ALL_PERMISSIONS is set', () => { | ||
const permissions = { | ||
ALL_PERMISSIONS: true, | ||
CHANGEOWNER: true, | ||
}; | ||
const encoded = ERC725.encodePermissions(permissions); | ||
assert.strictEqual( | ||
encoded, | ||
LSP6_DEFAULT_PERMISSIONS.ALL_PERMISSIONS, | ||
'ALL_PERMISSIONS did not correctly encode with additional permissions', | ||
); | ||
}); | ||
it('should be able to disable permissions that are part of ALL_PERMISSIONS', () => { | ||
const permissions = { | ||
ALL_PERMISSIONS: true, | ||
CHANGEOWNER: false, // Explicitly disable CHANGEOWNER | ||
}; | ||
|
||
const encoded = ERC725.encodePermissions(permissions); | ||
const decodedPermissions = ERC725.decodePermissions(encoded); | ||
|
||
// check that the permission is disabled | ||
assert.strictEqual( | ||
decodedPermissions.CHANGEOWNER, | ||
false, | ||
'CHANGEOWNER permission was not correctly disabled', | ||
); | ||
}); | ||
}); | ||
|
||
describe('decodePermissions', () => { | ||
testCases.forEach((testCase) => { | ||
it(`Decodes ${testCase.hex} permission correctly`, () => { | ||
assert.deepStrictEqual( | ||
ERC725.decodePermissions(testCase.hex), | ||
testCase.permissions, | ||
); | ||
|
||
assert.deepStrictEqual( | ||
erc725Instance.decodePermissions(testCase.hex), | ||
testCase.permissions, | ||
|
@@ -1419,6 +1533,7 @@ describe('Running @erc725/erc725.js tests...', () => { | |
SIGN: true, | ||
EXECUTE_RELAY_CALL: true, | ||
ERC4337_PERMISSION: true, | ||
ALL_PERMISSIONS: true, | ||
}, | ||
); | ||
assert.deepStrictEqual( | ||
|
@@ -1450,6 +1565,7 @@ describe('Running @erc725/erc725.js tests...', () => { | |
SIGN: true, | ||
EXECUTE_RELAY_CALL: true, | ||
ERC4337_PERMISSION: true, | ||
ALL_PERMISSIONS: true, | ||
}, | ||
); | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest adding a comment that this is not a standard permission defined in LSP6, but used for integration of ERC4337 standard.
Otherwise, people might look into the LSP6 specs to understand what this is used for, but will not find it.
Do we have a link in our docs or a guide that mentions this permission? Maybe worth adding it here.
@Hugoo @skimaharvey wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i agree that this is confusing. I am not sure if the confusion starts at the lib level but imo more at the LIPs level and probably we should fix it there first