Solidity

類型地址不能隱式轉換為預期類型 uint256

  • July 23, 2022
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;

library CryptoSuite {
   function splitSignature(bytes memory sig)
       internal
       pure
       returns (
           uint8 v,
           bytes32 r,
           bytes32 s
       )
   {
       require(sig.length == 65);

       assembly {
           //first 32bytes
           r := mload(add(sig, 32))

           //next 32bytes
           s := mload(add(sig, 64))

           //first 32bytes
           r := byte(0, mload(add(sig, 96)))
       }

       return (v, r, s);
   }

   function recoverSigner(bytes32 message, bytes memory sig)
       internal
       pure
       returns (address)
   {
       (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);

       return ecrecover(message, v, r, s);
   }
}

contract ColdChain {
   enum Mode {
       ISSUER,
       PROVER,
       VERIFIER
   }
   struct Entity {
       address id;
       Mode mode;
       uint[] certificateIds;
   }

   enum Status {
       MANUFACTURED,
       DELIVERING_INTERNATIONAL,
       STORED,
       DELIVERING_LOCAL,
       DELIVERED
   }

   struct Certificate {
       uint id;
       Entity issuer;
       Entity prover;
       bytes signature;
       Status status;
   }

   struct VaccineBatch {
       uint id;
       string brand;
       address manufacturer;
       uint[] certificateIds;
   }

   uint public constant MAX_CERTITICATIONS = 2;

   uint[] public certificateIds;
   uint[] public vaccineBatchIds;

   mapping(uint => VaccineBatch) public vaccineBatches;
   mapping(uint => Certificate) public certificates;
   mapping(uint => Entity) public entities;

   event AddEntity(address entityId, string entityMode);
   event AddVaccineBatch(uint vaccineBatchId, address indexed manufacturer);
   event IssueCertificate(
       address indexed issuer,
       address indexed prover,
       uint certificateId
   );

   function addEntity(address _id, string memory _mode) public {
       Mode mode = unmarshalMode(_mode);
       uint[] memory _certificateIds = new uint[](MAX_CERTITICATIONS);
       Entity memory entity = Entity(_id, mode, _certificateIds);
       entities[_id] = entity;

       emit AddEntity(entity.id, _mode);
   }

   function unmarshalMode(string memory _mode)
       private
       pure
       returns (Mode mode)
   {
       bytes32 encodedMode = keccak256(abi.encodePacked(_mode));
       bytes32 encodedMode0 = keccak256(abi.encodePacked("ISSUER"));
       bytes32 encodedMode1 = keccak256(abi.encodePacked("PROVER"));
       bytes32 encodedMode2 = keccak256(abi.encodePacked("VERIFIER"));

       if (encodedMode == encodedMode0) {
           return Mode.ISSUER;
       } else if (encodedMode == encodedMode1) {
           return Mode.PROVER;
       } else if (encodedMode == encodedMode2) {
           return Mode.VERIFIER;
       }

       revert("recieved invalid entity mode");
   }

   function addVaccineBatch(string memory brand, address manufacturer)
       public
       returns (uint)
   {
       uint[] memory _certificateIds = new uint[](MAX_CERTITICATIONS);
       uint id = vaccineBatchIds.length;
       VaccineBatch memory batch = VaccineBatch(
           id,
           brand,
           manufacturer,
           _certificateIds
       );

       vaccineBatches[id] = batch;
       vaccineBatchIds.push(id);

       emit AddVaccineBatch(batch.id, batch.manufacturer);
       return id;
   }

   function issueCertificate(
       address _issuer,
       address _prover,
       string memory _status,
       uint vaccineBatchId,
       bytes memory signature
   ) public returns (uint) {
       Entity memory issuer = entities[_issuer];
       require(issuer.mode == Mode.ISSUER);

       Entity memory prover = entities[_prover];
       require(prover.mode == Mode.PROVER);

       Status status = unmarshalStatus(_status);

       uint id = certificateIds.length;
       Certificate memory certificate = Certificate(
           id,
           issuer,
           prover,
           signature,
           status
       );

       certificateIds.push(certificateIds.length);
       certificates[certificateIds.length - 1] = certificate;

       emit IssueCertificate(_issuer, _prover, certificateIds.length - 1);

       return certificateIds.length - 1;
   }

   function unmarshalStatus(string memory _status)
       private
       pure
       returns (Status status)
   {
       bytes32 encodedStatus = keccak256(abi.encodePacked(_status));
       bytes32 encodedStatus0 = keccak256(abi.encodePacked("MANUFACTURED"));
       bytes32 encodedStatus1 = keccak256(
           abi.encodePacked("DELIVERING_INTERNATIONAL")
       );
       bytes32 encodedStatus2 = keccak256(abi.encodePacked("STORED"));
       bytes32 encodedStatus3 = keccak256(
           abi.encodePacked("DELIVERING_LOCAL")
       );
       bytes32 encodedStatus4 = keccak256(abi.encodePacked("DELIVERED"));

       if (encodedStatus == encodedStatus0) {
           return Status.MANUFACTURED;
       } else if (encodedStatus == encodedStatus1) {
           return Status.DELIVERING_INTERNATIONAL;
       } else if (encodedStatus == encodedStatus2) {
           return Status.STORED;
       } else if (encodedStatus == encodedStatus3) {
           return Status.DELIVERING_LOCAL;
       } else if (encodedStatus == encodedStatus4) {
           return Status.DELIVERED;
       }

       revert("recieved invalid Certificate Status");
   }

   function isMatchingSignature(
       bytes32 message,
       uint id,
       address issuer
   ) public view returns (bool) {
       Certificate memory cert = certificates[id];
       require(cert.issuer.id == issuer);

       address recoveredSigner = CryptoSuite.recoverSigner(
           message,
           cert.signature
       );

       return recoveredSigner == cert.issuer.id;
   }
}

