Skip to content

Instantly share code, notes, and snippets.

@chiro-hiro
Last active April 20, 2022 11:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chiro-hiro/2ffbde71ed24d2a0646b9fd9bf68de9e to your computer and use it in GitHub Desktop.
Save chiro-hiro/2ffbde71ed24d2a0646b9fd9bf68de9e to your computer and use it in GitHub Desktop.
chiro-code.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.6.4;
contract VerifyPoC {
function verifySerialized(bytes memory message, bytes memory signature) public pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
// Singature need to be 65 in length
// if (signature.length !== 65) revert();
if iszero(eq(mload(signature), 65)) {
revert(0, 0)
}
// r = signature[:32]
// s = signature[32:64]
// v = signature[64]
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
// For Ethereum it's only possible to be 27, 28 and 0,1 in legacy code
if lt(v, 27) {
v := add(v, 27)
}
if iszero(or(eq(v, 27), eq(v, 28))) {
revert(0, 0)
}
}
// Get hashes of message with Ethereum proof prefix
bytes32 hashes = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", uintToStr(message.length), message));
return ecrecover(hashes, v, r, s);
}
function verify(bytes memory message, bytes32 r, bytes32 s, uint8 v) public pure returns (address) {
if(v < 27) {
v += 27;
}
// V must be 27 or 28
require(v == 27 || v == 28, "Invalid v value");
// Get hashes of message with Ethereum proof prefix
bytes32 hashes = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", uintToStr(message.length), message));
return ecrecover(hashes, v, r, s);
}
function uintToStr(uint256 value) public pure returns (bytes memory) {
assembly {
let result := mload(0x40)
mstore(result, 0x20)
let length := 0x00
let lenOffset := add(result, 0x20)
let offset := add(result, 0x40)
switch value
case 0x00 {
// result.length = 1
length := 0x01
mstore(lenOffset, length)
// result = "0"
mstore8(offset, 0x30)
}
default {
// Get length of render number
// for (let v := value; v > 0; v = v / 10)
for { let v := value } gt(v, 0x00) { v := div(v, 0x0a) } {
length := add(length, 0x01)
}
// We're only support number with 32 digits
// if (length > 32) revert();
if gt(length, 0x20) {
revert(0x00, 0x00)
}
// Set length of result
mstore(lenOffset, length)
// Start render result
// for (let v := value; length > 0; v = v / 10)
for { let v := value } gt(length, 0x00) { v := div(v, 0x0a) } {
// result[--length] = 48 + (v % 10)
length := sub(length, 0x01)
mstore8(add(offset, length), add(0x30, mod(v, 0x0a)))
}
}
return(result, 0x60)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment