1

I'm trying to save in storage some values in a nested mapping. Found some results of a similar problem, tried the solutions, but no success, also read the documentation of https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html but still did not figured out what is wrong.

This is the complete code:

pragma solidity ^0.8.0;
import "hardhat/console.sol";

contract Spiral {
    struct Chunk {
        int256 x;
        int256 y;
    }

    // 0: right, 1: down, 2: left, 3: up
    bytes1 directionB = 0x00;
    uint256 currentTravel = 1;
    uint256 stepCounter = currentTravel;

    Chunk[] public chunks;
    mapping(int256 => mapping(int256 => uint256)) public XYtoChunkId;

    constructor() {
        // Start the spiral at the origin (0, 0)
        chunks.push(Chunk(0, 0));
        XYtoChunkId[0][0] = 0;
    }

    function addChunk() public {
        int256 x;
        int256 y;
        uint256 chunkId;
        assembly {
            let r := sload(chunks.slot)
            mstore(0x00, chunks.slot)
            let chunks_pt := keccak256(0x00, 0x20)
            let p := add(mul(sub(r, 1), 2), chunks_pt)
            x := sload(p)
            y := sload(add(p, 1))

            let new_r := add(r, 1)
            let new_p := add(mul(r, 2), chunks_pt)

            sstore(chunks.slot, new_r)
            switch sload(directionB.slot)
            case 0x00 {
                sstore(new_p, add(x, 1))
                sstore(add(new_p, 1), y)
            }
            case 0x01 {
                sstore(new_p, x)
                sstore(add(new_p, 1), sub(y, 1))
            }
            case 0x02 {
                sstore(new_p, sub(x, 1))
                sstore(add(new_p, 1), y)
            }
            case 0x03 {
                sstore(new_p, x)
                sstore(add(new_p, 1), add(y, 1))
            }

            sstore(stepCounter.slot, sub(sload(stepCounter.slot), 1))
            if eq(sload(stepCounter.slot), 0x00) {
                sstore(
                    directionB.slot,
                    addmod(sload(directionB.slot), 0x01, 0x04)
                )
                sstore(stepCounter.slot, sload(currentTravel.slot))
                switch sload(directionB.slot)
                case 0x01 {
                    sstore(
                        currentTravel.slot,
                        add(sload(currentTravel.slot), 1)
                    )
                }
                case 0x03 {
                    sstore(
                        currentTravel.slot,
                        add(sload(currentTravel.slot), 1)
                    )
                }
            }

            mstore(0x00, x)
            mstore(0x20, XYtoChunkId.slot)
            let xHash := keccak256(0x00, 0x40)
            mstore(0x00, y)
            mstore(0x20, xHash)
            let chunkIdSlot := keccak256(0x00, 0x40)

            chunkId := sload(chunkIdSlot)
            sstore(chunkIdSlot, sub(r, 2))
        }
        console.log(chunkId);
        // XYtoChunkId[x][y] = chunks.length - 2;
    }
}

I am trying to add the chunkId which is r - 2 in the mapping storage mapping(int256 => mapping(int256 => uint256)) public XYtoChunkId; using this part of the code

mstore(0x00, x)
mstore(0x20, XYtoChunkId.slot)
let xHash := keccak256(0x00, 0x40)
mstore(0x00, y)
mstore(0x20, xHash)
let chunkIdSlot := keccak256(0x00, 0x40)

chunkId := sload(chunkIdSlot)
sstore(chunkIdSlot, sub(r, 2))

Adapted this part from a similar question on the forum, no success, also tried to play around and switching order of x and y when keccak256, was getting some id's back , but not the correct ones. Thanks.

5
  • it is not clear what you mean by "no success", are you implying that sstore instruction doesn't save the value at specified location? that's not true
    – Nulik
    Dec 21, 2022 at 19:03
  • sstore gets the location and value from the stack, where are you pushing it?
    – Nulik
    Dec 21, 2022 at 19:06
  • by no success i mean when i console log chunkId i get 0 , instead of real values. sstore saves to storage if i'm not wrong, sload gets the value from the storage. The last part of the code that i mentioned should produce the same result as XYtoChunkId[x][y] = chunks.length - 2; but it does not. After executing the function and calling XYtoChunkId[x][y] I get 0 back instead of a real Id
    – Peter
    Dec 21, 2022 at 20:25
  • run a trace and verify that the stack contains correct location and value just before SSTORE opcode is executed. if you store some value but get 0 when reading it, then it means you are giving it wrong location either at write or read operation
    – Nulik
    Dec 22, 2022 at 1:44
  • please stop, you're not helping, of course it's the wrong location i mentioned that i'm using the formula provided in the docs to calculate the storage location of a nested mapping, but value it's not getting inserted there
    – Peter
    Dec 22, 2022 at 4:22

1 Answer 1

0

It is zero because in the constructor you stored zero XYtoChunkId[0][0] = 0.

chunkId := sload(chunkIdSlot)
sstore(chunkIdSlot, sub(r, 2))

If you want to get the updated value, you have to read the slot after the modification

sstore(chunkIdSlot, sub(r, 2))   // <--- modification
chunkId := sload(chunkIdSlot).   // <--- read

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.