Storage
Solidity 狀態變數在函式內部重置為預設值
對於這個項目,我正在使用 Solidity 為乙太坊編寫智能合約。
在以下程式碼中,變數
numCertificates
最初應為 1。儘管如此,newCertificateId 在分配時為 0。根據調試器(我正在使用 remix.ethereum.org),由於某種原因,一旦到達分配 newCertificateId 的行,numCertificates 就會變為 0。我玩過很多混音,根據它,numCertificates 是 1,直到達到上述行。另外,我認為如果我在另一個函式中修改 numCertificates,該變數將保持與以前相同。
我試圖弄清楚這一點的嘗試使我相信,當我訪問 numCertificates 時,我訪問的不是公共狀態變數,而是其他東西。
為什麼這段程式碼會出現這個問題,如何解決?
pragma solidity ^0.4.21; contract MyToken { struct Certificate { uint64 certificateId; uint64 meterId; uint32 timestamp; uint48 value; address[] owners; mapping (address => uint48) ownershipSplit; bool burned; } mapping (uint64 => Certificate) public certificates; uint64 numCertificates = 1; function MyToken() public { // ... irrelevant stuff } function produceCertificate( uint64 meterId, uint32 timestamp, uint48 value, address owner ) public { // Create the certificate in memory numCertificates;// only for debbuging Certificate storage newCertificate = constructCertificate(meterId, timestamp, carbonMitigationValue, owner); uint64 newCertificateId = numCertificates; newCertificate.certificateId = newCertificateId; // Save the certificate certificates[newCertificateId] = newCertificate; numCertificates++; } function constructCertificate( uint64 meterId, uint32 timestamp, uint48 value, address owner ) internal returns (Certificate storage newCertificate) { newCertificate.meterId = meterId; newCertificate.timestamp = timestamp; newCertificate.value = value; newCertificate.owners.push(owner); newCertificate.ownershipSplit[owner] = value; newCertificate.burned = false; // by default new certificates are fresh return newCertificate; } }
問題似乎是您正在使用的儲存指針。我不明白你在使用時指的是什麼:
Certificate storage newCertificate = constructCertificate(meterId, timestamp, Value, owner);
我將您的程式碼更改為:
pragma solidity ^0.4.21; contract MyToken { struct Certificate { uint64 certificateId; uint64 meterId; uint32 timestamp; uint48 value; address[] owners; mapping (address => uint48) ownershipSplit; bool burned; } mapping (uint64 => Certificate) public certificates; uint64 public numCertificates = 1; function MyToken() public { // ... irrelevant stuff } function produceCertificate( uint64 meterId, uint32 timestamp, uint48 value, address owner ) public { // Create the certificate in memory //numCertificates;// only for debbuging Certificate storage newCertificate = certificates[numCertificates]; newCertificate.meterId = meterId; newCertificate.timestamp = timestamp; newCertificate.value = value; newCertificate.owners.push(owner); newCertificate.ownershipSplit[owner] = value; newCertificate.burned = false; // by default new certificates are fresh newCertificate.certificateId = numCertificates; numCertificates= numCertificates +1; } }
在此程式碼中,您定義了一個指向結構的指針,該結構是映射,位於由
numCertificates
(實際上是新證書的 Id)指示的位置。因此,對 to 的更改
newCertficate
實際上是對certificates[numCertificates]
直接進行的更改。請注意,
produceCertificate
為簡單起見,我刪除了該功能。希望這可以幫助