Skip to content

Commit

Permalink
0.1.0-alpha.2
Browse files Browse the repository at this point in the history
  • Loading branch information
0xGh committed Nov 26, 2023
1 parent 619d620 commit 5ff0dd0
Show file tree
Hide file tree
Showing 7 changed files with 1,082 additions and 44 deletions.
663 changes: 662 additions & 1 deletion LICENSE

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions contracts/ERC721Baseline.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol";
import {IERC721Baseline} from "./IERC721Baseline.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol";
import {Utils} from "./Utils.sol";

/**
* @title ERC721Baseline
* @custom:version v0.1.0-alpha.1
* @custom:version v0.1.0-alpha.2
* @notice A baseline ERC721 contract implementation that exposes internal methods to a proxy instance.
*/

Expand All @@ -20,7 +20,7 @@ contract ERC721Baseline is ERC721, IERC2981, IERC721Baseline {
/**
* @dev The version of the implementation contract.
*/
string public constant VERSION = "0.1.0-alpha.1";
string public constant VERSION = "0.1.0-alpha.2";

constructor() ERC721("", "") {}

Expand Down Expand Up @@ -471,30 +471,30 @@ contract ERC721Baseline is ERC721, IERC2981, IERC721Baseline {
_transferOwnership(newOwner);
}


/************************************************
* Utils
************************************************/

/**
* Signature Validation Library.
* MIT Licensed, (c) 2022-present Solady.
* @dev See {IERC721Baseline-recover}.
*/
function recover(bytes32 hash, bytes memory signature) external view returns (address result) {
return Utils.recover(hash, signature);
}

/**
* @dev See {SignatureCheckerLib-isValidSignatureNow}.
* @dev See {IERC721Baseline-recoverCalldata}.
*/
function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)
external
view
returns (bool isValid)
{
return SignatureCheckerLib.isValidSignatureNow(signer, hash, signature);
function recoverCalldata(bytes32 hash, bytes calldata signature) external view returns (address result) {
return Utils.recoverCalldata(hash, signature);
}

/**
* @dev See {SignatureCheckerLib-isValidSignatureNowCalldata}.
* @dev See {IERC721Baseline-toString}.
*/
function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)
external
view
returns (bool isValid)
{
return SignatureCheckerLib.isValidSignatureNowCalldata(signer, hash, signature);
function toString(uint256 value) external pure returns (string memory) {
return Utils.toString(value);
}

}
35 changes: 34 additions & 1 deletion contracts/IERC721Baseline.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";

/**
* @title IERC721Baseline
* @custom:version v0.1.0-alpha.1
* @custom:version v0.1.0-alpha.2
* @notice A baseline ERC721 contract implementation that exposes internal methods to a proxy instance.
*/

Expand Down Expand Up @@ -286,4 +286,37 @@ interface IERC721Baseline is IERC721 {
* @param newOwner new owner address
*/
function __transferOwnership(address newOwner) external;


/************************************************
* Utils
************************************************/

/**
* @notice Recovers the signer's address from a message digest `hash`, and the `signature`.
*
* @param hash the message digest that was signed
* @param signature the signature for hash
* @return result address the recovered address
*/
function recover(bytes32 hash, bytes memory signature) external view returns (address result);

/**
* @notice Recovers the signer's address from a message digest `hash`, and the `signature`.
* @dev In this method the signature comes from calldata.
*
* @param hash the message digest that was signed
* @param signature the signature for hash
* @return result address the recovered address
*/
function recoverCalldata(bytes32 hash, bytes calldata signature) external view returns (address result);

/**
* @notice Converts a uint256 to string
*
* @param value the uint256 to convert
* @return string ASCII string decimal representation of `value`
*/
function toString(uint256 value) external pure returns (string memory);

}
187 changes: 187 additions & 0 deletions contracts/Utils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.21;

/**
* @title Utils
* @custom:version v0.1.0-alpha.2
* @notice Utilities used in ERC721Baseline.
*/

library Utils {
/************************************************
* ECDSA Utils
************************************************/

error InvalidSignature();

/**
* recover
*
* @notice Recovers the signer's address from a message digest `hash`, and the `signature`.
* MIT Licensed, (c) 2022-present Solady.
*/
function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := 1
let m := mload(0x40) // Cache the free memory pointer.
// prettier-ignore
for {} 1 {} {
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
if eq(mload(signature), 64) {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
break
}
if eq(mload(signature), 65) {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
break
}
result := 0
break
}
result := mload(
staticcall(
gas(), // Amount of gas left for the transaction.
result, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}

/**
* recoverCalldata
*
* @notice Recovers the signer's address from a message digest `hash`, and the `signature`.
* MIT Licensed, (c) 2022-present Solady.
*/
function recoverCalldata(
bytes32 hash,
bytes calldata signature
) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := 1
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
// prettier-ignore
for {} 1 {} {
if eq(signature.length, 64) {
let vs := calldataload(add(signature.offset, 0x20))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, calldataload(signature.offset)) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
break
}
if eq(signature.length, 65) {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
break
}
result := 0
break
}
result := mload(
staticcall(
gas(), // Amount of gas left for the transaction.
result, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}


/************************************************
* String Utils
************************************************/

/**
* @notice toString.
* MIT Licensed, (c) 2022-present OpenZeppelin.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), "0123456789abcdef"))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}

/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
}
Loading

0 comments on commit 5ff0dd0

Please sign in to comment.