Source Code
Overview
ETH Balance
0.0000008 ETH
Eth Value
Less Than $0.01 (@ $2,113.39/ETH)| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| 0x860c41dcbee20b8356a0bad81c551cf397fdf4394a83dd7433e482fbbfa47809 | Claim | (pending) | 4 days ago | IN | 0 ETH | (Pending) | |||
| 0x5c1aa82b5f3675be85d42d9b8317b2d9610a57fff086178af0f5192ce7259e5e | Claim | (pending) | 4 days ago | IN | 0 ETH | (Pending) | |||
| Claim | 24540702 | 7 days ago | IN | 0 ETH | 0.00000484 | ||||
| Claim | 24535411 | 7 days ago | IN | 0 ETH | 0.00022824 | ||||
| Claim | 24530801 | 8 days ago | IN | 0 ETH | 0.0001872 | ||||
| Claim | 24522673 | 9 days ago | IN | 0 ETH | 0.00018741 | ||||
| Claim | 24522602 | 9 days ago | IN | 0 ETH | 0.00018532 | ||||
| Claim | 24522578 | 9 days ago | IN | 0 ETH | 0.00000525 | ||||
| Claim | 24522488 | 9 days ago | IN | 0 ETH | 0.00018553 | ||||
| Claim | 24522089 | 9 days ago | IN | 0 ETH | 0.00018446 | ||||
| Claim | 24481704 | 15 days ago | IN | 0 ETH | 0.00000076 | ||||
| Claim | 24481704 | 15 days ago | IN | 0 ETH | 0.00000076 | ||||
| Claim | 24481668 | 15 days ago | IN | 0 ETH | 0.00000084 | ||||
| Claim | 24481665 | 15 days ago | IN | 0 ETH | 0.00000264 | ||||
| Claim | 24466783 | 17 days ago | IN | 0 ETH | 0.00000402 | ||||
| Claim | 24443153 | 20 days ago | IN | 0 ETH | 0.00018698 | ||||
| Claim | 24442385 | 20 days ago | IN | 0 ETH | 0.00001071 | ||||
| Claim | 24439232 | 21 days ago | IN | 0 ETH | 0.00018674 | ||||
| Claim | 24434245 | 21 days ago | IN | 0 ETH | 0.00003849 | ||||
| Claim | 24433499 | 22 days ago | IN | 0 ETH | 0.00000777 | ||||
| Claim | 24432586 | 22 days ago | IN | 0 ETH | 0.00018642 | ||||
| Claim | 24431412 | 22 days ago | IN | 0 ETH | 0.00018402 | ||||
| Claim | 24429393 | 22 days ago | IN | 0 ETH | 0.00018631 | ||||
| Claim | 24428894 | 22 days ago | IN | 0 ETH | 0.00018813 | ||||
| Claim | 24428615 | 22 days ago | IN | 0 ETH | 0.00018893 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60a06040 | 17882210 | 938 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
BoringClaimer
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
import "lib/solady/src/auth/Ownable.sol";
import {SignatureCheckerLib} from "lib/solady/src/utils/SignatureCheckerLib.sol";
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;
interface BoringSecurity {
function safeTransferFrom(address, address, uint256, uint256, bytes memory) external;
function balanceOf(address, uint256) external view returns (uint256);
}
error InvalidSignature();
error InvalidToken();
error AlreadyClaimed();
error Not101Holder();
contract BoringClaimer is Ownable {
address private constant BORING_SECURITY_VAULT = 0x52C45Bab6d0827F44a973899666D9Cd18Fd90bCF;
BoringSecurity private immutable boringSecurity;
address private _signer;
mapping(uint256 => bytes32) roots;
mapping(address => mapping(uint256 => bool)) public claimed;
constructor(address signer_) {
boringSecurity = BoringSecurity(0x0164fB48891b891e748244B8Ae931F2318b0c25B);
_initializeOwner(tx.origin);
_signer = signer_;
}
function claim(uint256 tokenId, bytes calldata signature) external {
if (tokenId != 101 && tokenId != 102) revert InvalidToken();
if (claimed[msg.sender][tokenId]) revert AlreadyClaimed();
if (tokenId == 102 && boringSecurity.balanceOf(msg.sender, 101) == 0) revert Not101Holder();
bytes32 hashedMessage = keccak256(abi.encodePacked(msg.sender, tokenId));
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 prefixedHashedMessage = keccak256(abi.encodePacked(prefix, hashedMessage));
if (!SignatureCheckerLib.isValidSignatureNowCalldata(_signer, prefixedHashedMessage, signature)) revert InvalidSignature();
claimed[msg.sender][tokenId] = true;
boringSecurity.safeTransferFrom(BORING_SECURITY_VAULT, msg.sender, tokenId, 1, "");
}
function setSigner(address _newSigner) external onlyOwner {
_signer = _newSigner;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
/// This event is intentionally kept the same as OpenZeppelin's Ownable to be
/// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
/// despite it not being as lightweight as a single argument event.
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
/// @dev An ownership handover to `pendingOwner` has been requested.
event OwnershipHandoverRequested(address indexed pendingOwner);
/// @dev The ownership handover to `pendingOwner` has been canceled.
event OwnershipHandoverCanceled(address indexed pendingOwner);
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
/// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The owner slot is given by: `not(_OWNER_SLOT_NOT)`.
/// It is intentionally chosen to be a high value
/// to avoid collision with lower slots.
/// The choice of manual storage layout is to enable compatibility
/// with both regular and upgradeable contracts.
uint256 private constant _OWNER_SLOT_NOT = 0x8b78c6d8;
/// The ownership handover slot of `newOwner` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
/// let handoverSlot := keccak256(0x00, 0x20)
/// ```
/// It stores the expiry timestamp of the two-step ownership handover.
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Initializes the owner directly without authorization guard.
/// This function must be called upon initialization,
/// regardless of whether the contract is upgradeable or not.
/// This is to enable generalization to both regular and upgradeable contracts,
/// and to save gas in case the initial owner is not the caller.
/// For performance reasons, this function will not check if there
/// is an existing owner.
function _initializeOwner(address newOwner) internal virtual {
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(not(_OWNER_SLOT_NOT), newOwner)
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
/// @dev Sets the owner directly without authorization guard.
function _setOwner(address newOwner) internal virtual {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := not(_OWNER_SLOT_NOT)
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, newOwner)
}
}
/// @dev Throws if the sender is not the owner.
function _checkOwner() internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner, revert.
if iszero(eq(caller(), sload(not(_OWNER_SLOT_NOT)))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns how long a two-step ownership handover is valid for in seconds.
/// Override to return a different value if needed.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to transfer the ownership to `newOwner`.
function transferOwnership(address newOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
/// @dev Allows the owner to renounce their ownership.
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
/// @dev Request a two-step ownership handover to the caller.
/// The request will automatically expire in 48 hours (172800 seconds) by default.
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to `expires`.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
// Emit the {OwnershipHandoverRequested} event.
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
/// @dev Cancels the two-step ownership handover to the caller, if any.
function cancelOwnershipHandover() public payable virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
// Emit the {OwnershipHandoverCanceled} event.
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
/// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
/// Reverts if there is no existing ownership handover requested by `pendingOwner`.
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
// If the handover does not exist, or has expired.
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
revert(0x1c, 0x04)
}
// Set the handover slot to 0.
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the owner of the contract.
function owner() public view virtual returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(not(_OWNER_SLOT_NOT))
}
}
/// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
// Compute the handover slot.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
// Load the handover slot.
result := sload(keccak256(0x0c, 0x20))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by the owner.
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Signature verification helper that supports both ECDSA signatures from EOAs
/// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol)
///
/// @dev Note: Unlike ECDSA signatures, contract signatures are revocable.
///
/// WARNING! Do NOT use signatures as unique identifiers.
/// Please use EIP712 with a nonce included in the digest to prevent replay attacks.
/// This implementation does NOT check if a signature is non-malleable.
library SignatureCheckerLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SIGNATURE CHECKING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns whether `signature` is valid for `signer` and `hash`.
/// If `signer` is a smart contract, the signature is validated with ERC1271.
/// Otherwise, the signature is validated with `ECDSA.recover`.
function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits of `signer` in case they are dirty.
for { signer := shr(96, shl(96, signer)) } signer {} {
let m := mload(0x40)
let signatureLength := mload(signature)
if eq(signatureLength, 65) {
mstore(m, hash)
mstore(add(m, 0x20), byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(add(m, 0x40), mload(add(signature, 0x20))) // `r`.
mstore(add(m, 0x60), mload(add(signature, 0x40))) // `s`.
pop(
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
m, // Start of input.
0x80, // Size of input.
m, // Start of output.
0x20 // Size of output.
)
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if mul(eq(mload(m), signer), returndatasize()) {
isValid := 1
break
}
}
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata.
// Copy the `signature` over.
let n := add(0x20, signatureLength)
pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
// forgefmt: disable-next-item
isValid := and(
and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(0x00), f),
// Whether the returndata is exactly 0x20 bytes (1 word) long.
eq(returndatasize(), 0x20)
),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
add(signatureLength, 0x64), // Length of calldata in memory.
0x00, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
break
}
}
}
/// @dev Returns whether `signature` is valid for `signer` and `hash`.
/// If `signer` is a smart contract, the signature is validated with ERC1271.
/// Otherwise, the signature is validated with `ECDSA.recover`.
function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits of `signer` in case they are dirty.
for { signer := shr(96, shl(96, signer)) } signer {} {
let m := mload(0x40)
if eq(signature.length, 65) {
mstore(m, hash)
mstore(add(m, 0x20), byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(add(m, 0x40), signature.offset, 0x40) // `r`, `s`.
pop(
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
m, // Start of input.
0x80, // Size of input.
m, // Start of output.
0x20 // Size of output.
)
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if mul(eq(mload(m), signer), returndatasize()) {
isValid := 1
break
}
}
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata.
mstore(add(m, 0x44), signature.length)
// Copy the `signature` over.
calldatacopy(add(m, 0x64), signature.offset, signature.length)
// forgefmt: disable-next-item
isValid := and(
and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(0x00), f),
// Whether the returndata is exactly 0x20 bytes (1 word) long.
eq(returndatasize(), 0x20)
),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
add(signature.length, 0x64), // Length of calldata in memory.
0x00, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
break
}
}
}
/// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`.
/// If `signer` is a smart contract, the signature is validated with ERC1271.
/// Otherwise, the signature is validated with `ECDSA.recover`.
function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
internal
view
returns (bool isValid)
{
uint8 v;
bytes32 s;
/// @solidity memory-safe-assembly
assembly {
s := shr(1, shl(1, vs))
v := add(shr(255, vs), 27)
}
isValid = isValidSignatureNow(signer, hash, v, r, s);
}
/// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`.
/// If `signer` is a smart contract, the signature is validated with ERC1271.
/// Otherwise, the signature is validated with `ECDSA.recover`.
function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits of `signer` in case they are dirty.
for { signer := shr(96, shl(96, signer)) } signer {} {
let m := mload(0x40)
mstore(m, hash)
mstore(add(m, 0x20), and(v, 0xff)) // `v`.
mstore(add(m, 0x40), r) // `r`.
mstore(add(m, 0x60), s) // `s`.
pop(
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
m, // Start of input.
0x80, // Size of input.
m, // Start of output.
0x20 // Size of output.
)
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if mul(eq(mload(m), signer), returndatasize()) {
isValid := 1
break
}
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata.
mstore(add(m, 0x44), 65) // Length of the signature.
mstore(add(m, 0x64), r) // `r`.
mstore(add(m, 0x84), s) // `s`.
mstore8(add(m, 0xa4), v) // `v`.
// forgefmt: disable-next-item
isValid := and(
and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(0x00), f),
// Whether the returndata is exactly 0x20 bytes (1 word) long.
eq(returndatasize(), 0x20)
),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
0xa5, // Length of calldata in memory.
0x00, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
break
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC1271 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns whether `signature` is valid for `hash`
/// for an ERC1271 `signer` contract.
function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let signatureLength := mload(signature)
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata.
// Copy the `signature` over.
let n := add(0x20, signatureLength)
pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
// forgefmt: disable-next-item
isValid := and(
and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(0x00), f),
// Whether the returndata is exactly 0x20 bytes (1 word) long.
eq(returndatasize(), 0x20)
),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
add(signatureLength, 0x64), // Length of calldata in memory.
0x00, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
}
}
/// @dev Returns whether `signature` is valid for `hash`
/// for an ERC1271 `signer` contract.
function isValidERC1271SignatureNowCalldata(
address signer,
bytes32 hash,
bytes calldata signature
) internal view returns (bool isValid) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata.
mstore(add(m, 0x44), signature.length)
// Copy the `signature` over.
calldatacopy(add(m, 0x64), signature.offset, signature.length)
// forgefmt: disable-next-item
isValid := and(
and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(0x00), f),
// Whether the returndata is exactly 0x20 bytes (1 word) long.
eq(returndatasize(), 0x20)
),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
add(signature.length, 0x64), // Length of calldata in memory.
0x00, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
}
}
/// @dev Returns whether the signature (`r`, `vs`) is valid for `hash`
/// for an ERC1271 `signer` contract.
function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
internal
view
returns (bool isValid)
{
uint8 v;
bytes32 s;
/// @solidity memory-safe-assembly
assembly {
s := shr(1, shl(1, vs))
v := add(shr(255, vs), 27)
}
isValid = isValidERC1271SignatureNow(signer, hash, v, r, s);
}
/// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash`
/// for an ERC1271 `signer` contract.
function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata.
mstore(add(m, 0x44), 65) // Length of the signature.
mstore(add(m, 0x64), r) // `r`.
mstore(add(m, 0x84), s) // `s`.
mstore8(add(m, 0xa4), v) // `v`.
// forgefmt: disable-next-item
isValid := and(
and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(0x00), f),
// Whether the returndata is exactly 0x20 bytes (1 word) long.
eq(returndatasize(), 0x20)
),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
0xa5, // Length of calldata in memory.
0x00, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EMPTY CALLDATA HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an empty calldata bytes.
function emptySignature() internal pure returns (bytes calldata signature) {
/// @solidity memory-safe-assembly
assembly {
signature.length := 0
}
}
}{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"solady/=lib/solady/",
"lib/forge-std:ds-test/=lib/forge-std/lib/ds-test/src/",
"lib/solady:ds-test/=lib/solady/lib/ds-test/src/",
"lib/solady:forge-std/=lib/solady/test/utils/forge-std/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"signer_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"Not101Holder","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_newSigner","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
60a060405234801561001057600080fd5b5060405161093a38038061093a83398101604081905261002f916100b1565b730164fb48891b891e748244b8ae931f2318b0c25b60805261005032610075565b600080546001600160a01b0319166001600160a01b03929092169190911790556100e1565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b6000602082840312156100c357600080fd5b81516001600160a01b03811681146100da57600080fd5b9392505050565b608051610837610103600039600081816102b5015261048c01526108376000f3fe6080604052600436106100915760003560e01c8063715018a611610059578063715018a6146101385780638da5cb5b14610140578063f04e283e1461016c578063f2fde38b1461017f578063fee81cf41461019257600080fd5b8063256929621461009657806338926b6d146100a05780634dd6c8de146100c057806354d1f13d146101105780636c19e78314610118575b600080fd5b61009e6101d3565b005b3480156100ac57600080fd5b5061009e6100bb3660046106d2565b610223565b3480156100cc57600080fd5b506100fb6100db36600461076a565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020015b60405180910390f35b61009e6104f8565b34801561012457600080fd5b5061009e610133366004610794565b610534565b61009e61055e565b34801561014c57600080fd5b50638b78c6d819546040516001600160a01b039091168152602001610107565b61009e61017a366004610794565b610572565b61009e61018d366004610794565b6105b2565b34801561019e57600080fd5b506101c56101ad366004610794565b63389a75e1600c908152600091909152602090205490565b604051908152602001610107565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b82606514158015610235575082606614155b156102535760405163c1ab6dc160e01b815260040160405180910390fd5b33600090815260026020908152604080832086845290915290205460ff161561028f57604051630c8d9eab60e31b815260040160405180910390fd5b8260661480156103295750604051627eeac760e11b8152336004820152606560248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169062fdd58e90604401602060405180830381865afa158015610303573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032791906107b6565b155b15610347576040516341d06bdd60e11b815260040160405180910390fd5b6040516bffffffffffffffffffffffff193360601b1660208201526034810184905260009060540160408051601f1981840301815282825280516020918201208383018352601c84527f19457468657265756d205369676e6564204d6573736167653a0a3332000000008483015291519193506000916103cb9184918691016107cf565b60408051601f1981840301815291905280516020909101206000549091506103fe906001600160a01b03168287876105d9565b61041b57604051638baa579f60e01b815260040160405180910390fd5b3360008181526002602090815260408083208a8452909152808220805460ff191660019081179091559051637921219560e11b81527352c45bab6d0827f44a973899666d9cd18fd90bcf6004820152602481019390935260448301899052606483015260a0608483015260a48201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f242432a9060c401600060405180830381600087803b1580156104d857600080fd5b505af11580156104ec573d6000803e3d6000fd5b50505050505050505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b61053c610679565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b610566610679565b6105706000610694565b565b61057a610679565b63389a75e1600c52806000526020600c2080544211156105a257636f5e88186000526004601cfd5b600090556105af81610694565b50565b6105ba610679565b8060601b6105d057637448fbae6000526004601cfd5b6105af81610694565b6001600160a01b039093169260008415610671576040516041830361063057848152604084013560001a6020820152604084604083013760208160808360015afa503d868251140215610630576001915050610671565b631626ba7e60e01b80825285600483015260406024830152836044830152838560648401376020600060648601848a5afa60203d1482600051141616925050505b949350505050565b638b78c6d819543314610570576382b429006000526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b6000806000604084860312156106e757600080fd5b83359250602084013567ffffffffffffffff8082111561070657600080fd5b818601915086601f83011261071a57600080fd5b81358181111561072957600080fd5b87602082850101111561073b57600080fd5b6020830194508093505050509250925092565b80356001600160a01b038116811461076557600080fd5b919050565b6000806040838503121561077d57600080fd5b6107868361074e565b946020939093013593505050565b6000602082840312156107a657600080fd5b6107af8261074e565b9392505050565b6000602082840312156107c857600080fd5b5051919050565b6000835160005b818110156107f057602081870181015185830152016107d6565b50919091019182525060200191905056fea2646970667358221220053fb821f602022dca19e44f4d73aab70e5def573cc5107c518c6d15ca590e3264736f6c634300081400330000000000000000000000003fcc99430694716e21dd5401872dbe84a0b4608e
Deployed Bytecode
0x6080604052600436106100915760003560e01c8063715018a611610059578063715018a6146101385780638da5cb5b14610140578063f04e283e1461016c578063f2fde38b1461017f578063fee81cf41461019257600080fd5b8063256929621461009657806338926b6d146100a05780634dd6c8de146100c057806354d1f13d146101105780636c19e78314610118575b600080fd5b61009e6101d3565b005b3480156100ac57600080fd5b5061009e6100bb3660046106d2565b610223565b3480156100cc57600080fd5b506100fb6100db36600461076a565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020015b60405180910390f35b61009e6104f8565b34801561012457600080fd5b5061009e610133366004610794565b610534565b61009e61055e565b34801561014c57600080fd5b50638b78c6d819546040516001600160a01b039091168152602001610107565b61009e61017a366004610794565b610572565b61009e61018d366004610794565b6105b2565b34801561019e57600080fd5b506101c56101ad366004610794565b63389a75e1600c908152600091909152602090205490565b604051908152602001610107565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b82606514158015610235575082606614155b156102535760405163c1ab6dc160e01b815260040160405180910390fd5b33600090815260026020908152604080832086845290915290205460ff161561028f57604051630c8d9eab60e31b815260040160405180910390fd5b8260661480156103295750604051627eeac760e11b8152336004820152606560248201527f0000000000000000000000000164fb48891b891e748244b8ae931f2318b0c25b6001600160a01b03169062fdd58e90604401602060405180830381865afa158015610303573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032791906107b6565b155b15610347576040516341d06bdd60e11b815260040160405180910390fd5b6040516bffffffffffffffffffffffff193360601b1660208201526034810184905260009060540160408051601f1981840301815282825280516020918201208383018352601c84527f19457468657265756d205369676e6564204d6573736167653a0a3332000000008483015291519193506000916103cb9184918691016107cf565b60408051601f1981840301815291905280516020909101206000549091506103fe906001600160a01b03168287876105d9565b61041b57604051638baa579f60e01b815260040160405180910390fd5b3360008181526002602090815260408083208a8452909152808220805460ff191660019081179091559051637921219560e11b81527352c45bab6d0827f44a973899666d9cd18fd90bcf6004820152602481019390935260448301899052606483015260a0608483015260a48201527f0000000000000000000000000164fb48891b891e748244b8ae931f2318b0c25b6001600160a01b03169063f242432a9060c401600060405180830381600087803b1580156104d857600080fd5b505af11580156104ec573d6000803e3d6000fd5b50505050505050505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b61053c610679565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b610566610679565b6105706000610694565b565b61057a610679565b63389a75e1600c52806000526020600c2080544211156105a257636f5e88186000526004601cfd5b600090556105af81610694565b50565b6105ba610679565b8060601b6105d057637448fbae6000526004601cfd5b6105af81610694565b6001600160a01b039093169260008415610671576040516041830361063057848152604084013560001a6020820152604084604083013760208160808360015afa503d868251140215610630576001915050610671565b631626ba7e60e01b80825285600483015260406024830152836044830152838560648401376020600060648601848a5afa60203d1482600051141616925050505b949350505050565b638b78c6d819543314610570576382b429006000526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b6000806000604084860312156106e757600080fd5b83359250602084013567ffffffffffffffff8082111561070657600080fd5b818601915086601f83011261071a57600080fd5b81358181111561072957600080fd5b87602082850101111561073b57600080fd5b6020830194508093505050509250925092565b80356001600160a01b038116811461076557600080fd5b919050565b6000806040838503121561077d57600080fd5b6107868361074e565b946020939093013593505050565b6000602082840312156107a657600080fd5b6107af8261074e565b9392505050565b6000602082840312156107c857600080fd5b5051919050565b6000835160005b818110156107f057602081870181015185830152016107d6565b50919091019182525060200191905056fea2646970667358221220053fb821f602022dca19e44f4d73aab70e5def573cc5107c518c6d15ca590e3264736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003fcc99430694716e21dd5401872dbe84a0b4608e
-----Decoded View---------------
Arg [0] : signer_ (address): 0x3FcC99430694716e21Dd5401872dBe84a0B4608e
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000003fcc99430694716e21dd5401872dbe84a0b4608e
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0.000001
Token Allocations
ETH
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $2,113.39 | 0.0000008 | $0.001691 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.