I'd like to call mapping as arguments of function. I've tried the following code, but it returned the error. Could I call mapping as arguments as a function?

mapping ( uint256 => mapping (bytes32 => bytes32)) public users;

function add( uint256 id, bytes32[] list, mapping ( uint256 => mapping (bytes32 => bytes32) table){
    for( var i=0; i< list.length; i++ ){
        table[id][list[i]] = list[i];

Error: Type is required to live outside storage. function add( uint256 id, bytes32[] list, mapping ( uint256 => mapping (bytes32 => bytes32)) table){ ^------------------------------------------------------^ Error: Internal type is not allowed for public or external functions. function add( uint256 id, bytes32[] kv_list, mapping ( uint256 => mapping (bytes32 => bytes32)) table){

3 Answers 3


The second error you get tells you that external functions cannot have internal types as arguments (i.e. structs and mappings). You can solve that one by specifying internal or private for your function.

For the first error, im not sure if it is a bug or not, but you cannot pass mappings as arguments. What you could do is wrap them in a struct and pass the struct as a parameter.

One final notice is that if you declare your mapping as a state variable then you have access to it directly in your function. So in you example table could just be a state variable...especially since you only use it for storage purposes.


I'm working on a project where I need to access users like you, while being able to add quickly. For this my current (barebones) data struct looks like

address lastAccess = 0x0;

struct User {

address mappingHead = 0x0;
mapping (address => address) public users;
mapping (address => User) public data;

Adding a user looks like

if(users[msg.sender] == 0x0 && msg.sender != mappingHead) {
  users[mappingHead] = msg.sender;
  mappingHead = msg.sender;

  data[mappingHead] = new User(...);

Iteration to find a user looks like

address iterator = lastAccess;
uint256 iteration = 0;

while(iterator != 0x0) {
  if(iteration++ > _maxIterations){
    lastAccess = iterator;
    iterator = 0x0; // Or break
  } else {
    if(data[iterator].x == X){
    iterator = 0x0; // Or break
    } else {
      iterator = users[iterator];

Finding/modifying is O(N) for N _maxIterations in a single call and insertion/reading/accessing is O(1). This implementation does not support deletion, but you could add a "deleted" flag.

Another solution is to keep a bunch of property mappings.

struct User {

mapping (type => address) public prop_1;
mapping (type => address) public prop_2;
mapping (type => address) public prop_n;

mapping (address => User) public list;

Accessing is done by

// Switch on the property x

User u = list[prop_x[_prop_x]];

Adding is done by

prop_1[_prop_1] = msg.sender;
prop_2[_prop_2] = msg.sender;
prop_n[_prop_n] = msg.sender;

The problem with this implementation is that you will overwrite addresses for repeating properties. You could add an indexing on repeating properties, so as to know how many repeated properties are for each type, as above, but modified

// Redefine prop_1 as
// mapping(type => mapping(uint256 => address)) public prop_1;

if(prop_x[_prop_x][prop_x_count[_prop_x]] != 0x0)

prop_x[_prop_x][prop_x_count[_prop_x]] = msg.sender;

This is still subject to attacks on gas limits, but at least you could make partial searches as shown in the original version.

Note: this is untested code.

  • Having a loop without a fixed amount of iterations is not a very good idea in solidity, using anything not O(1) is a very bad idea. If you data grows it can get locked because the block gas limit cannot be enough to process all your data.
    – Ismael
    Commented Sep 17, 2017 at 4:38
  • I don't think there are that many alternatives to searching and accessing in constant time. It's not possible to make a struct->primitive mapping. Maybe making n parallel mappings of property->address and an address->struct would make access easier, but there's still no way of iterating over all keys.
    – OFRBG
    Commented Sep 17, 2017 at 5:49
  • I've use an inverted map for something similar, but if you can't get rid of the O(N) I'd suggest to rework your data structures. The risk with O(N) constructions is that the contract can get blocked unable to process if N is too large.
    – Ismael
    Commented Sep 19, 2017 at 16:20
  • I set N as a constant. If the total array is too large for a single call, the contract saves the last accesses index.
    – OFRBG
    Commented Sep 19, 2017 at 16:44
  • It's not O(1) exactly. I'm brig flexible with notation. It's constant per call, but O(n) for the algo.
    – OFRBG
    Commented Sep 19, 2017 at 16:45

I am not sure why you would like to pass mapping since mapping is available in the scope of the contract.You can use library in solidity to achieve this.

library Helper{

   function add(uint256 _id, 
               bytes32[] memory list, 
               mapping(uint256=>mapping (bytes32 => bytes32)) storage table)
            public {
       for( uint i=0; i< list.length; i++ ){
           table[_id][list[i]] = list[i];

contract A{
    mapping(uint256=>mapping (bytes32 => bytes32)) public table;
    function add(uint256 _id, 
                bytes32[] memory _list) 
                external {
        Helper.add(_id, _list, table);


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.