6

Is there a way to access a mapping variable such as:

mapping(bytes => bool) myMappingVar;

which is NOT:

  • Declared public explicitly
  • without using indexed based id
  • Also no corresponding public getter method is set

For example, from web3:

contract.instance.methods.myMappingVar('somevalue').call();

3 Answers 3

8

Not conveniently, but you can access any value in a smart contract's storage via web3.eth.getStorageAt. See https://solidity.readthedocs.io/en/develop/miscellaneous.html#layout-of-state-variables-in-storage for the details of how storage is laid out.

If your mapping is the first state variable in the contract, so it's at slot 0, this code will retrieve the value for the key 0x123456.

var slot = "0".repeat(64);  // hex uint256 representation of 0
var key = "0x123456";  // hex representation of the key

web3.eth.getStorageAt(
  contractAddress,  // address of the contract to read from
  web3.sha3(key+slot, { encoding: 'hex' }),  // keccak256(k . p)
  function (err, result) {
    console.log(result);  // 00...0 for false, 00...1 for true, both 32 bytes wide
  }
);
7
  • What is the slot? Is it an index of the mapping variable? Commented Mar 1, 2018 at 11:12
  • "Slot" is the name given to the position in storage where some value resides.
    – user19510
    Commented Mar 1, 2018 at 11:21
  • I dont understand. How do I get a slot for a mapping with key 'height' such as: ``` ['age': true, 'name': true, 'height': true] ``` also see, my question states without using or assuming indexes to be a known value Commented Mar 1, 2018 at 12:26
  • 2
    Just use key = web3.fromAscii('height') in the above code.
    – user19510
    Commented Mar 1, 2018 at 19:47
  • I will give it a try! Thanks. But what should be the value for slot? 0? Commented Mar 2, 2018 at 6:07
9

You can access a public mapping variable like a regular public variable with the exception that you need to provide the index value for the mapping.

I have done the following example, and it worked for me

In my contract written using Solidity


address public owner; 
mapping(uint8 => address) public incomingQueue;
mapping(address => string) public assignedName;

After I obtain the contract address:

const contract = web3.eth.contract(abiArray).at(contract_address);

I can access these variable using the following web3 javascript code:


contract.owner.call(function(err, result){
     if(!err)
         alert(result)
 });
contract.incomingQueue.call(0, function(err, result){
     if(!err){
        alert(result)
     }
 });
contract.assignedName.call(web3.eth.accounts[0], function(err, result){
     if(!err){
        alert(result)
     }
 });
2
  • Using this method i am getting the error Cannot read property 'call' of undefined Commented Apr 16, 2019 at 16:35
  • 1
    This is for older versions of web3. On web3 version 1.2 you should call it as contract.methods.incomingQueue(0).call();
    – Sr.PEDRO
    Commented Sep 2, 2019 at 19:09
1

From the perspective of information hiding, you can not access fields from outside. You need a getter function. When you specify the public modifier on the mapping, Solidity generates a getter function for you.

However, as smarx is explaining in his answer, this is not protecting your data from being read directly from the storage.

5
  • 3
    From outside the EVM, you can read anything stored in a smart contract.
    – user19510
    Commented Feb 28, 2018 at 20:40
  • Oh.. you're assuming the question is asked from the perspective of securing the data? Then of course "You can not access fields from outside" is wrong.
    – ivicaa
    Commented Feb 28, 2018 at 20:45
  • 2
    I'm not sure what the perspective is... the question just says "is there a way."
    – user19510
    Commented Feb 28, 2018 at 20:46
  • Upvoting your answer as soon as I recovered from "Vox Populi". ;-)
    – ivicaa
    Commented Feb 28, 2018 at 21:03
  • 1
    @smarx's answer is more inclined towards a possible answer. Commented Mar 1, 2018 at 12:28

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.