I don't understand why my struct is not saved in mapping. I've tried diffrerent methods of initializing struct I found all over the web and it didn't work on development network (ganache + truffle). What do I wrong?

Original source of the whole project available here: https://github.com/panwaclaw/bxftoken. Here I leave only part of code with AccountData struct and createAccount() method.

// SPDX-License-Identifier: MIT

pragma solidity ^0.7.5;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/EnumerableSet.sol";

contract AccountStorage is AccessControl {

    using EnumerableSet for EnumerableSet.AddressSet;
    using SafeMath for uint256;

    struct AccountData {
        address sponsor;
        uint256 balance;
        uint256 selfBuy;
        uint rank;
        uint256 turnover;
        uint256 maxChildTurnover;
        uint256 directBonus;
        uint256 indirectBonus;
        uint256 founderBonus;
        uint256 cryptoRewardBonus;
        uint256 reinvestedAmount;
        uint256 withdrawnAmount;
        int256 distributionBonus;

    EnumerableSet.AddressSet private _accounts;
    mapping (address => AccountData) private _accountsData;

    event AccountCreation(address indexed account, address indexed sponsor);

    constructor() {
        address contractAddress = address(this);
        _accountsData[contractAddress].sponsor = address(0);
        _accountsData[contractAddress].balance = 0;
        _accountsData[contractAddress].rank = 0;
        _accountsData[contractAddress].selfBuy = 0;
        _accountsData[contractAddress].turnover = 0;
        _accountsData[contractAddress].maxChildTurnover = 0;
        _accountsData[contractAddress].directBonus = 0;
        _accountsData[contractAddress].indirectBonus = 0;
        _accountsData[contractAddress].founderBonus = 0;
        _accountsData[contractAddress].cryptoRewardBonus = 0;
        _accountsData[contractAddress].distributionBonus = 0;
        _accountsData[contractAddress].reinvestedAmount = 0;
        _accountsData[contractAddress].withdrawnAmount = 0;

    function createAccount(address sponsor) public returns(bool) {
        address account = msg.sender;

        if (sponsor == address(0)) {
            sponsor = address(this);
        if (sponsor != address(this)) {
            require(_accounts.contains(sponsor), "AccountStorage: there's no such sponsor, consider joining with existing sponsor account or contract itself");
        if (!hasAccount(account)) {
            _accountsData[account].sponsor = sponsor;
            _accountsData[account].balance = 0;
            _accountsData[account].rank = 0;
            _accountsData[account].selfBuy = 0;
            _accountsData[account].turnover = 0;
            _accountsData[account].maxChildTurnover = 0;
            _accountsData[account].directBonus = 0;
            _accountsData[account].indirectBonus = 0;
            _accountsData[account].founderBonus = 0;
            _accountsData[account].cryptoRewardBonus = 0;
            _accountsData[account].distributionBonus = 0;
            _accountsData[account].reinvestedAmount = 0;
            _accountsData[account].withdrawnAmount = 0;


            emit AccountCreation(account, sponsor);
            return true;
        return false;

    function hasAccount(address account) public view returns(bool) {
        return _accounts.contains(account);


  • Why does it not work? Is a test failing? I tried in remix and the contract works as expected. My guess is that the problem is not in the contracts but how they are called.
    – Ismael
    Commented Dec 11, 2020 at 19:25
  • @Ismael, The most strange that it passes building tree tests. But I have some other bugs in the contract and I want to debug it with truffle, but it returns very strange results like it doesn't show me anything contained in _accountsData mapping. Is that a debugger bug or?
    – vkozlovsk
    Commented Dec 11, 2020 at 20:18

1 Answer 1


For future generations

Updating a Value in a Struct

Don't do this if you use SafeMath. This will not work, because that updates field only in memory

function increaseBalanceOf(address account, uint256 amount) internal view {

Do only this to change struct field in storage!

function increaseBalanceOf(address account, uint256 amount) internal {
    _accountsData[account].balance = _accountsData[account].balance.add(amount);

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.