在此功能上遇到問題… :(

Type address is not implicitly convertible to expected type uint256.

問題在於這些關鍵字**_issuer_prover** 誰能幫幫我???

您的問題是指查詢entities映射。詳細地說,當您以這種方式聲明映射時:

mapping(uint => Entity) public entities;

uint 是鍵,Entity 是值。現在,要查詢此映射,您必須放置一個 uint 值以檢索與其相關的實體值。例子:

Entities memory _entity = entities[{uint}]; {uint} <- refers to key datatype!

你在智能合約中的所有問題都與這種誤解有關。我以這種方式調整了你的智能合約:

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;

library CryptoSuite {
   function splitSignature(bytes memory sig)
       internal
       pure
       returns (
           uint8 v,
           bytes32 r,
           bytes32 s
       )
   {
       require(sig.length == 65);

       assembly {
           //first 32bytes
           r := mload(add(sig, 32))

           //next 32bytes
           s := mload(add(sig, 64))

           //first 32bytes
           r := byte(0, mload(add(sig, 96)))
       }

       return (v, r, s);
   }

   function recoverSigner(bytes32 message, bytes memory sig)
       internal
       pure
       returns (address)
   {
       (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);

       return ecrecover(message, v, r, s);
   }
}

contract ColdChain {
   enum Mode {
       ISSUER,
       PROVER,
       VERIFIER
   }
   struct Entity {
       address id;
       Mode mode;
       uint[] certificateIds;
   }

   enum Status {
       MANUFACTURED,
       DELIVERING_INTERNATIONAL,
       STORED,
       DELIVERING_LOCAL,
       DELIVERED
   }

   struct Certificate {
       uint id;
       Entity issuer;
       Entity prover;
       bytes signature;
       Status status;
   }

   struct VaccineBatch {
       uint id;
       string brand;
       address manufacturer;
       uint[] certificateIds;
   }

   uint public constant MAX_CERTITICATIONS = 2;

   uint[] public certificateIds;
   uint[] public vaccineBatchIds;

   mapping(uint => VaccineBatch) public vaccineBatches;
   mapping(uint => Certificate) public certificates;
   mapping(uint => Entity) public entities;
   // NOTE: I declared a variable that allows you to track the length of Entities in the mapping
   uint entitiesCount = 0; 

   event AddEntity(address entityId, string entityMode);
   event AddVaccineBatch(uint vaccineBatchId, address indexed manufacturer);
   event IssueCertificate(
       address indexed issuer,
       address indexed prover,
       uint certificateId
   );

   function addEntity(address _id, string memory _mode) public {
       Mode mode = unmarshalMode(_mode);
       uint[] memory _certificateIds = new uint[](MAX_CERTITICATIONS);
       Entity memory entity = Entity(_id, mode, _certificateIds);
       // NOTE: I changed _id with an uint value;
       entities[entitiesCount] = entity;

       emit AddEntity(entity.id, _mode);
   }

   function unmarshalMode(string memory _mode)
       private
       pure
       returns (Mode mode)
   {
       bytes32 encodedMode = keccak256(abi.encodePacked(_mode));
       bytes32 encodedMode0 = keccak256(abi.encodePacked("ISSUER"));
       bytes32 encodedMode1 = keccak256(abi.encodePacked("PROVER"));
       bytes32 encodedMode2 = keccak256(abi.encodePacked("VERIFIER"));

       if (encodedMode == encodedMode0) {
           return Mode.ISSUER;
       } else if (encodedMode == encodedMode1) {
           return Mode.PROVER;
       } else if (encodedMode == encodedMode2) {
           return Mode.VERIFIER;
       }

       revert("recieved invalid entity mode");
   }

   function addVaccineBatch(string memory brand, address manufacturer)
       public
       returns (uint)
   {
       uint[] memory _certificateIds = new uint[](MAX_CERTITICATIONS);
       uint id = vaccineBatchIds.length;
       VaccineBatch memory batch = VaccineBatch(
           id,
           brand,
           manufacturer,
           _certificateIds
       );

       vaccineBatches[id] = batch;
       vaccineBatchIds.push(id);

       emit AddVaccineBatch(batch.id, batch.manufacturer);
       return id;
   }

   function issueCertificate(
       uint _idIssuer,
       address _issuer,
       uint _idProver,
       address _prover,
       string memory _status,
       uint vaccineBatchId,
       bytes memory signature
   ) public returns (uint) {
       // NOTE: Entities mapping have uint datatype as KEY. For this reason if you want querying entities mapping 
       //       you must put a uint value  
       Entity memory issuer = entities[_idIssuer];
       require(issuer.mode == Mode.ISSUER);

       // NOTE: The same reasoning that I wrote in the previous comment (153-154)
       Entity memory prover = entities[_idProver];
       require(prover.mode == Mode.PROVER);

       Status status = unmarshalStatus(_status);

       uint id = certificateIds.length;
       Certificate memory certificate = Certificate(
           id,
           issuer,
           prover,
           signature,
           status
       );

       certificateIds.push(certificateIds.length);
       certificates[certificateIds.length - 1] = certificate;

       emit IssueCertificate(_issuer, _prover, certificateIds.length - 1);

       return certificateIds.length - 1;
   }

   function unmarshalStatus(string memory _status)
       private
       pure
       returns (Status status)
   {
       bytes32 encodedStatus = keccak256(abi.encodePacked(_status));
       bytes32 encodedStatus0 = keccak256(abi.encodePacked("MANUFACTURED"));
       bytes32 encodedStatus1 = keccak256(
           abi.encodePacked("DELIVERING_INTERNATIONAL")
       );
       bytes32 encodedStatus2 = keccak256(abi.encodePacked("STORED"));
       bytes32 encodedStatus3 = keccak256(
           abi.encodePacked("DELIVERING_LOCAL")
       );
       bytes32 encodedStatus4 = keccak256(abi.encodePacked("DELIVERED"));

       if (encodedStatus == encodedStatus0) {
           return Status.MANUFACTURED;
       } else if (encodedStatus == encodedStatus1) {
           return Status.DELIVERING_INTERNATIONAL;
       } else if (encodedStatus == encodedStatus2) {
           return Status.STORED;
       } else if (encodedStatus == encodedStatus3) {
           return Status.DELIVERING_LOCAL;
       } else if (encodedStatus == encodedStatus4) {
           return Status.DELIVERED;
       }

       revert("recieved invalid Certificate Status");
   }

   function isMatchingSignature(
       bytes32 message,
       uint id,
       address issuer
   ) public view returns (bool) {
       Certificate memory cert = certificates[id];
       require(cert.issuer.id == issuer);

       address recoveredSigner = CryptoSuite.recoverSigner(
           message,
           cert.signature
       );

       return recoveredSigner == cert.issuer.id;
   }
}

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