1

I am developing a todo list dapp. Currently I have the createTask toggleCompleted and now I need the deleteTask to be done.

The smart contract.

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract TodoList {

  uint public taskCount = 0;

  mapping(uint => Task) public tasks;

  struct Task {
    uint id;
    string content;
    bool completed;
  }

  event TaskCreated(
    uint id,
    string content,
    bool completed
  );

  event TaskDeleted(
    uint id,
    string content,
    bool completed
  );

  event TaskCompleted(
    uint id,
    bool completed
  );

  constructor() public {
    createTask("Check out dappuniversity.com");
  }

  function createTask(string memory _content) public {
    taskCount ++;
    tasks[taskCount] = Task(taskCount, _content, false);
    emit TaskCreated(taskCount, _content, false);
  }

  function toggleCompleted(uint _id) public {
    Task memory _task = tasks[_id];
    _task.completed = !_task.completed;
    tasks[_id] = _task;
    emit TaskCompleted(_id, _task.completed);
  }

  function deleteTask(uint _id) public {
    Task memory _task = tasks[_id];
    delete tasks[_id];
    emit TaskDeleted(_id, _task.content, _task.completed);
  }

}

When I call the deteleTask MetaMask says that there Transaction Error. Exception thrown in contract code.. I have noticed that for createTask there is a gas consumption of 0.00222456ETH and for deleting 0.12771752ETH the difference is significant, and it does not depend on the function body because I have make them equal. On what does it depend and how do I reduce the gas for this transaction? Do I have to add something to the truffle-config.js?

truffle-config.js

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 7545,
      network_id: "*", // Match any network id
    }
  },
  solc: {
    optimizer: {
      enabled: true,
      runs: 200
    }
  }
}

Ganache settings.

GAS PRICE
20000000000

GAS LIMIT
6721975

UPDATE I have switched to the harmony one testnet, the same issues persists. Empty deleteTask function requires to pay 0.76 harmony and metamask says the following

This transaction is expected to fail. Trying to execute it is expected to be expensive but fail, and is not recommended.
8
  • How are you going to get the tasks list in Dapp?
    – Mad Jackal
    Dec 14, 2021 at 7:10
  • @MadJackal using react.js Dec 14, 2021 at 7:35
  • 1. There is no view method in your contract for getting a list of tasks. 2. You cannot get a mapping list in Solidity - only array.
    – Mad Jackal
    Dec 14, 2021 at 7:42
  • @MadJackal I need the delete method to work, everything else works just fine. The problem is within the gas fee. Dec 14, 2021 at 7:46
  • Try not to use the local _task variable, but do an emit before delete. Or try replacing delete tasks[_id]; with tasks[_id].id=0;.
    – Mad Jackal
    Dec 14, 2021 at 9:01

2 Answers 2

2

The cause for the gas consumption might be connected to the error message. Before Solidity 0.8.0 if a contract fails because of an assert it uses an invalid opcode and therefore it uses up all remaining gas. So if you set a high gas limit it will eat up all the gas. If a contract fails because of a revert no additional gas will be used up. More info on this can be found here: https://docs.soliditylang.org/en/latest/control-structures.html?highlight=assert#panic-via-assert-and-error-via-require.

Edit: For further investigation could you post the following information:

  • the output of solc --version
  • The methods and parameters that you call in your transactions (e.g. how do you create the task struct)

Edit 2: I was testing your contract on https://remix.ethereum.org/ and everything seems to work. Do you only see errors on bsc related networks or also on remix?

0

Deleting a mapping basically sets all elements of the struct to the default value. That could have been the issue.

I made some small changes, by basically adding a bool that indicates if a task still exists.

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract TodoList {

  uint public taskCount = 0;

  mapping(uint => Task) public tasks;

  struct Task {
    uint id;
    string content;
    bool completed;
    bool exists;
  }

  event TaskCreated(
    uint id,
    string content,
    bool completed
  );

  event TaskDeleted(
    uint id,
    string content,
    bool completed
  );

  event TaskCompleted(
    uint id,
    bool completed
  );

  constructor() {
    createTask("Check out dappuniversity.com");
  }

  function createTask(string memory _content) public {
    taskCount ++;
    tasks[taskCount] = Task(taskCount, _content, false, true);
    emit TaskCreated(taskCount, _content, false);
  }

  function toggleCompleted(uint _id) public {
    require(tasks[_id].exists, "Task does not exist");
    tasks[_id].completed = !tasks[_id].completed;
    emit TaskCompleted(_id, tasks[_id].completed);
  }

  function deleteTask(uint _id) public {
    require(tasks[_id].exists, "Task does not exist");
    tasks[_id].exists = false;
    emit TaskDeleted(_id, tasks[_id].content,tasks[_id].completed);
  }
}

Does this solve the gas topic?

If not, the source of the problem might be outside of the contract: How do you initiate the transaction, in JS? Which function is calling the web3 wrappers and which one is calculating the gas (do you leave it up to MetaMask?)

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.