Offline.sol (3107B)
1 pragma solidity ^0.8.0; 2 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 5 import './OfflineBase.sol'; 6 7 contract OfflineRubber is Offline { 8 9 struct Instruction { 10 bytes32 domain; 11 uint256 value; 12 address beneficiary; 13 } 14 15 address public contractOwner; 16 uint256 public executedTimes; 17 18 bytes32 public eip712DomainSeparator; 19 bytes32 constant public eip712TypeHash = keccak256("Instruction(bytes32 domain,uint256 value,address beneficiary)"); 20 21 struct EIP712Domain { 22 string name; 23 string version; 24 uint256 chainId; 25 address verifyingContract; 26 bytes32 salt; 27 } 28 29 bytes32 constant eip712DomainTypehash = keccak256( 30 "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)" 31 ); 32 33 function hash(EIP712Domain memory eip712Domain) internal pure returns (bytes32) { 34 return keccak256(abi.encode( 35 eip712DomainTypehash, 36 keccak256(bytes(eip712Domain.name)), 37 keccak256(bytes(eip712Domain.version)), 38 eip712Domain.chainId, 39 eip712Domain.verifyingContract, 40 eip712Domain.salt 41 )); 42 } 43 44 constructor(uint256 chainId) { 45 contractOwner = msg.sender; 46 eip712DomainSeparator = hash(EIP712Domain({ 47 name: "Offline signing test", 48 version: '0', 49 chainId: chainId, 50 verifyingContract: address(this), 51 //salt: blockhash(block.number) 52 salt: bytes32(0x00) 53 })); 54 } 55 56 function toBytes(Instruction memory _instruction) public pure returns(bytes memory) { 57 return abi.encode(_instruction); 58 } 59 60 function executeOfflineRequest(bytes memory _data, bytes memory _signature, uint8 _version) public override returns(uint256) { 61 if (_version == 0) { 62 require(verifyOfflineRequest(_data, _signature), 'ERR_UNVERIFIED'); 63 } else if (_version == 1) { 64 require(verifyOfflineRequest(_data, _signature, eip712DomainSeparator, eip712TypeHash), 'ERR_UNVERIFIED'); 65 } else { 66 revert('UNKNOWN VERSION'); 67 } 68 executedTimes++; 69 return 0; 70 } 71 72 function isOfflineValid(address _signer, bytes memory _data) external override view returns(bool) { 73 if (_signer == address(0)) { 74 return false; 75 } 76 if (uint96(bytes12(_data)) == 0) { 77 return false; 78 } 79 if (_data.length != 96) { 80 return false; 81 } 82 return contractOwner == _signer; 83 } 84 85 // function splitData(bytes memory _data) private pure returns(Instruction memory instruction) { 86 // bytes memory nonce; 87 // bytes memory beneficiary; 88 // bytes memory domain; 89 // bytes memory value; 90 // 91 // if(_data.length != 84) { 92 // return instruction; 93 // } 94 // 95 // nonce = new bytes(12); 96 // beneficiary = new bytes(20); 97 // value = new bytes(32); 98 // domain = new bytes(32); 99 // 100 // for (uint256 i; i < nonce.length; i++) { 101 // nonce[i] = _data[i]; 102 // } 103 // for (uint256 i; i < beneficiary.length; i++) { 104 // beneficiary[i] = _data[i+12]; 105 // } 106 // for (uint256 i; i < 32; i++) { 107 // domain[i] = _data[i + 32]; 108 // } 109 // for (uint256 i; i < 32; i++) { 110 // value[i] = _data[i + 64]; 111 // } 112 // instruction.nonce = bytes12(nonce); 113 // instruction.beneficiary = address(bytes20(beneficiary)); 114 // instruction.domain = bytes32(domain); 115 // instruction.value = uint256(bytes32(value)); 116 // } 117 }