Skip to content

Instantly share code, notes, and snippets.

@ahbanavi
Last active May 19, 2022 19:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahbanavi/ca2a2ec90bdfb7662ed9063e13d609cd to your computer and use it in GitHub Desktop.
Save ahbanavi/ca2a2ec90bdfb7662ed9063e13d609cd to your computer and use it in GitHub Desktop.
ECDSA Sign off-chain and Validate on-chain
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
using ECDSA for bytes32;
// verify signature
if (
keccak256(abi.encodePacked(msg.sender, address(this))).toEthSignedMessageHash().recover(signature) !=
owner()
) revert InvalidSignature();
<?php
use Elliptic\EC;
use kornrunner\Keccak;
// all addresses are without 0x
function hashMessage($address, $contractAddress): string
{
return Keccak::hash(hex2bin($address . $contractAddress), 256);
}
function sign($message, $privateKey): string
{
$message = Keccak::hash(hex2bin(bin2hex("\x19Ethereum Signed Message:\n32") . $message), 256);
$ec = new EC('secp256k1');
$privateKey = $ec->keyFromPrivate($privateKey);
$signature = $privateKey->sign($message, ['canonical' => true]);
$r = str_pad($signature->r->toString(16), 64, '0', STR_PAD_LEFT);
$s = str_pad($signature->s->toString(16), 64, '0', STR_PAD_LEFT);
$v = dechex($signature->recoveryParam + 27);
return "0x$r$s$v";
}
function hashAndSign($address, $contractAddress, $privateKey): array
{
$hash = hashMessage($address, $contractAddress);
return sign($hash, $privateKey);
}
async function getPreSaleSignature(
signer: SignerWithAddress,
minter: SignerWithAddress,
contractAddress: string
): Promise<string> {
const hash = ethers.utils.solidityKeccak256(['address', 'address'], [minter.address, contractAddress]);
return signer.signMessage(ethers.utils.arrayify(hash));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment