-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add erc-1271 support for claiming airdrops
- Loading branch information
1 parent
2756109
commit fe4d485
Showing
6 changed files
with
352 additions
and
3 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: MIT | ||
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1271.sol) | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
/** | ||
* @dev Interface of the ERC-1271 standard signature validation method for | ||
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. | ||
*/ | ||
interface IERC1271 { | ||
/** | ||
* @dev Should return whether the signature provided is valid for the provided data | ||
* @param hash Hash of the data to be signed | ||
* @param signature Signature byte array associated with _data | ||
*/ | ||
function isValidSignature( | ||
bytes32 hash, | ||
bytes memory signature | ||
) external view returns (bytes4 magicValue); | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
// SPDX-License-Identifier: MIT | ||
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
/** | ||
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. | ||
* | ||
* These functions can be used to verify that a message was signed by the holder | ||
* of the private keys of a given address. | ||
*/ | ||
library ECDSA { | ||
enum RecoverError { | ||
NoError, | ||
InvalidSignature, | ||
InvalidSignatureLength, | ||
InvalidSignatureS | ||
} | ||
|
||
/** | ||
* @dev The signature derives the `address(0)`. | ||
*/ | ||
error ECDSAInvalidSignature(); | ||
|
||
/** | ||
* @dev The signature has an invalid length. | ||
*/ | ||
error ECDSAInvalidSignatureLength(uint256 length); | ||
|
||
/** | ||
* @dev The signature has an S value that is in the upper half order. | ||
*/ | ||
error ECDSAInvalidSignatureS(bytes32 s); | ||
|
||
/** | ||
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not | ||
* return address(0) without also returning an error description. Errors are documented using an enum (error type) | ||
* and a bytes32 providing additional information about the error. | ||
* | ||
* If no error is returned, then the address can be used for verification purposes. | ||
* | ||
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: | ||
* this function rejects them by requiring the `s` value to be in the lower | ||
* half order, and the `v` value to be either 27 or 28. | ||
* | ||
* IMPORTANT: `hash` _must_ be the result of a hash operation for the | ||
* verification to be secure: it is possible to craft signatures that | ||
* recover to arbitrary addresses for non-hashed data. A safe way to ensure | ||
* this is by receiving a hash of the original message (which may otherwise | ||
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. | ||
* | ||
* Documentation for signature generation: | ||
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] | ||
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] | ||
*/ | ||
function tryRecover( | ||
bytes32 hash, | ||
bytes memory signature | ||
) internal pure returns (address, RecoverError, bytes32) { | ||
if (signature.length == 65) { | ||
bytes32 r; | ||
bytes32 s; | ||
uint8 v; | ||
// ecrecover takes the signature parameters, and the only way to get them | ||
// currently is to use assembly. | ||
/// @solidity memory-safe-assembly | ||
assembly { | ||
r := mload(add(signature, 0x20)) | ||
s := mload(add(signature, 0x40)) | ||
v := byte(0, mload(add(signature, 0x60))) | ||
} | ||
return tryRecover(hash, v, r, s); | ||
} else { | ||
return ( | ||
address(0), | ||
RecoverError.InvalidSignatureLength, | ||
bytes32(signature.length) | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* @dev Returns the address that signed a hashed message (`hash`) with | ||
* `signature`. This address can then be used for verification purposes. | ||
* | ||
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: | ||
* this function rejects them by requiring the `s` value to be in the lower | ||
* half order, and the `v` value to be either 27 or 28. | ||
* | ||
* IMPORTANT: `hash` _must_ be the result of a hash operation for the | ||
* verification to be secure: it is possible to craft signatures that | ||
* recover to arbitrary addresses for non-hashed data. A safe way to ensure | ||
* this is by receiving a hash of the original message (which may otherwise | ||
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. | ||
*/ | ||
function recover( | ||
bytes32 hash, | ||
bytes memory signature | ||
) internal pure returns (address) { | ||
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover( | ||
hash, | ||
signature | ||
); | ||
_throwError(error, errorArg); | ||
return recovered; | ||
} | ||
|
||
/** | ||
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. | ||
* | ||
* See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures] | ||
*/ | ||
function tryRecover( | ||
bytes32 hash, | ||
bytes32 r, | ||
bytes32 vs | ||
) internal pure returns (address, RecoverError, bytes32) { | ||
unchecked { | ||
bytes32 s = vs & | ||
bytes32( | ||
0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | ||
); | ||
// We do not check for an overflow here since the shift operation results in 0 or 1. | ||
uint8 v = uint8((uint256(vs) >> 255) + 27); | ||
return tryRecover(hash, v, r, s); | ||
} | ||
} | ||
|
||
/** | ||
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. | ||
*/ | ||
function recover( | ||
bytes32 hash, | ||
bytes32 r, | ||
bytes32 vs | ||
) internal pure returns (address) { | ||
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover( | ||
hash, | ||
r, | ||
vs | ||
); | ||
_throwError(error, errorArg); | ||
return recovered; | ||
} | ||
|
||
/** | ||
* @dev Overload of {ECDSA-tryRecover} that receives the `v`, | ||
* `r` and `s` signature fields separately. | ||
*/ | ||
function tryRecover( | ||
bytes32 hash, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
) internal pure returns (address, RecoverError, bytes32) { | ||
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature | ||
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines | ||
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most | ||
// signatures from current libraries generate a unique signature with an s-value in the lower half order. | ||
// | ||
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value | ||
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or | ||
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept | ||
// these malleable signatures as well. | ||
if ( | ||
uint256(s) > | ||
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 | ||
) { | ||
return (address(0), RecoverError.InvalidSignatureS, s); | ||
} | ||
|
||
// If the signature is valid (and not malleable), return the signer address | ||
address signer = ecrecover(hash, v, r, s); | ||
if (signer == address(0)) { | ||
return (address(0), RecoverError.InvalidSignature, bytes32(0)); | ||
} | ||
|
||
return (signer, RecoverError.NoError, bytes32(0)); | ||
} | ||
|
||
/** | ||
* @dev Overload of {ECDSA-recover} that receives the `v`, | ||
* `r` and `s` signature fields separately. | ||
*/ | ||
function recover( | ||
bytes32 hash, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
) internal pure returns (address) { | ||
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover( | ||
hash, | ||
v, | ||
r, | ||
s | ||
); | ||
_throwError(error, errorArg); | ||
return recovered; | ||
} | ||
|
||
/** | ||
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. | ||
*/ | ||
function _throwError(RecoverError error, bytes32 errorArg) private pure { | ||
if (error == RecoverError.NoError) { | ||
return; // no error: do nothing | ||
} else if (error == RecoverError.InvalidSignature) { | ||
revert ECDSAInvalidSignature(); | ||
} else if (error == RecoverError.InvalidSignatureLength) { | ||
revert ECDSAInvalidSignatureLength(uint256(errorArg)); | ||
} else if (error == RecoverError.InvalidSignatureS) { | ||
revert ECDSAInvalidSignatureS(errorArg); | ||
} | ||
} | ||
} |
Oops, something went wrong.