Created
October 5, 2023 18:51
-
-
Save toddstephens335/8bca6e03d7db52bef093927c0d02964b to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.19+commit.7dd6d404.js&optimize=true&runs=200&gist=
This file contains 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 | |
// Copyright (c) 2021 the ethier authors (github.com/divergencetech/ethier) | |
pragma solidity >=0.8.0 <0.9.0; | |
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; | |
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; | |
/** | |
@title SignatureChecker | |
@notice Additional functions for EnumerableSet.Addresset that require a valid | |
ECDSA signature of a standardized message, signed by any member of the set. | |
*/ | |
library SignatureChecker { | |
using EnumerableSet for EnumerableSet.AddressSet; | |
/** | |
@notice Requires that the message has not been used previously and that the | |
recovered signer is contained in the signers AddressSet. | |
@dev Convenience wrapper for message generation + signature verification | |
+ marking message as used | |
@param signers Set of addresses from which signatures are accepted. | |
@param usedMessages Set of already-used messages. | |
@param signature ECDSA signature of message. | |
*/ | |
function requireValidSignature( | |
EnumerableSet.AddressSet storage signers, | |
bytes memory data, | |
bytes calldata signature, | |
mapping(bytes32 => bool) storage usedMessages | |
) internal { | |
bytes32 message = generateMessage(data); | |
require( | |
!usedMessages[message], | |
"SignatureChecker: Message already used" | |
); | |
usedMessages[message] = true; | |
requireValidSignature(signers, message, signature); | |
} | |
/** | |
@notice Requires that the message has not been used previously and that the | |
recovered signer is contained in the signers AddressSet. | |
@dev Convenience wrapper for message generation + signature verification. | |
*/ | |
function requireValidSignature( | |
EnumerableSet.AddressSet storage signers, | |
bytes memory data, | |
bytes calldata signature | |
) internal view { | |
bytes32 message = generateMessage(data); | |
requireValidSignature(signers, message, signature); | |
} | |
/** | |
@notice Requires that the message has not been used previously and that the | |
recovered signer is contained in the signers AddressSet. | |
@dev Convenience wrapper for message generation from address + | |
signature verification. | |
*/ | |
function requireValidSignature( | |
EnumerableSet.AddressSet storage signers, | |
address a, | |
bytes calldata signature | |
) internal view { | |
bytes32 message = generateMessage(abi.encodePacked(a)); | |
requireValidSignature(signers, message, signature); | |
} | |
/** | |
@notice Common validator logic, checking if the recovered signer is | |
contained in the signers AddressSet. | |
*/ | |
function validSignature( | |
EnumerableSet.AddressSet storage signers, | |
bytes32 message, | |
bytes calldata signature | |
) internal view returns (bool) { | |
return signers.contains(ECDSA.recover(message, signature)); | |
} | |
/** | |
@notice Requires that the recovered signer is contained in the signers | |
AddressSet. | |
@dev Convenience wrapper that reverts if the signature validation fails. | |
*/ | |
function requireValidSignature( | |
EnumerableSet.AddressSet storage signers, | |
bytes32 message, | |
bytes calldata signature | |
) internal view { | |
require( | |
validSignature(signers, message, signature), | |
"SignatureChecker: Invalid signature" | |
); | |
} | |
/** | |
@notice Generates a message for a given data input that will be signed | |
off-chain using ECDSA. | |
@dev For multiple data fields, a standard concatenation using | |
`abi.encodePacked` is commonly used to build data. | |
*/ | |
function generateMessage(bytes memory data) | |
internal | |
pure | |
returns (bytes32) | |
{ | |
return ECDSA.toEthSignedMessageHash(data); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment