---
# System prepended metadata

title: Untitled

---

i was curious of this new way of storing AllowedERC725Ykeys so i had a nice exercise, check it out:

```
3,0xA00000,1,0xDD,255,0xAA...0032,0xBB...0032,0xCC...0032
```

0xA00000

| prefix length 1 - 1 byte | prefix 1 - dynamic length | prefix length - 1 byte | prefix 2 - dynamic length | full-match divider - 1 byte (value: 255) | full key 1 - 32 bytes | full key 2 - 32 bytes | full key 3 - 32 bytes |


```
[
    3,0xA00000, // exactly 3 bytes
    1,0xDD, // exactly 1 byte
    255, // seperator (0xff) 1111 1111
    0xAA...0032,    // 32 bytes
    0xBB...0032,    // 32 bytes
    0xCC...0032    // 32 bytes
]
```

``` solidity
function chechAllowedERC725YKey5(
    bytes32 checkedKey,
    bytes calldata allowedERC725YKeys
) public pure returns(bool foundAllowedKey) {
    /**
     * pointer will always land on these values:
     *
     * ↓↓
     * 03 a00000
     * 03 fff83a
     * ff
     * aa0000000000000000000000000000000000000000000000000000000000beef
     * bb0000000000000000000000000000000000000000000000000000000000beef
     * cc0000000000000000000000000000000000000000000000000000000000beef
     * ↑↑
     *
     * the values on which the pointer can land are the following
     * - the length of a dynamic key
     * - the separator
     * - the first index of a fixed key
     */
    uint256 pointer = 0;

    // dynamic keys <-- separator --> fixed keys 
    bytes1 separator = 0xff;

    // false until allowedERC725YKeys[] == separator
    bool foundSeparator = allowedERC725YKeys[pointer] == separator;  

    /**
     * iterate over each key by saving in the `pointer` variable the index for
     * the length of the following key until we find the key or we land on the separator
     * 
     * 0x 03 a00000 03 fff83a ff ...
     *    ↑↑        ↑↑        ↑↑
     *  first  |  second  | separator
     *  length |  length  |
     */
    while (!foundAllowedKey && !foundSeparator) {
        /**
         * save the length of the following allowed key
         * which is saved in `allowedERC725YKeys[pointer]`
         */
        uint256 length = uint256(uint8(bytes1(allowedERC725YKeys[pointer])));

        /*
         * transform the allowed key situated from `pointer + 1` until `pointer + 1 + length` to a bytes32 value
         * E.g. 0xfff83a -> 0xfff83a0000000000000000000000000000000000000000000000000000000000
         */
        bytes32 allowedDynamicKey = bytes32(allowedERC725YKeys[pointer + 1:pointer + 1 + length]);

        /**
         * the bitmask discard the last `32 - length` bytes of the input key via ANDing &
         * so to compare only the relevant parts of each ERC725Y keys
         *
         * E.g.:
         *
         * allowed key = 0xa00000
         *               
         *      &     compare this part
         *                 vvvvvv
         * checked key = 0xa00000cafecafecafecafecafecafecafe000000000000000000000011223344
         *
         *                                              discard this part
         *                       vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
         *        mask = 0xffffff0000000000000000000000000000000000000000000000000000000000
         */
        bytes32 mask = bytes32(
            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
        ) << (8 * (32 - length));

        if (allowedDynamicKey == (checkedKey & mask)) {
            // voila you found the key ;)
            foundAllowedKey = true;
        }
        else {
            // move the pointer to the first index of the first fixed key
            pointer += length + 1;
        }

        /**
         * if the value at the current `pointer` is the separator we move to the fixed keys
         */
        if (allowedERC725YKeys[pointer] == separator) {
            foundSeparator = true;
            // set the pointer to the first byte of the first fixed key
            pointer++;
        }
    }

    /**
     * iterate over the fixed keys and check for match with the `checkedKey`
     * pointer will start at the first byte of the first fixed key
     * and will only land on the first byte of each fixed key
     * until the key is found or there's nothing left to check
     * 
     *  ...ff aa0000000000000000000000000000000000000000000000000000000000cafe...
     *        ↑↑
     * | first byte of the |
     * | first fixed key   |
     * ...cafebb0000000000000000000000000000000000000000000000000000000000beef...
     *        ↑↑
     * | first byte of the |
     * | second fixed key  |
     * ...beefcc0000000000000000000000000000000000000000000000000000000000deed
     *        ↑↑
     * | first byte of the |
     * | third fixed key   |
     */
    while (!foundAllowedKey && foundSeparator && allowedERC725YKeys.length >= pointer + 32) {
        bytes memory memoryAllowedERC725YKeys = allowedERC725YKeys;
        bytes32 allowedFixedKey;
        bytes32 bytes32Pointer = bytes32(32 + pointer);

        //save the key from the index `32 + pointer` until `64 + pointer`
        assembly {
            allowedFixedKey := mload(add(memoryAllowedERC725YKeys, bytes32Pointer))
        }

        // check the match for the `allowedFixedKey` and `checkedKey`
        if(allowedFixedKey == checkedKey) foundAllowedKey = true; // voila you found the key ;)

        // update the pointer to the first byte of the next fixed key
        pointer += 32;
    }
}
```