Solidity

Solidity:函式消耗過多的氣體

  • January 3, 2022

我正在開發一個待辦事項列表 dapp。目前我有createTask toggleCompleted,現在我需要deleteTask完成。

智能合約。

// 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);
 }

}

當我打電話給deteleTaskMetaMask 時說那裡Transaction Error. Exception thrown in contract code.。我注意到,對於和刪除的createTask氣體消耗量差異很大,並且它不依賴於函式體,因為我已經使它們相等。它取決於什麼以及如何減少此交易的氣體?我必須添加一些東西嗎?0.00222456ETH``0.12771752ETH``truffle-config.js

松露-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
   }
 }
}

甘納許設置。

GAS PRICE
20000000000

GAS LIMIT
6721975

更新我已經切換到和諧一測試網,同樣的問題仍然存在。空 deleteTask 函式需要支付 0.76 和諧和 metamask 說如下

This transaction is expected to fail. Trying to execute it is expected to be expensive but fail, and is not recommended.

氣體消耗的原因可能與錯誤消息有關。在 Solidity 0.8.0 之前,如果合約由於assert使用無效的操作碼而失敗,因此它會耗盡所有剩餘的 gas。因此,如果您設置了較高的 gas 限制,它將耗盡所有的 gas。如果合約因為revert沒有額外的 gas 用完而失敗。可以在此處找到更多資訊:https ://docs.soliditylang.org/en/latest/control-structures.html?highlight=assert#panic-via-assert-and-error-via-require 。

編輯:為了進一步調查,您可以發布以下資訊:

  • 的輸出solc --version
  • 您在事務中呼叫的方法和參數(例如,您如何創建任務結構)

編輯 2:我在https://remix.ethereum.org/上測試你的合約,一切似乎都正常。您是否只在 bsc 相關網路或混音上看到錯誤?

刪除映射基本上會將結構的所有元素設置為預設值。那可能是問題所在。

我做了一些小的改動,基本上添加了一個布爾值來指示任務是否仍然存在。

// 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);
 }
}

這是否解決了天然氣問題?

如果不是,問題的根源可能在合約之外:你如何在 JS 中發起交易?哪個函式在呼叫 web3 包裝器,哪個函式在計算氣體(你把它留給 MetaMask 嗎?)

引用自:https://ethereum.stackexchange.com/questions/115533