Для этого проекта я пишу умные контракты для Ethereum, используя Solidity.
В следующем коде переменная numCertificates
должна изначально иметь значение 1. Тем не менее, newCertificateId равен 0 при назначении. Согласно отладчику (я использую remix.ethereum.org), по какой-то причине numCertificates становится равным 0, как только достигается строка, которой назначен newCertificateId.
Я много играл с ремиксом, и, согласно ему, 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
(который фактически является идентификатором нового сертификата).
Следовательно, изменения в newCertficate
фактически являются изменениями, внесенными в certificates[numCertificates]
напрямую.
Обратите внимание, что я удалил функцию produceCertificate
для простоты.
Надеюсь это поможет
Jaime
Ник Сзер
Jaime
Ник Сзер
Ник Сзер