commit 6802d8018d8b85e7e119a0f1d136a0cdb21c664a
Author: lash <dev@holbrook.no>
Date: Mon, 13 Mar 2023 12:12:17 +0000
Initial commit
Diffstat:
1 file changed, 94 insertions(+), 0 deletions(-)
diff --git a/solidity/OfflineMinter.sol b/solidity/OfflineMinter.sol
@@ -0,0 +1,94 @@
+pragma solidity ^0.8.0;
+
+contract OfflineMinter {
+
+ bytes26 constant prefix = bytes26(abi.encodePacked("0x19457468657265756d205369676e6564204d6573736167653a0a"));
+
+ function verifyRequest(address _owner, bytes memory _data, bytes memory _signature) public pure returns(bool) {
+ address beneficiary;
+ bytes memory extra;
+ bytes memory message;
+ bytes32 messageDigest;
+ string memory messageLength;
+ uint256 messageLengthLength;
+
+ (beneficiary, extra) = splitData(_data);
+ messageLength = uintToString(uint(_data.length));
+ messageLengthLength = bytes(messageLength).length;
+
+ message = new bytes(_data.length + 26 + messageLengthLength);
+ messageDigest = keccak256(abi.encodePacked(prefix, messageLength, _data));
+
+ return _owner == recoverSigner(messageDigest, _signature);
+ }
+
+ function splitData(bytes memory _data) public pure returns(address _beneficiary, bytes memory _extra) {
+ bytes memory beneficiary;
+ bytes memory extra;
+
+ require(_data.length > 20, 'ERR_CONTENTS');
+
+ beneficiary = new bytes(20);
+ extra = new bytes(_data.length - 20);
+
+ for (uint256 i; i < beneficiary.length; i++) {
+ beneficiary[i] = _data[i];
+ }
+ for (uint256 i; i < extra.length; i++) {
+ extra[i] = _data[i+20];
+ }
+ verifyExtraData(extra);
+ return (address(bytes20(beneficiary)), extra);
+ }
+
+ function verifyExtraData(bytes memory _data) public pure {
+ revert('verification not implemented');
+ }
+
+ // from https://solidity-by-example.org/signature/
+ function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature) public pure returns (address) {
+ (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
+ return ecrecover(_ethSignedMessageHash, v, r, s);
+ }
+
+ // from https://solidity-by-example.org/signature/
+ function splitSignature(bytes memory sig) public pure returns (bytes32 r, bytes32 s, uint8 v) {
+ require(sig.length == 65, "invalid signature length");
+
+ assembly {
+ /*
+ First 32 bytes stores the length of the signature
+
+ add(sig, 32) = pointer of sig + 32
+ effectively, skips first 32 bytes of signature
+
+ mload(p) loads next 32 bytes starting at the memory address p into memory
+ */
+
+ // first 32 bytes, after the length prefix
+ r := mload(add(sig, 32))
+ // second 32 bytes
+ s := mload(add(sig, 64))
+ // final byte (first byte of the next 32 bytes)
+ v := byte(0, mload(add(sig, 96)))
+ }
+
+ // implicitly return (r, s, v)
+ }
+
+ function uintToString(uint v) public pure returns (string memory str) {
+ uint maxlength = 100;
+ bytes memory reversed = new bytes(maxlength);
+ uint i = 0;
+ while (v != 0) {
+ uint remainder = v % 10;
+ v = v / 10;
+ reversed[i++] = bytes1(bytes32(48 + remainder));
+ }
+ bytes memory s = new bytes(i);
+ for (uint j = 0; j < i; j++) {
+ s[j] = reversed[i - 1 - j];
+ }
+ str = string(s);
+ }
+}