Solidity – How to Assign a Value to a Member in a Struct

mappingsoliditystruct

I have the following:

pragma solidity ^0.4.0;  
contract MyContract {

struct FooFighter {  
    bool foo;  
    uint fighters;  
}  
mapping(bytes32 => FooFighter) public fooFighters;  

If i want the initial value of uint fighters to be a predefined number instead of 0 for all fooFighters. how would i do that?

Best Answer

There is no way to have a default value for a state variable, especially for a mapping as there is no way for the EVM to know prior to assignment where it will be stored. The next best thing for setting up storage values is the constructor.

So there is no way to assign default struct values in Solidity, however in analysing compiled traces of the following contract, I find that struct variables declared with the memory keyword have their members explicitly initialised to zero values before the actual values are assigned. This is not the case with struct state variables which are assigned directly.

contract abc
{
    struct ABC {
        uint a;
        uint b;
        uint c;
    }

    ABC s;

    // Bytecode assigns value directly to storage slots
    function s_pass() {
        s = ABC({a:1, b:2, c:3});
    }

    // Bytcode initialised `ABC memory m` into `memory` with `0` values before assigning        
    function s_frm_m_pass() {
        ABC memory m = ABC({a:1, b:2, c:3});
        s = m;
    }
}

Struct initialisation bytecode from ABC memory m

JUMPDEST
PUSH1 60
PUSH1 40
MLOAD
SWAP1
DUP2
ADD
PUSH1 40
MSTORE   // setup memory index for ABC.a
DUP1
PUSH1 00 // initialise ABC.a 
DUP2
MSTORE   // memory store ABC.a 
PUSH1 20 // offset to  ABC.b
ADD
PUSH1 00 // initialise ABC.b
DUP2
MSTORE   // memory store ABC.b 
PUSH1 20 // offset to  ABC.c
ADD
PUSH1 00 // initialise ABC.c
DUP2
MSTORE   // memory store ABC.c 
POP
SWAP1
JUMP     // return to function

The fact that the compiler does this for structs in memory indicates there could be an argument to having default values passed through by assigning a memory initialised but unassigned struct. You could then pass the default values to storage in the following way...

    // proposed default value syntax for structs
    struct ABC {
        uint a = 1;
        uint b = 2;
        uint c = 3;
    }

    // Assigning default struct values to storage
    function s_frm_default() {
        ABC memory m;
        s = m;
    }

Of course, if you're up for some post compilation bytecode surgery, you could perhaps edit the PUSH1 00 to whatever values you like before deploying the contract.

However, all this is considerably more work than just s = ABC({a:1, b:2, c:3});

Related Topic