Solidity
將建構子結果推送到合約成員數組
我正在嘗試在 Solidity 中執行以下操作:
BetCampaign memory newCampaign = BetCampaign(id, new Bet[](0), betEndTime, false); betCampaigns.push(newCampaign);
使用以下成員聲明:
BetCampaign[] public betCampaigns;
但我不斷收到以下錯誤:
UnimplementedFeatureError: Copying of type struct Betting.Bet memory[] memory to storage not yet supported.
我嘗試將 newCampaign 聲明更改為“儲存”而不是“記憶體”,但這也會導致錯誤。我該如何解決這個問題?
這是我正在使用的整個文件:
pragma solidity ^0.5.0; contract Betting { struct Bet { uint betId; uint campaignId; address sender; uint stake; bool betValue; } struct BetCampaign { uint campaignId; Bet[] bets; mapping(address => bool) userReserved; // mapping ignored in constructor (?) uint betEndTime; bool isEnded; } event BetCampaignCreated(uint campaignId, uint betEndTime); event BetAdded(uint betId, uint campaignId, address indexed user, uint256 betAmount, bool betsTrue); BetCampaign[] public betCampaigns; mapping(uint => bool) betCampaignReserved; mapping(uint => bool) betReserved; uint nonce; constructor() public { nonce = 0; } modifier isLater(uint time) { require(time > now, "The end time must be in the future"); _; } modifier campaignExistsM(uint campaignId) { require(campaignExists(campaignId), "The campaign does not exist"); _; } modifier userNotInCampaign(uint campaignId, address user) { require(!betPlaced(campaignId, user)); _; } modifier userInCampaign(uint campaignId, address user) { require(betPlaced(campaignId, user)); _; } modifier isSelf(address target) { require(msg.sender == target); _; } modifier enoughMoney(uint amount) { require(msg.value >= amount); _; } function generateId() internal returns (uint) { nonce += 1; return uint(keccak256(abi.encodePacked(nonce))); } function campaignExists(uint campaignId) internal view returns (bool) { return betCampaignReserved[campaignId]; } function createCampaign(uint betEndTime) public isLater(betEndTime) { while (true) { uint id = generateId(); if (!campaignExists(id)) { BetCampaign memory newCampaign = BetCampaign(id, new Bet[](0), betEndTime, false); betCampaigns.push(newCampaign); betCampaignReserved[id] = true; emit BetCampaignCreated(id, betEndTime); break; } } } function getCampaignInformation(uint campaignId) public view campaignExistsM(campaignId) returns (uint, uint, bool) { BetCampaign memory campaign; for (uint i = 0; i < betCampaigns.length; i++) { if (betCampaigns[i].campaignId == campaignId) { campaign = betCampaigns[i]; break; } } return (campaign.campaignId, campaign.betEndTime, campaign.isEnded); } function getCampaign(uint campaignId) internal view campaignExistsM(campaignId) returns (BetCampaign storage) { uint index = 0; for (uint i = 0; i < betCampaigns.length; i++) { if (betCampaigns[i].campaignId == campaignId) { index = i; break; } } BetCampaign storage campaign = betCampaigns[index]; return campaign; } function betExists(uint betId) internal view returns (bool) { return betReserved[betId]; } function addBet(uint campaignId, address sender, uint stake, bool betValue) payable public isSelf(sender) enoughMoney(stake) campaignExistsM(campaignId) userNotInCampaign(campaignId, sender) { while (true) { uint id = generateId(); if (!betExists(id)) { BetCampaign storage campaign = getCampaign(campaignId); campaign.bets.push(Bet(id, campaignId, sender, stake, betValue)); campaign.userReserved[sender] = true; emit BetAdded(id, campaignId, sender, stake, betValue); break; } } } function getBet(uint campaignId, address sender) public view campaignExistsM(campaignId) userInCampaign(campaignId, sender) returns (uint, uint, address, uint, bool) { Bet memory bet; BetCampaign memory campaign = getCampaign(campaignId); for (uint i = 0; i < campaign.bets.length; i++) { if (campaign.bets[i].sender == sender) { bet = campaign.bets[i]; } } return (bet.betId, bet.campaignId, bet.sender, bet.stake, bet.betValue); } function betPlaced(uint campaignId, address sender) public view campaignExistsM(campaignId) returns (bool) { BetCampaign storage campaign = getCampaign(campaignId); return campaign.userReserved[sender]; } }
的數組
BetCampaign
並不理想,這會很尷尬。struct BetCampaign { uint campaignId; Bet[] bets; mapping(address => bool) userReserved; // mapping ignored in constructor (?) uint betEndTime; bool isEnded; } BetCampaign[] public betCampaigns;
您遇到了麻煩,因為您無法將在記憶體中建構的實例複製到儲存中,並且您不想建構儲存單例只是為了將其複制(推送)到數組中。這將在一次移動中使用兩次昂貴的儲存空間。
這在另一方面是次優的。包括類似的
id
,struct
這意味著在列表中釣魚以找到匹配的。像這樣重構來解決這兩個問題。
struct BetCampaign { // uint campaignId; Bet[] bets; mapping(address => bool) userReserved; // mapping ignored in constructor (?) uint betEndTime; bool isEnded; } // BetCampaign[] public betCampaigns; mapping(uint => BetCampaign) public betCampaigns; // id => struct
現在,您可以在單個操作中按 ID 查找匹配的廣告系列。您還解決了令人討厭的記憶體/儲存問題,因為您將始終寫入
betCampaigns[]
映射中的索引。檢查此是否有重要警告:https ://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089
檢查此以獲取有用的模式並詳細說明所描述的解決方案:https ://medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a
希望能幫助到你。