github.com/diadata-org/diadata@v1.4.593/pkg/dia/scraper/blockchain-scrapers/blockchains/ethereum/diaOracleV2Multiupdate/DIASignedOracleMultiple.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  
     3  pragma solidity ^0.8.23;
     4  
     5  import "@openzeppelin/contracts/access/Ownable.sol";
     6  
     7  contract DIASignedOracleMultiple is Ownable {
     8      address public signer;
     9      struct Message {
    10          string Symbol;
    11          address Address;
    12          string Blockchain;
    13          uint256 Price;
    14          uint256 Time;
    15      }
    16  
    17      struct RawMessage {
    18          string Symbol;
    19          address Address;
    20          string Blockchain;
    21          uint256 Price;
    22          uint256 Time;
    23          bytes Signature;
    24      }
    25  
    26      mapping(string => Message) public values;
    27  
    28      event OracleUpdate(string key, uint256 value, uint256 timestamp);
    29   
    30       event RequestUpdate(
    31          address assetAddress,
    32          string blockchain,
    33          uint256 timestamp
    34      );
    35  
    36      constructor() Ownable(msg.sender) {
    37          signer = msg.sender;
    38      }
    39  
    40      function setValues(RawMessage[] memory vs) public {
    41          for (uint i = 0; i < vs.length; i++) {
    42              this.setValue(vs[i]);
    43          }
    44      }
    45  
    46      function setValue(RawMessage memory v) external {
    47          require(getSigner(v) == signer, "SIGNER_DONT_MATCH");
    48          require(v.Time >= values[v.Symbol].Time, "NEWER_TIMESTAMP_REQUIRED");
    49  
    50          Message memory valueWithoutSignature = Message({
    51              Symbol: v.Symbol,
    52              Address: v.Address,
    53              Blockchain: v.Blockchain,
    54              Price: v.Price,
    55              Time: v.Time
    56          });
    57  
    58          values[v.Symbol] = valueWithoutSignature;
    59          emit OracleUpdate(v.Symbol, v.Price, v.Time);
    60      }
    61  
    62      function requestForUpdate(
    63          address assetAddress,
    64          string memory blockchain,
    65          uint256 timestamp
    66      ) external {
    67          emit RequestUpdate(assetAddress, blockchain, timestamp);
    68      }
    69  
    70      function getValue(
    71          string memory key
    72      ) external view returns (Message memory) {
    73          return values[key];
    74      }
    75  
    76      function updateSigner(address _newSigner) external onlyOwner {
    77          signer = _newSigner;
    78      }
    79  
    80      function changeOwner(address newOwner) external onlyOwner {
    81          _transferOwnership(newOwner);
    82      }
    83  
    84      function getSigner(RawMessage memory message) public pure returns (address) {
    85          bytes memory _signature;
    86          _signature = message.Signature;
    87  
    88          string
    89              memory EIP712_DOMAIN_TYPE = "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)";
    90          string
    91              memory MESSAGE_TYPE = "Message(string Symbol,address Address,string Blockchain,uint256 Price,uint256 Time)";
    92  
    93          bytes32 DOMAIN_SEPARATOR = keccak256(
    94              abi.encode(
    95                  keccak256(abi.encodePacked(EIP712_DOMAIN_TYPE)),
    96                  keccak256(abi.encodePacked("DiaData")),
    97                  keccak256(abi.encodePacked("1.0.0")),
    98                  1,
    99                  0x0000000000000000000000000000000000000000
   100              )
   101          );
   102  
   103          bytes32 hash = keccak256(
   104              abi.encodePacked(
   105                  "\x19\x01", // backslash is needed to escape the character
   106                  DOMAIN_SEPARATOR,
   107                  keccak256(
   108                      abi.encode(
   109                          keccak256(abi.encodePacked(MESSAGE_TYPE)),
   110                          keccak256(bytes(message.Symbol)),
   111                          message.Address,
   112                          keccak256(bytes(message.Blockchain)),
   113                          message.Price,
   114                          message.Time
   115                      )
   116                  )
   117              )
   118          );
   119  
   120          // split signature
   121          bytes32 r;
   122          bytes32 s;
   123          uint8 v;
   124          if (_signature.length != 65) {
   125              return address(0);
   126          }
   127          assembly {
   128              r := mload(add(_signature, 32))
   129              s := mload(add(_signature, 64))
   130              v := byte(0, mload(add(_signature, 96)))
   131          }
   132          if (v < 27) {
   133              v += 27;
   134          }
   135          if (v != 27 && v != 28) {
   136              return address(0);
   137          } else {
   138              // verify
   139              return ecrecover(hash, v, r, s);
   140          }
   141      }
   142  }