base-10grans/contracts/libraries/TransitionMintLib.sol

86 lines
2.9 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/utils/Strings.sol";
/**
* @title TransitionMintLib
* @notice Library for handling transition minting logic
*/
library TransitionMintLib {
function getEthSignedMessageHash(bytes32 _messageHash) internal pure returns (bytes32) {
/*
Signature is produced by signing a keccak256 hash with the following format:
"\x19Ethereum Signed Message\n" + len(msg) + msg
*/
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash));
}
function toString(address x) internal pure returns (string memory) {
bytes memory s = new bytes(40);
for (uint i = 0; i < 20; i++) {
bytes1 b = bytes1(uint8(uint(uint160(x)) / (2 ** (8 * (19 - i)))));
bytes1 hi = bytes1(uint8(b) / 16);
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
s[2 * i] = char(hi);
s[2 * i + 1] = char(lo);
}
return string(s);
}
function char(bytes1 b) internal pure returns (bytes1 c) {
if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
else return bytes1(uint8(b) + 0x57);
}
function messageHash(
address holder,
uint256 snapshotQuantity
) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(
"10grans migration address: ",
toString(holder),
" wei: ",
Strings.toString(snapshotQuantity)
));
}
function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature) internal pure returns (address) {
(bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
return ecrecover(_ethSignedMessageHash, v, r, s);
}
function splitSignature(bytes memory sig) internal 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)))
}
}
function verifyMintSignature(
address holder,
uint256 snapshotQuantity,
bytes memory signature,
address signer
) internal pure returns (bool) {
bytes32 mh = messageHash(holder, snapshotQuantity);
bytes32 ethSignedMessageHash = getEthSignedMessageHash(mh);
return recoverSigner(ethSignedMessageHash, signature) == signer;
}
}