Skip to content

Instantly share code, notes, and snippets.

@ItsCuzzo
Last active September 14, 2022 14:11
Show Gist options
  • Save ItsCuzzo/6083865aaeabd104319cf7705c909a00 to your computer and use it in GitHub Desktop.
Save ItsCuzzo/6083865aaeabd104319cf7705c909a00 to your computer and use it in GitHub Desktop.
Understanding arrays using assembly.
contract AsmArray {
uint256[] public arr;
/// @dev Push some dummy data to begin with.
constructor() {
arr.push(1);
arr.push(2);
}
/// @dev Function used to view the value of `arr[idx]`.
/// This function will return 0 if out of bounds `idx` is provided.
function viewStorageAtIdx(uint256 idx) external view returns (uint256) {
assembly {
mstore(0x00, arr.slot)
mstore(0x40, sload(add(keccak256(0, 32), idx)))
return(0x40, 32)
}
}
/// @dev Function used to push a `val` to `arr`.
function pushToArr(uint256 val) external {
assembly {
/// Reuse array length to avoid double sload.
let len := sload(arr.slot)
mstore(0x00, arr.slot)
/// Store `val` in array at `len`.
sstore(add(keccak256(0, 32), len), val)
/// Increment value of `arr.slot` which is the length of the array by 1.
sstore(arr.slot, add(len, 1))
}
}
/// @dev Function used to return the current length of `arr`.
function getArrLength() external view returns (uint256) {
assembly {
/// Store the current length of `arr` in memory at fmp.
mstore(0x40, sload(arr.slot))
return(0x40, 32)
}
}
}
@atarpara
Copy link

atarpara commented Aug 30, 2022

contract AsmArray {
    uint256[] public arr;

    /// @dev Push some dummy data to begin with.
    constructor() {
        arr.push(1);
        arr.push(2);
    }

    /// @dev Function used to view the value of `arr[idx]`.
    /// This function will return 0 if out of bounds `idx` is provided.
    function viewStorageAtIdx(uint256 idx) external view returns (uint256) {
        assembly {
            mstore(0x00 , arr.slot)
            mstore(0x40, sload(add(keccak256(0, 32), idx)))
            return(0x40, 32)
        }
    }

    /// @dev Function used to push a `val` to `arr`.
    function pushToArr(uint256 val) external {
        assembly {
            /// Reuse array length to avoid double sload.
            let len := sload(arr.slot)
            mstore(0x00 , arr.slot)
            /// Store `val` in array at `len`.
            sstore(add(keccak256(0, 32), len), val)

            /// Increment value of `arr.slot` which is the length of the array by 1.
            sstore(arr.slot, add(len, 1))
        }
    }

    /// @dev Function used to return the current length of `arr`.
    function getArrLength() external view returns (uint256) {
        assembly {
            /// Store the current length of `arr` in memory at fmp.
            mstore(0x40, sload(arr.slot))
            return(0x40, 32)
        }
    }

}

@ItsCuzzo Just fix minor bug on calculating slot of dynamic array.

@ItsCuzzo
Copy link
Author

@atarpara Sorry man, forgot to reply! But I have updated with your fixes. Thanks for the insight. 💪

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment