Last active
April 20, 2022 11:15
-
-
Save chiro-hiro/2ffbde71ed24d2a0646b9fd9bf68de9e to your computer and use it in GitHub Desktop.
chiro-code.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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