OfflineBase.sol (3187B)
1 pragma solidity ^0.8.0; 2 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // Some methods are copied under other licenses, please see code comments for details 5 6 abstract contract Offline { 7 function executeOfflineRequest(bytes memory _data, bytes memory _signature, uint8 _version) public virtual returns(uint256); 8 9 function isOfflineValid(address _validator, bytes memory _data) external virtual view returns(bool); 10 11 function verifyOfflineRequest(bytes memory _data, bytes memory _signature, bytes32 _domainSeparator, bytes32 _typeHash) public view returns(bool) { 12 bytes memory message; 13 bytes32 messageDigest; 14 bytes memory dataDigest; 15 address _owner; 16 17 dataDigest = new bytes(32 + _data.length); 18 for (uint256 i = 0; i < 32; i++) { 19 dataDigest[i] = _typeHash[i]; 20 } 21 for (uint256 i = 0; i < _data.length; i++) { 22 dataDigest[i+32] = _data[i]; 23 } 24 messageDigest = keccak256(dataDigest); 25 26 message = new bytes(2 + 32 + 32); 27 message[0] = 0x19; 28 message[1] = 0x01; 29 for (uint256 i = 0; i < 32; i++) { 30 message[i+2] = _domainSeparator[i]; 31 } 32 for (uint256 i = 0; i < 32; i++) { 33 message[i+34] = messageDigest[i]; 34 } 35 36 messageDigest = keccak256(message); 37 _owner = recoverSigner(messageDigest, _signature); 38 39 return this.isOfflineValid(_owner, _data); 40 } 41 42 function verifyOfflineRequest(bytes memory _data, bytes memory _signature) public view returns(bool) { 43 bytes memory message; 44 bytes32 messageDigest; 45 address _owner; 46 47 message = toValidatorMessage(_data); 48 messageDigest = keccak256(message); 49 _owner = recoverSigner(messageDigest, _signature); 50 51 return this.isOfflineValid(_owner, _data); 52 } 53 54 function toValidatorMessage(bytes memory _data) private view returns(bytes memory) { 55 bytes memory message; 56 uint256 c; 57 bytes20 contractBytes; 58 59 message = new bytes(22 + _data.length); 60 message[0] = 0x19; 61 62 c = 2; 63 contractBytes = bytes20(address(this)); 64 for (uint256 i = 0; i < 20; i++) { 65 message[i+c] = contractBytes[i]; 66 } 67 68 c += 20; 69 for (uint256 i = 0; i < _data.length; i++) { 70 message[i+c] = _data[i]; 71 } 72 return message; 73 } 74 75 // from https://solidity-by-example.org/signature/ 76 // Published under MIT license 77 function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature) private pure returns (address) { 78 (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature); 79 return ecrecover(_ethSignedMessageHash, v, r, s); 80 } 81 82 // from https://solidity-by-example.org/signature/ 83 // Published under MIT license 84 function splitSignature(bytes memory sig) private pure returns (bytes32 r, bytes32 s, uint8 v) { 85 require(sig.length == 65, "invalid signature length"); 86 87 assembly { 88 /* 89 First 32 bytes stores the length of the signature 90 91 add(sig, 32) = pointer of sig + 32 92 effectively, skips first 32 bytes of signature 93 94 mload(p) loads next 32 bytes starting at the memory address p into memory 95 */ 96 97 // first 32 bytes, after the length prefix 98 r := mload(add(sig, 32)) 99 // second 32 bytes 100 s := mload(add(sig, 64)) 101 // final byte (first byte of the next 32 bytes) 102 v := byte(0, mload(add(sig, 96))) 103 } 104 105 // implicitly return (r, s, v) 106 } 107 }