Solidity

固定計數數組的問題

  • September 7, 2022

使用映射和不使用映射有什麼區別?

我可以用映射聲明門票變數嗎? Ticket[TOTAL_TICKETS] public tickets;

這是solidity智能合約

pragma solidity >=0.4.22 <0.9.0;

uint256 constant TOTAL_TICKETS = 10;

contract Tickets {
 address public owner = msg.sender;

 struct Ticket {
   uint256 price;
   address owner;
 }
 //mapping(uint256 => Ticket) public tickets;
 Ticket[TOTAL_TICKETS] public tickets;

 constructor() {
   for (uint256 i = 0; i < TOTAL_TICKETS; i++) {
     tickets[i].price = 1e17; // 0.1 ETH
     tickets[i].owner = address(0x0);
   }
 }

 function buyTicket(uint256 _index) external payable {
   require(_index < TOTAL_TICKETS && _index >= 0);
   require(tickets[_index].owner == address(0x0));
   require(msg.value >= tickets[_index].price);
   tickets[_index].owner = msg.sender;
 }
}

取票時,松露控制台出現錯誤

truffle(development)> Tickets.deployed().then(function(instance) { app=instance})
undefined
truffle(development)> app.tickets()
Uncaught Error: Invalid number of parameters for "tickets". Got 0 expected 1!

ticketsstate 變數是一個數組,所以你需要發送你想要的票的索引。就像是:

app.tickets(0)

但無論如何,mapping在這種情況下, a 可能對您更方便。

id我建議您為該Ticket結構創建一個成員。每張工單都應該有自己的 id,以便能夠正確辨識、修改等。

我建議的方法如下所示:

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

type TicketId is uint256;

contract Tickets {

 event TicketSold(TicketId id, address ticketOwner);

 address public owner = msg.sender;

 struct Ticket {
   TicketId id;
   uint256 price;
   address owner;
 }
 mapping(TicketId => Ticket) public tickets;

 modifier onlyOwner {
     require(owner == msg.sender);
     _;
 }

 // Maybe you want to be able to add tickets dynamically
 function addTicket(TicketId id, uint256 price) public onlyOwner {
     tickets[id] = Ticket(id, price, address(0x0));
 }

 // Maybe you want to be able to remove tickets?
 function removeTicket(TicketId id) public onlyOwner {
     delete tickets[id];
 }

 function buyTicket(TicketId id) external payable {
   require(tickets[id].owner == address(0x0), "Ticket already bought.");
   require(msg.value >= tickets[id].price, "Not enough balance to buy the ticket");
   tickets[id].owner = msg.sender;
   emit TicketSold(id, msg.sender);
 }
}

也許不再需要 aTOTAL_TICKETS了。但是您可以更改邏輯以使用狀態變數來計算總票數,並確保不要添加更多。

使用 amapping對於一般查找更有效(與遍歷數組相比,儘管通過索引訪問數組元素與映射一樣有效)。

Amapping從其中刪除元素更有效。通過數組上的索引刪除元素是有效的,但通常,您希望調整數組的大小,以便數組中沒有空白空間,並且與從映射中刪除元素時的常量相比,其複雜性是線性的.

我在實現中使用了自定義類型,以明確映射的關鍵是票證的 id,以使其更具可讀性和類型安全性。

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