Storage

Solidity 狀態變數在函式內部重置為預設值

  • June 28, 2018

對於這個項目,我正在使用 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為簡單起見,我刪除了該功能。

希望這可以幫助

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