🏗️
This commit is contained in:
78
contracts/lib/utils/ECDSA.sol
Normal file
78
contracts/lib/utils/ECDSA.sol
Normal file
@@ -0,0 +1,78 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.4;
|
||||
|
||||
/// @notice Gas optimized ECDSA wrapper.
|
||||
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
|
||||
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
|
||||
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
|
||||
library ECDSA {
|
||||
/// @dev The signature is invalid.
|
||||
error InvalidSignature();
|
||||
|
||||
/// @dev The number which `s` must not exceed in order for
|
||||
/// the signature to be non-malleable.
|
||||
bytes32 private constant _MALLEABILITY_THRESHOLD =
|
||||
0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0;
|
||||
|
||||
/// @dev Recovers the signer's address from a message digest `hash`,
|
||||
/// and the signature defined by `v`, `r`, `s`.
|
||||
function recover(
|
||||
bytes32 hash,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) internal view returns (address result) {
|
||||
/// @solidity memory-safe-assembly
|
||||
assembly {
|
||||
// Copy the free memory pointer so that we can restore it later.
|
||||
let m := mload(0x40)
|
||||
mstore(0x00, hash)
|
||||
mstore(0x20, and(v, 0xff))
|
||||
mstore(0x40, r)
|
||||
mstore(0x60, s)
|
||||
pop(
|
||||
staticcall(
|
||||
gas(), // Amount of gas left for the transaction.
|
||||
// If `s` in lower half order, such that the signature is not malleable.
|
||||
lt(s, add(_MALLEABILITY_THRESHOLD, 1)), // Address of `ecrecover`.
|
||||
0x00, // Start of input.
|
||||
0x80, // Size of input.
|
||||
0x00, // Start of output.
|
||||
0x20 // Size of output.
|
||||
)
|
||||
)
|
||||
result := mload(0x00)
|
||||
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
|
||||
if iszero(returndatasize()) {
|
||||
// Store the function selector of `InvalidSignature()`.
|
||||
mstore(0x00, 0x8baa579f)
|
||||
// Revert with (offset, size).
|
||||
revert(0x1c, 0x04)
|
||||
}
|
||||
// Restore the zero slot.
|
||||
mstore(0x60, 0)
|
||||
// Restore the free memory pointer.
|
||||
mstore(0x40, m)
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Returns an Ethereum Signed Message, created from a `hash`.
|
||||
/// This produces a hash corresponding to the one signed with the
|
||||
/// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
|
||||
/// JSON-RPC method as part of EIP-191.
|
||||
function toEthSignedMessageHash(
|
||||
bytes32 hash
|
||||
) internal pure returns (bytes32 result) {
|
||||
/// @solidity memory-safe-assembly
|
||||
assembly {
|
||||
// Store into scratch space for keccak256.
|
||||
mstore(0x20, hash)
|
||||
mstore(
|
||||
0x00,
|
||||
"\x00\x00\x00\x00\x19Ethereum Signed Message:\n32"
|
||||
)
|
||||
// 0x40 - 0x04 = 0x3c
|
||||
result := keccak256(0x04, 0x3c)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user