# How does the Storage work with an array of length 2^256 - 1?

If you have a dynamic array that stores `bytes32` (called arr) and do `arr.length--;` (Assuming there is no underflow protection, i.e. pre solc 0.8.0) Then the length of `arr` would become 2^256 - 1, taking up the entire storage space, thus allowing you to manipulate different state variables indirectly via this array.

Where in the storage would you access the last member of the array? My guess is the last item of the array would be keccak256(p) - 1 although i am uncertain.

If you change the storage slot that keeps the length of the array (position p) to 500 for example, what would happen to other slots previously designated to the array, e.g. lets say slot 2^256 -1 currently holds 0x10 (padded with 0's to reach 32 bytes) what happens to this slot once the length of `arr` is changed to 500?

For some context: https://listed.to/@r1oga/13892/ethernaut-levels-19-to-21#AlienCodex

Read the section on level 20 (alien codex).

Your link already answer your question. You would access each element at their "normal" index . If you override/reduce the length to length', the index > length' cannot be accessed anymore (at high level at least) - ie in your example, reducing to 500 means you cannot access array[2^256-1] without assembly, and it reverts.

Proof/test for yourself: The following contract starts with a dynamic array of length 5, you can get element via high or low-level call. Then you can override the array length an try retrieving value via high-level call (array[idx]) -> fail, or low-level (in assembly, get elt stored at index x) -> still present:

``````pragma solidity ^0.7.6;

contract TestArray {

uint256[] abc;

constructor() {
abc.push(1);
abc.push(2);
abc.push(3);
abc.push(4);
abc.push(5); // length = 5
}

function getLength() external view returns (uint256 lgth) {
assembly {
let ptr := abc.slot
}
}

function newLength() external {
assembly {
let ptr := abc.slot
sstore(abc.slot, 2)
}
}

function getElt(uint256 idx) external view returns (uint256) {
return abc[idx];
}

function getStorage(uint256 idx) external view returns (uint256 res) {
assembly {
let ptr := abc.slot
}
}
}
``````

More details :

The array length insure the requested index is not out of bound. For instance, if you debug the (obviously) failed call to test(4) in this contract :

``````pragma solidity ^0.7.6;

uint256[] abc;

function test(uint256 idx) public view returns (uint256 res) {
return abc[idx];
}

}
``````

Here is what happens in assembly and to the stack :

``````            stack:   0            1      2
113 DUP2    ->                    4