For testing, I deployed my contract locally on anvil and am trying to interact with it using cast. To verify the correct working of my contract, I would like to check the values in a mapping after updating them. I think I should be using cast index. My current approach:

  • Start anvil by running anvil. Copy the address and private key of the first wallet into export WALLET_1=0x... & export PRIVATE_KEY_1=0x...
  • Deploy: forge script script/Contract.s.sol:ContractScript --fork-url http://localhost:8545 --private-key $PRIVATE_KEY_1 --broadcast. The resulting contract address goes into export CONTRACT_ADDRESS=0x...
  • Publish a message: cast send $CONTRACT_ADDRESS "addKVpair(bytes32, uint)" 0x1 10 --private-key $PRIVATE_KEY_1 --from $WALLET_1
  • Read mapping at key: cast index bytes32 0x1 0. I assumed that the slot number should be 0 because it's the first declared variable.
  • Result: 0x14184318b4299964f96ff8dfa1db97fc8a28d66e8c4434c0773f43adc6062152 which is not 10.
  • If I try to read the value of a non-exiting key, I get a similar, non-zero, value.

What is going wrong? What would be the best approach?

For reference, my contract is:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.0 <0.9.0;

contract Contract {
    mapping (bytes32 => uint) public mapTest;

    function addKVpair(bytes32 key, uint value) public {
        mapTest[key] = value;

1 Answer 1


The storage location of mappings and dynamic arrays in a contract can be calculated by
cast index [key-type] [key-value] [slot].

If you want to know what is going on this particular slot, use
cast storage [contract address] [mapping key].

Here are details on how the slot is calculated.

In this case, do

>> cast index bytes32 0x1 0
>> cast storage $CONTRACT_ADDRESS 0xabc..

which is 10.

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.