Search code examples
structethereumsoliditytruffle

why struct returns duplicate values as index in solidity?


im struggling with struct in solidity, im learning about it. this is a sample todo example contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Todos {
    
    struct Todo {
        string text;
        bool completed;
    }

    // An array of 'Todo' structs
    Todo[] public todos;

    function create(string calldata _text) public {
        // 3 ways to initialize a struct
        // - calling it like a function
        todos.push(Todo(_text, false));

        // key value mapping
        todos.push(Todo({text: _text, completed: false}));

        // initialize an empty struct and then update it
        Todo memory todo;
        todo.text = _text;
        // todo.completed initialized to false

        todos.push(todo);
    }

    // Solidity automatically created a getter for 'todos' so
    // you don't actually need this function.
    function get(uint _index) public view returns (string memory text, bool completed) {
        Todo storage todo = todos[_index];
        return (todo.text, todo.completed);
    }

    // update text
    function updateText(uint _index, string calldata _text) public {
        Todo storage todo = todos[_index];
        todo.text = _text;
    }

    // update completed
    function toggleCompleted(uint _index) public {
        Todo storage todo = todos[_index];
        todo.completed = !todo.completed;
    }
}

the output of the get function in truffle is: Result { '0': 'task 1', '1': true, text: 'task 1', completed: true }

so as you can see, i expected just keys and values like this Result {text: 'task 1', completed: true }

can you explain me why? is that normal we have index alongside keys and values?


Solution

  • The duplicate values are not returned by the contract itself. When you inspect the encoded binary returned by the contract, you'll see that each of the values (text and completed) is returned just once.

    However, these values are duplicated in the Truffle JS framework. The framework uses the contract's ABI JSON to decode the returned binary into other types (in this case string and bool).

    When the framework doesn't know the parameter names (e.g. they're not specified in your source code / ABI JSON), it only decodes the returned values into number-indexed result:

    Result { '0': 'task 1', '1': true }
    

    But since your contract source code (and for that reason, also the ABI JSON generated during contract compilation) contains the parameter names, Truffle framework also adds the named properties into the Result object while still keeping the number-indexed values to enable accessing the values by indexes as well.

    Result { '0': 'task 1', '1': true, text: 'task 1', completed: true }