-
Notifications
You must be signed in to change notification settings - Fork 50
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
fix: (C4 #97) add check for length == 0
to prevent mask
to allow any data key
#659
fix: (C4 #97) add check for length == 0
to prevent mask
to allow any data key
#659
Conversation
👋 Hello ⛽📊 See Gas Benchmark report of Using UniversalProfile owned by an EOA🔀
|
execute scenarios - 👑 UP Owner |
⛽ Gas Usage |
---|---|
Transfer 1 LYX to an EOA without data | 37537 |
Transfer 1 LYX to a UP without data | 36639 |
Transfer 1 LYX to an EOA with 256 bytes of data | 42210 |
Transfer 1 LYX to a UP with 256 bytes of data | 44750 |
Transfer 0.1 LYX to 3x EOA without data | 70862 |
Transfer 0.1 LYX to 3x UP without data | 75680 |
Transfer 0.1 LYX to 3x EOA with 256 bytes of data | 84850 |
Transfer 0.1 LYX to 3x EOA with 256 bytes of data | 99898 |
🗄️ setData
scenarios
setData scenarios - 👑 UP Owner |
⛽ Gas Usage |
---|---|
Set a 20 bytes long value | 49971 |
Set a 60 bytes long value | 95281 |
Set a 160 bytes long value | 164453 |
Set a 300 bytes long value | 279700 |
Set a 600 bytes long value | 484112 |
Change the value of a data key already set | 32859 |
Remove the value of a data key already set | 27333 |
Set 2 data keys of 20 bytes long value | 78428 |
Set 2 data keys of 100 bytes long value | 260580 |
Set 3 data keys of 20 bytes long value | 105145 |
Change the value of three data keys already set of 20 bytes long value | 45445 |
Remove the value of three data keys already set | 41339 |
🗄️ Tokens
scenarios
Tokens scenarios - 👑 UP Owner |
⛽ Gas Usage |
---|---|
Minting a LSP7Token to a UP (No Delegate) from an EOA | 91241 |
Minting a LSP7Token to an EOA from an EOA | 59206 |
Transferring an LSP7Token from a UP to another UP (No Delegate) | 98689 |
Minting a LSP8Token to a UP (No Delegate) from an EOA | 158192 |
Minting a LSP8Token to an EOA from an EOA | 126157 |
Transferring an LSP8Token from a UP to another UP (No Delegate) | 147236 |
📝 Notes
- The
execute
andsetData
scenarios are executed on a fresh UniversalProfile smart contract, deployed as standard contracts (not as proxy behind a base contract implementation).
⛽📊 See Gas Benchmark report of Using UniversalProfile owned by an LSP6KeyManager
This document contains the gas usage for common interactions and scenarios when using UniversalProfile smart contracts.
🔀 execute
scenarios
👑 unrestricted controller
execute scenarios - 👑 main controller |
⛽ Gas Usage |
---|---|
transfer LYX to an EOA | 60439 |
transfer LYX to a UP | 62041 |
transfer tokens (LSP7) to an EOA (no data) | 107162 |
transfer tokens (LSP7) to a UP (no data) | 242734 |
transfer a NFT (LSP8) to a EOA (no data) | 171009 |
transfer a NFT (LSP8) to a UP (no data) | 289909 |
🛃 restricted controller
execute scenarios - 🛃 restricted controller |
⛽ Gas Usage |
---|---|
transfer some LYXes to an EOA - restricted to 1 x allowed address only (TRANSFERVALUE + 1x AllowedCalls) | 72648 |
transfers some tokens (LSP7) to an EOA - restricted to LSP7 + 2x allowed contracts only (CALL + 2x AllowedCalls) (no data) | 122941 |
transfers some tokens (LSP7) to an other UP - restricted to LSP7 + 2x allowed contracts only (CALL + 2x AllowedCalls) (no data) | 258513 |
transfers a NFT (LSP8) to an EOA - restricted to LSP8 + 2x allowed contracts only (CALL + 2x AllowedCalls) (no data) | 186776 |
transfers a NFT (LSP8) to an other UP - restricted to LSP8 + 2x allowed contracts only (CALL + 2x AllowedCalls) (no data) | 305676 |
🗄️ setData
scenarios
👑 unrestricted controller
setData scenarios - 👑 main controller |
⛽ Gas Usage |
---|---|
updates profile details (LSP3Profile metadata) | 136875 |
give permissions to a controller (AddressPermissions[] + AddressPermissions[index] + AddressPermissions:Permissions:) | 132906 |
restrict a controller to some specific ERC725Y Data Keys | 139282 |
restrict a controller to interact only with 3x specific addresses | 161986 |
remove a controller (its permissions + its address from the AddressPermissions[] array) | 67871 |
write 5x LSP12 Issued Assets | 233253 |
🛃 restricted controller
setData scenarios - 🛃 restricted controller |
⛽ Gas Usage |
---|---|
setData(bytes32,bytes) -> updates 1x data key |
102776 |
setData(bytes32[],bytes[]) -> updates 3x data keys (first x3) |
161515 |
setData(bytes32[],bytes[]) -> updates 3x data keys (middle x3) |
145669 |
setData(bytes32[],bytes[]) -> updates 3x data keys (last x3) |
171002 |
setData(bytes32[],bytes[]) -> updates 2x data keys + add 3x new controllers (including setting the array length + indexes under AddressPermissions[index]) |
249922 |
📝 Notes
- The
execute
andsetData
scenarios are executed on a fresh UniversalProfile and LSP6KeyManager smart contracts, deployed as standard contracts (not as proxy behind a base contract implementation).
Changes to gas cost
🧾 Summary (10% most significant diffs)
Full diff report 👇
|
da084b1
to
79f2012
Compare
length == 0
to prevent mask
to allow any data keylength == 0
to prevent mask
to allow any data key
functionArgs | ||
); | ||
|
||
// CHECK it reverts when calling via the Key Manager |
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.
How you are testing for revert ? I don't see any vm.expectRevert
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.
because it using testFail_
pattern. it is expecting a revert
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.
Ah nice, didn't see it
d43c2d8
to
0179a70
Compare
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.
LGTM. Interesting though that with vm.expectRevert
it is not working
0179a70
to
456f418
Compare
What does this PR introduce?
🐛 Bug Fixes
Overview
There is an insufficient length check when validating the allowed data keys that can be set by a caller. In particular, if a decoded length in the compact bytes array happens to be 0, the caller will be validated against any data key.
Although a decoded length is not possible when setting allowed data keys via the
LSP6SetDataModule
contract, there is no guarantee that data values before ownership transfer to an LSP6 contract are valid. This allows a scamming opportunity as malicious actors who set-up an ERC725 contract for another can create a backdoor that cannot be easily seen as the allowed data keys will simply have an extra0x0000
.When verifying allowed data keys that a caller can set, a length check is done on the first 2 bytes of a compact bytes array to ensure that the length does not exceed a data key's length.
This length value is used to decide the bit mask when validating data keys.
In the case that
length == 0
, thenmask == bytes32(0)
.Then the validation check for all data keys will pass as the validation will be reduced to whether or not
allowedKey & bytes32(0) == inputDataKey & bytes32(0)
, which is always true.This allows the caller to set data values for all data keys except those used for LSP1, LSP6, and LSP17 due to the initial checks in
LSP6SetDataModule._getPermissionRequiredToSetDataKey(...)
. In particular, they would be able to obstruct data values for the following established keys:LSP3 keys detailing information about a universal profile
LSP5 keys detailing information about received assets
LSP10 keys detailing information about vault ownership
Implemented Fixes
add a check in
LSP6SetDataModule
to revert if in the extracted from theAllowedERC725YDataKeys
read from the linked account storage, there is an entry in the CompactByteArray that is0x0000
, meaning thelength
for the entry (= the allowed data key) is0
.Add Foundry tests to test that the scenario described above reverts
PR Checklist
npm run lint
&&npm run lint:solidity
(solhint)npm run format
(prettier)npm run build
npm run test