2

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

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
  }
);
  • What is the slot? Is it an index of the mapping variable? – InfinitePrime Mar 1 '18 at 11:12
  • "Slot" is the name given to the position in storage where some value resides. – smarx Mar 1 '18 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 – InfinitePrime Mar 1 '18 at 12:26
  • 1
    Just use key = web3.fromAscii('height') in the above code. – smarx Mar 1 '18 at 19:47
  • I will give it a try! Thanks. But what should be the value for slot? 0? – InfinitePrime Mar 2 '18 at 6:07
3

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)
     }
 });
  • Using this method i am getting the error Cannot read property 'call' of undefined – Sachin Tomar Apr 16 at 16:35
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.

  • 2
    From outside the EVM, you can read anything stored in a smart contract. – smarx Feb 28 '18 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 Feb 28 '18 at 20:45
  • 1
    I'm not sure what the perspective is... the question just says "is there a way." – smarx Feb 28 '18 at 20:46
  • Upvoting your answer as soon as I recovered from "Vox Populi". ;-) – ivicaa Feb 28 '18 at 21:03
  • 1
    @smarx's answer is more inclined towards a possible answer. – InfinitePrime Mar 1 '18 at 12:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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