Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 3,457 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 24500544 | 9 days ago | IN | 0 ETH | 0.00000213 | ||||
| Batch Mint | 24486167 | 11 days ago | IN | 0.05 ETH | 0.00014443 | ||||
| Batch Mint | 24486091 | 11 days ago | IN | 0.01 ETH | 0.00000572 | ||||
| Batch Mint | 24486026 | 11 days ago | IN | 0.015 ETH | 0.00001447 | ||||
| Batch Mint | 24486026 | 11 days ago | IN | 0.015 ETH | 0.00001449 | ||||
| Batch Mint | 24486024 | 11 days ago | IN | 0.05 ETH | 0.00003337 | ||||
| Mint | 24486024 | 11 days ago | IN | 0.005 ETH | 0.00002185 | ||||
| Mint | 24486017 | 11 days ago | IN | 0.005 ETH | 0.00001846 | ||||
| Batch Mint | 24486017 | 11 days ago | IN | 0.01 ETH | 0.00002525 | ||||
| Batch Mint | 24486017 | 11 days ago | IN | 0.01 ETH | 0.00002525 | ||||
| Batch Mint | 24486017 | 11 days ago | IN | 0.01 ETH | 0.00002525 | ||||
| Batch Mint | 24486017 | 11 days ago | IN | 0.02 ETH | 0.00002781 | ||||
| Batch Mint | 24486017 | 11 days ago | IN | 0.05 ETH | 0.00003581 | ||||
| Batch Mint | 24486010 | 11 days ago | IN | 0.01 ETH | 0.00002738 | ||||
| Batch Mint | 24486010 | 11 days ago | IN | 0.01 ETH | 0.00002739 | ||||
| Batch Mint | 24486010 | 11 days ago | IN | 0.01 ETH | 0.00002739 | ||||
| Batch Mint | 24486010 | 11 days ago | IN | 0.02 ETH | 0.00003018 | ||||
| Batch Mint | 24486010 | 11 days ago | IN | 0.01 ETH | 0.00002833 | ||||
| Mint | 24486007 | 11 days ago | IN | 0.005 ETH | 0.00002732 | ||||
| Mint | 24486007 | 11 days ago | IN | 0.005 ETH | 0.00018842 | ||||
| Mint | 24486007 | 11 days ago | IN | 0.005 ETH | 0.00002732 | ||||
| Mint | 24486007 | 11 days ago | IN | 0.005 ETH | 0.00005765 | ||||
| Mint | 24486007 | 11 days ago | IN | 0.005 ETH | 0.00002732 | ||||
| Mint | 24486007 | 11 days ago | IN | 0.005 ETH | 0.00002733 | ||||
| Mint | 24486007 | 11 days ago | IN | 0.005 ETH | 0.00002733 |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
NormiesMinterV2
Compiler Version
v0.8.33+commit.64118f21
Optimization Enabled:
Yes with 10000 runs
Other Settings:
prague EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;
import { INormies } from "./interfaces/INormies.sol";
import { INormiesStorage } from "./interfaces/INormiesStorage.sol";
import { IDelegateRegistry } from "./interfaces/IDelegateRegistry.sol";
import { IDelegateRegistryV1 } from "./interfaces/IDelegateRegistryV1.sol";
import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Lifebuoy } from "solady/utils/Lifebuoy.sol";
/**
* @title NormiesMinterV2
* @author Normies by Serc (https://x.com/serc1n)
* @author Smart Contract by Yigit Duman (https://x.com/yigitduman)
* @dev Added Delegate.xyz v1 support
*/
contract NormiesMinterV2 is Ownable, Lifebuoy {
IDelegateRegistry public constant DELEGATE_REGISTRY_V2 =
IDelegateRegistry(0x00000000000000447e69651d841bD8D104Bed493);
IDelegateRegistryV1 public constant DELEGATE_REGISTRY_V1 =
IDelegateRegistryV1(0x00000000000076A84feF008CDAbe6409d2FE638B);
INormies public normies;
INormiesStorage public normiesStorage;
address public signer;
address public withdrawAddress;
uint256 public mintPrice;
uint256 public nextTokenId;
bool public paused;
/// @notice Number of tokens minted per wallet address
mapping(address => uint256) public mintCount;
error InvalidSignature();
error InsufficientPayment();
error MintLimitReached();
error NotMinterOrDelegate();
error WithdrawFailed();
error ArrayLengthMismatch();
error SignatureExpired();
error MintingPaused();
event Mint(address indexed minter, uint256 indexed tokenId, bytes imageData, bytes8 traits);
constructor(
INormies _normies,
INormiesStorage _normiesStorage,
address _signer,
uint256 _mintPrice,
address _withdrawAddress
) Ownable() Lifebuoy() {
normies = _normies;
normiesStorage = _normiesStorage;
signer = _signer;
mintPrice = _mintPrice;
withdrawAddress = _withdrawAddress;
}
/**
* @notice Mints a token with server-signed data. Supports delegate.xyz v2 and v1 for cold wallet delegation.
* @param minter The allowlisted wallet that receives the NFT (cold wallet if delegated)
* @param imageData The encrypted raw image data of the token (200 bytes)
* @param traits Encrypted packed bytes8 trait indices
* @param maxMints Maximum number of mints allowed for this wallet (phase-specific, signed by server)
* @param deadline Unix timestamp after which the signature is no longer valid
* @param signature Server signature over (imageData, traits, minter, maxMints, deadline)
*/
function mint(
address minter,
bytes calldata imageData,
bytes8 traits,
uint8 maxMints,
uint256 deadline,
bytes calldata signature
) external payable {
require(!paused, MintingPaused());
require(block.timestamp <= deadline, SignatureExpired());
require(msg.value >= mintPrice, InsufficientPayment());
require(mintCount[minter] < maxMints, MintLimitReached());
// Verify caller is minter or a delegate.xyz v2/v1 delegate
if (msg.sender != minter) {
require(
DELEGATE_REGISTRY_V2.checkDelegateForAll(msg.sender, minter, "")
|| DELEGATE_REGISTRY_V2.checkDelegateForContract(msg.sender, minter, address(normies), "")
|| DELEGATE_REGISTRY_V1.checkDelegateForAll(msg.sender, minter)
|| DELEGATE_REGISTRY_V1.checkDelegateForContract(msg.sender, minter, address(normies)),
NotMinterOrDelegate()
);
}
// Verify server signature over (imageData ++ traits ++ minter ++ maxMints ++ deadline)
// Uses EIP-191 prefix so backend can sign with standard signMessage
bytes32 messageHash = keccak256(abi.encodePacked(imageData, traits, minter, maxMints, deadline));
bytes32 ethSignedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash));
require(SignatureCheckerLib.isValidSignatureNow(signer, ethSignedHash, signature), InvalidSignature());
// Track mints
mintCount[minter]++;
// Mint the token
uint256 tokenId = nextTokenId++;
normies.mint(minter, tokenId);
// Set the token data
normiesStorage.setTokenRawImageData(tokenId, imageData);
normiesStorage.setTokenTraits(tokenId, traits);
emit Mint(minter, tokenId, imageData, traits);
}
/**
* @notice Mints multiple tokens in a single transaction with a single server-signed message.
* @param minter The whitelisted wallet that receives the NFTs (cold wallet if delegated)
* @param imageDataArray Array of encrypted raw image data (200 bytes each)
* @param traitsArray Array of encrypted packed bytes8 trait indices
* @param maxMints Maximum number of mints allowed for this wallet (phase-specific, signed by server)
* @param deadline Unix timestamp after which the signature is no longer valid
* @param signature Server signature over abi.encode(imageDataArray, traitsArray, minter, maxMints, deadline)
*/
function batchMint(
address minter,
bytes[] calldata imageDataArray,
bytes8[] calldata traitsArray,
uint8 maxMints,
uint256 deadline,
bytes calldata signature
) external payable {
require(!paused, MintingPaused());
require(block.timestamp <= deadline, SignatureExpired());
uint256 count = imageDataArray.length;
require(count == traitsArray.length, ArrayLengthMismatch());
require(msg.value >= mintPrice * count, InsufficientPayment());
require(mintCount[minter] + count <= maxMints, MintLimitReached());
// Verify caller is minter or a delegate.xyz v2/v1 delegate (once for the batch)
if (msg.sender != minter) {
require(
DELEGATE_REGISTRY_V2.checkDelegateForAll(msg.sender, minter, "")
|| DELEGATE_REGISTRY_V2.checkDelegateForContract(msg.sender, minter, address(normies), "")
|| DELEGATE_REGISTRY_V1.checkDelegateForAll(msg.sender, minter)
|| DELEGATE_REGISTRY_V1.checkDelegateForContract(msg.sender, minter, address(normies)),
NotMinterOrDelegate()
);
}
// Verify single server signature over all batch data
bytes32 messageHash = keccak256(abi.encode(imageDataArray, traitsArray, minter, maxMints, deadline));
bytes32 ethSignedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash));
require(SignatureCheckerLib.isValidSignatureNow(signer, ethSignedHash, signature), InvalidSignature());
for (uint256 i; i < count; ++i) {
mintCount[minter]++;
uint256 tokenId = nextTokenId++;
normies.mint(minter, tokenId);
normiesStorage.setTokenRawImageData(tokenId, imageDataArray[i]);
normiesStorage.setTokenTraits(tokenId, traitsArray[i]);
emit Mint(minter, tokenId, imageDataArray[i], traitsArray[i]);
}
}
function withdraw() external onlyOwner {
(bool success,) = withdrawAddress.call{ value: address(this).balance }("");
require(success, WithdrawFailed());
}
function setWithdrawAddress(address _withdrawAddress) external onlyOwner {
withdrawAddress = _withdrawAddress;
}
function setPaused(bool _paused) external onlyOwner {
paused = _paused;
}
function setMintPrice(uint256 _mintPrice) external onlyOwner {
mintPrice = _mintPrice;
}
function setSigner(address _signer) external onlyOwner {
signer = _signer;
}
function setNormies(address _normies) external onlyOwner {
normies = INormies(_normies);
}
function setNormiesStorage(address _normiesStorage) external onlyOwner {
normiesStorage = INormiesStorage(_normiesStorage);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;
interface INormies {
function mint(address to, uint256 tokenId) external;
function totalSupply() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;
interface INormiesStorage {
function getTokenRawImageData(uint256 tokenId) external view returns (bytes memory);
function getTokenTraits(uint256 tokenId) external view returns (bytes8);
function setTokenRawImageData(uint256 tokenId, bytes calldata imageData) external;
function setTokenTraits(uint256 tokenId, bytes8 traits) external;
function isTokenDataSet(uint256 tokenId) external view returns (bool);
function isRevealed() external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;
/// @notice Minimal interface for delegate.xyz v2 registry
/// @dev Full registry at 0x00000000000000447e69651d841bD8D104Bed493
interface IDelegateRegistry {
function checkDelegateForAll(address to, address from, bytes32 rights) external view returns (bool);
function checkDelegateForContract(
address to,
address from,
address contract_,
bytes32 rights
) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;
/// @notice Minimal interface for delegate.xyz v1 registry
/// @dev Full registry at 0x00000000000076A84feF008CDAbe6409d2FE638B
interface IDelegateRegistryV1 {
function checkDelegateForAll(address delegate, address vault) external view returns (bool);
function checkDelegateForContract(
address delegate,
address vault,
address contract_
) external view returns (bool);
}// 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:
/// - The signature checking functions use the ecrecover precompile (0x1).
/// - The `bytes memory signature` variants use the identity precompile (0x4)
/// to copy memory internally.
/// - Unlike ECDSA signatures, contract signatures are revocable.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
/// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
/// See: https://eips.ethereum.org/EIPS/eip-2098
/// This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT use signatures as unique identifiers:
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
/// EIP-712 also enables readable signing of typed data for better user safety.
/// 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.code.length == 0`, then validate with `ecrecover`, else
/// it will validate with ERC1271 on `signer`.
function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)
internal
view
returns (bool isValid)
{
if (signer == address(0)) return isValid;
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
for {} 1 {} {
if iszero(extcodesize(signer)) {
switch mload(signature)
case 64 {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
}
default { break }
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
let d := add(m, 0x24)
mstore(d, 0x40) // The offset of the `signature` in the calldata.
// Copy the `signature` over.
let n := add(0x20, mload(signature))
let copied := staticcall(gas(), 4, signature, n, add(m, 0x44), n)
isValid := staticcall(gas(), signer, m, add(returndatasize(), 0x44), d, 0x20)
isValid := and(eq(mload(d), f), and(isValid, copied))
break
}
}
}
/// @dev Returns whether `signature` is valid for `signer` and `hash`.
/// If `signer.code.length == 0`, then validate with `ecrecover`, else
/// it will validate with ERC1271 on `signer`.
function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)
internal
view
returns (bool isValid)
{
if (signer == address(0)) return isValid;
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
for {} 1 {} {
if iszero(extcodesize(signer)) {
switch signature.length
case 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`.
}
case 65 {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`.
}
default { break }
mstore(0x00, hash)
let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
let d := add(m, 0x24)
mstore(d, 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)
isValid := staticcall(gas(), signer, m, add(signature.length, 0x64), d, 0x20)
isValid := and(eq(mload(d), f), isValid)
break
}
}
}
/// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`.
/// If `signer.code.length == 0`, then validate with `ecrecover`, else
/// it will validate with ERC1271 on `signer`.
function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
internal
view
returns (bool isValid)
{
if (signer == address(0)) return isValid;
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
for {} 1 {} {
if iszero(extcodesize(signer)) {
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
let d := add(m, 0x24)
mstore(d, 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), shr(1, shl(1, vs))) // `s`.
mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`.
isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
isValid := and(eq(mload(d), f), isValid)
break
}
}
}
/// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`.
/// If `signer.code.length == 0`, then validate with `ecrecover`, else
/// it will validate with ERC1271 on `signer`.
function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (bool isValid)
{
if (signer == address(0)) return isValid;
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
for {} 1 {} {
if iszero(extcodesize(signer)) {
mstore(0x00, hash)
mstore(0x20, and(v, 0xff)) // `v`.
mstore(0x40, r) // `r`.
mstore(0x60, s) // `s`.
let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
let d := add(m, 0x24)
mstore(d, 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`.
isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
isValid := and(eq(mload(d), f), isValid)
break
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC1271 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Note: These ERC1271 operations do NOT have an ECDSA fallback.
/// @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 f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
let d := add(m, 0x24)
mstore(d, 0x40) // The offset of the `signature` in the calldata.
// Copy the `signature` over.
let n := add(0x20, mload(signature))
let copied := staticcall(gas(), 4, signature, n, add(m, 0x44), n)
isValid := staticcall(gas(), signer, m, add(returndatasize(), 0x44), d, 0x20)
isValid := and(eq(mload(d), f), and(isValid, copied))
}
}
/// @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)
let d := add(m, 0x24)
mstore(d, 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)
isValid := staticcall(gas(), signer, m, add(signature.length, 0x64), d, 0x20)
isValid := and(eq(mload(d), f), isValid)
}
}
/// @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)
{
/// @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)
let d := add(m, 0x24)
mstore(d, 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), shr(1, shl(1, vs))) // `s`.
mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`.
isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
isValid := and(eq(mload(d), f), isValid)
}
}
/// @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)
let d := add(m, 0x24)
mstore(d, 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`.
isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
isValid := and(eq(mload(d), f), isValid)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC6492 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Note: These ERC6492 operations now include an ECDSA fallback at the very end.
// The calldata variants are excluded for brevity.
/// @dev Returns whether `signature` is valid for `hash`.
/// If the signature is postfixed with the ERC6492 magic number, it will attempt to
/// deploy / prepare the `signer` smart account before doing a regular ERC1271 check.
/// Note: This function is NOT reentrancy safe.
/// The verifier must be deployed.
/// Otherwise, the function will return false if `signer` is not yet deployed / prepared.
/// See: https://gist.github.com/Vectorized/011d6becff6e0a73e42fe100f8d7ef04
/// With a dedicated verifier, this function is safe to use in contracts
/// that have been granted special permissions.
function isValidERC6492SignatureNowAllowSideEffects(
address signer,
bytes32 hash,
bytes memory signature
) internal returns (bool isValid) {
/// @solidity memory-safe-assembly
assembly {
function callIsValidSignature(signer_, hash_, signature_) -> _isValid {
let m_ := mload(0x40)
let f_ := shl(224, 0x1626ba7e)
mstore(m_, f_) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m_, 0x04), hash_)
let d_ := add(m_, 0x24)
mstore(d_, 0x40) // The offset of the `signature` in the calldata.
let n_ := add(0x20, mload(signature_))
let copied_ := staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_)
_isValid := staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20)
_isValid := and(eq(mload(d_), f_), and(_isValid, copied_))
}
let noCode := iszero(extcodesize(signer))
let n := mload(signature)
for {} 1 {} {
if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) {
if iszero(noCode) { isValid := callIsValidSignature(signer, hash, signature) }
break
}
if iszero(noCode) {
let o := add(signature, 0x20) // Signature bytes.
isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40))))
if isValid { break }
}
let m := mload(0x40)
mstore(m, signer)
mstore(add(m, 0x20), hash)
pop(
call(
gas(), // Remaining gas.
0x0000bc370E4DC924F427d84e2f4B9Ec81626ba7E, // Non-reverting verifier.
0, // Send zero ETH.
m, // Start of memory.
add(returndatasize(), 0x40), // Length of calldata in memory.
staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1.
0x00 // Length of returndata to write.
)
)
isValid := returndatasize()
break
}
// Do `ecrecover` fallback if `noCode && !isValid`.
for {} gt(noCode, isValid) {} {
switch n
case 64 {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
}
default { break }
let m := mload(0x40)
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/// @dev Returns whether `signature` is valid for `hash`.
/// If the signature is postfixed with the ERC6492 magic number, it will attempt
/// to use a reverting verifier to deploy / prepare the `signer` smart account
/// and do a `isValidSignature` check via the reverting verifier.
/// Note: This function is reentrancy safe.
/// The reverting verifier must be deployed.
/// Otherwise, the function will return false if `signer` is not yet deployed / prepared.
/// See: https://gist.github.com/Vectorized/846a474c855eee9e441506676800a9ad
function isValidERC6492SignatureNow(address signer, bytes32 hash, bytes memory signature)
internal
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
function callIsValidSignature(signer_, hash_, signature_) -> _isValid {
let m_ := mload(0x40)
let f_ := shl(224, 0x1626ba7e)
mstore(m_, f_) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m_, 0x04), hash_)
let d_ := add(m_, 0x24)
mstore(d_, 0x40) // The offset of the `signature` in the calldata.
let n_ := add(0x20, mload(signature_))
let copied_ := staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_)
_isValid := staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20)
_isValid := and(eq(mload(d_), f_), and(_isValid, copied_))
}
let noCode := iszero(extcodesize(signer))
let n := mload(signature)
for {} 1 {} {
if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) {
if iszero(noCode) { isValid := callIsValidSignature(signer, hash, signature) }
break
}
if iszero(noCode) {
let o := add(signature, 0x20) // Signature bytes.
isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40))))
if isValid { break }
}
let m := mload(0x40)
mstore(m, signer)
mstore(add(m, 0x20), hash)
let willBeZeroIfRevertingVerifierExists :=
call(
gas(), // Remaining gas.
0x00007bd799e4A591FeA53f8A8a3E9f931626Ba7e, // Reverting verifier.
0, // Send zero ETH.
m, // Start of memory.
add(returndatasize(), 0x40), // Length of calldata in memory.
staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1.
0x00 // Length of returndata to write.
)
isValid := gt(returndatasize(), willBeZeroIfRevertingVerifierExists)
break
}
// Do `ecrecover` fallback if `noCode && !isValid`.
for {} gt(noCode, isValid) {} {
switch n
case 64 {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
}
default { break }
let m := mload(0x40)
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @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 {
mstore(0x20, hash) // Store into scratch space for keccak256.
mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
}
}
/// @dev Returns an Ethereum Signed Message, created from `s`.
/// 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.
/// Note: Supports lengths of `s` up to 999999 bytes.
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let sLength := mload(s)
let o := 0x20
mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
mstore(0x00, 0x00)
// Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
for { let temp := sLength } 1 {} {
o := sub(o, 1)
mstore8(o, add(48, mod(temp, 10)))
temp := div(temp, 10)
if iszero(temp) { break }
}
let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
// Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
mstore(s, sLength) // Restore the length.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* 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
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Class that allows for rescue of ETH, ERC20, ERC721 tokens.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Lifebuoy.sol)
///
/// @dev This contract is created to mitigate the following disasters:
/// - Careless user sends tokens to the wrong chain or wrong contract.
/// - Careless dev deploys a contract without a withdraw function in attempt to rescue
/// careless user's tokens, due to deployment nonce mismatch caused by
/// script misfire / misconfiguration.
/// - Careless dev forgets to add a withdraw function to a NFT sale contract.
///
/// Note: if you are deploying via a untrusted `tx.origin`,
/// you MUST override `_lifebuoyDefaultDeployer` to return a trusted address.
///
/// For best safety:
/// - For non-escrow contracts, inherit Lifebuoy as much as possible,
/// and leave it unlocked.
/// - For escrow contracts, lock access as tight as possible,
/// as soon as possible. Or simply don't inherit Lifebuoy.
/// Escrow: Your contract is designed to hold ETH, ERC20s, ERC721s
/// (e.g. liquidity pools).
///
/// All rescue and rescue authorization functions require either:
/// - Caller is the deployer
/// AND the contract is not a proxy
/// AND `rescueLocked() & _LIFEBUOY_DEPLOYER_ACCESS_LOCK == 0`.
/// - Caller is `owner()`
/// AND `rescueLocked() & _LIFEBUOY_OWNER_ACCESS_LOCK == 0`.
///
/// The choice of using bit flags to represent locked statuses is for
/// efficiency, flexibility, convenience.
///
/// This contract is optimized with a priority on minimal bytecode size,
/// as the methods are not intended to be called often.
contract Lifebuoy {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to rescue or lock the rescue function.
error RescueUnauthorizedOrLocked();
/// @dev The rescue operation has failed due to a failed transfer.
error RescueTransferFailed();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* LOCK FLAGS CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// These flags are kept internal to avoid bloating up the function dispatch.
// You can just copy paste this into your own code.
/// @dev Flag to denote that the deployer's access is locked. (1)
uint256 internal constant _LIFEBUOY_DEPLOYER_ACCESS_LOCK = 1 << 0;
/// @dev Flag to denote that the `owner()`'s access is locked. (2)
uint256 internal constant _LIFEBUOY_OWNER_ACCESS_LOCK = 1 << 1;
/// @dev Flag to denote that the `lockRescue` function is locked. (4)
uint256 internal constant _LIFEBUOY_LOCK_RESCUE_LOCK = 1 << 2;
/// @dev Flag to denote that the `rescueETH` function is locked. (8)
uint256 internal constant _LIFEBUOY_RESCUE_ETH_LOCK = 1 << 3;
/// @dev Flag to denote that the `rescueERC20` function is locked. (16)
uint256 internal constant _LIFEBUOY_RESCUE_ERC20_LOCK = 1 << 4;
/// @dev Flag to denote that the `rescueERC721` function is locked. (32)
uint256 internal constant _LIFEBUOY_RESCUE_ERC721_LOCK = 1 << 5;
/// @dev Flag to denote that the `rescueERC1155` function is locked. (64)
uint256 internal constant _LIFEBUOY_RESCUE_ERC1155_LOCK = 1 << 6;
/// @dev Flag to denote that the `rescueERC6909` function is locked. (128)
uint256 internal constant _LIFEBUOY_RESCUE_ERC6909_LOCK = 1 << 7;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* IMMUTABLES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev For checking that the caller is the deployer and
/// that the context is not a delegatecall
/// (so that the implementation deployer cannot drain proxies).
bytes32 internal immutable _lifebuoyDeployerHash;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The rescue locked flags slot is given by:
/// `bytes32(~uint256(uint32(bytes4(keccak256("_RESCUE_LOCKED_FLAGS_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.
bytes32 internal constant _RESCUE_LOCKED_FLAGS_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTRUCTOR */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
constructor() payable {
bytes32 hash;
uint256 deployer = uint160(_lifebuoyDefaultDeployer());
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, address())
mstore(0x20, deployer)
hash := keccak256(0x00, 0x40)
}
_lifebuoyDeployerHash = hash;
}
/// @dev Returns `tx.origin` by default. Override to return another address if needed.
///
/// Note: If you are deploying via a untrusted `tx.origin` (e.g. ERC4337 bundler)
/// you MUST override this function to return a trusted address.
function _lifebuoyDefaultDeployer() internal view virtual returns (address) {
// I know about EIP7645, and I will stop it if it gets traction.
// Worse case, I will add an `ecrecover` method. But not today.
return tx.origin;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RESCUE OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Sends `amount` (in wei) ETH from the current contract to `to`.
/// Reverts upon failure.
function rescueETH(address to, uint256 amount)
public
payable
virtual
onlyRescuer(_LIFEBUOY_RESCUE_ETH_LOCK)
{
/// @solidity memory-safe-assembly
assembly {
if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0x7ec62e76) // `RescueTransferFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
/// Does not check for existence of token or return data. Reverts upon failure.
function rescueERC20(address token, address to, uint256 amount)
public
payable
virtual
onlyRescuer(_LIFEBUOY_RESCUE_ERC20_LOCK)
{
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
// `RescueTransferFailed()` and `transfer(address,uint256)`.
mstore(0x00, shl(96, 0x7ec62e76a9059cbb))
if iszero(call(gas(), token, callvalue(), 0x10, 0x44, codesize(), 0x00)) {
revert(0x0c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sends `id` of ERC721 `token` from the current contract to `to`.
/// Does not check for existence of token or return data. Reverts upon failure.
function rescueERC721(address token, address to, uint256 id)
public
payable
virtual
onlyRescuer(_LIFEBUOY_RESCUE_ERC721_LOCK)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, id) // Store the `id` argument.
mstore(0x40, shr(96, shl(96, to))) // Store the `to` argument.
mstore(0x20, address()) // Store the `from` argument.
// `RescueTransferFailed()` and `transferFrom(address,address,uint256)`.
mstore(0x00, 0x7ec62e7623b872dd)
if iszero(call(gas(), token, callvalue(), 0x1c, 0x64, codesize(), 0x00)) {
revert(0x18, 0x04)
}
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Sends `amount` of `id` of ERC1155 `token` from the current contract to `to`.
/// Does not check for existence of token or return data. Reverts upon failure.
function rescueERC1155(
address token,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) public payable virtual onlyRescuer(_LIFEBUOY_RESCUE_ERC1155_LOCK) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
// `RescueTransferFailed()` and `safeTransferFrom(address,address,uint256,uint256,bytes)`.
mstore(m, 0x7ec62e76f242432a)
mstore(add(0x20, m), address()) // Store the `from` argument.
mstore(add(0x40, m), shr(96, shl(96, to))) // Store the `to` argument.
mstore(add(0x60, m), id) // Store the `id` argument.
mstore(add(0x80, m), amount) // Store the `amount` argument.
mstore(add(0xa0, m), 0xa0) // Store the offset to `data`.
mstore(add(0xc0, m), data.length)
calldatacopy(add(m, 0xe0), data.offset, data.length)
// forgefmt: disable-next-item
if iszero(
call(gas(), token, callvalue(), add(m, 0x1c), add(0xc4, data.length), codesize(), 0x00)
) { revert(add(m, 0x18), 0x04) }
}
}
/// @dev Sends `amount` of `id` of ERC6909 `token` from the current contract to `to`.
/// Does not check for existence of token or return data. Reverts upon failure.
function rescueERC6909(address token, address to, uint256 id, uint256 amount)
public
payable
virtual
onlyRescuer(_LIFEBUOY_RESCUE_ERC6909_LOCK)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, id) // Store the `id` argument.
mstore(0x54, amount) // Store the `amount` argument.
// `RescueTransferFailed()` and `transfer(address,uint256,uint256)`.
mstore(0x00, shl(96, 0x7ec62e76095bcdb6))
if iszero(call(gas(), token, callvalue(), 0x10, 0x64, codesize(), 0x00)) {
revert(0x0c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RESCUE AUTHORIZATION OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the flags denoting whether access to rescue functions
/// (including `lockRescue`) is locked.
function rescueLocked() public view virtual returns (uint256 locks) {
/// @solidity memory-safe-assembly
assembly {
locks := sload(_RESCUE_LOCKED_FLAGS_SLOT)
}
}
/// @dev Locks (i.e. permanently removes) access to rescue functions (including `lockRescue`).
function lockRescue(uint256 locksToSet)
public
payable
virtual
onlyRescuer(_LIFEBUOY_LOCK_RESCUE_LOCK)
{
_lockRescue(locksToSet);
}
/// @dev Internal function to set the lock flags without going through access control.
function _lockRescue(uint256 locksToSet) internal virtual {
/// @solidity memory-safe-assembly
assembly {
let s := _RESCUE_LOCKED_FLAGS_SLOT
sstore(s, or(sload(s), locksToSet))
}
}
/// @dev Requires that the rescue function being guarded is:
/// 1. Not locked, AND
/// 2. Called by either:
/// (a) The `owner()`, OR
/// (b) The deployer (if not via a delegate call and deployer is an EOA).
function _checkRescuer(uint256 modeLock) internal view virtual {
uint256 locks = rescueLocked();
bytes32 h = _lifebuoyDeployerHash;
/// @solidity memory-safe-assembly
assembly {
for {} 1 {} {
// If the `modeLock` flag is true, set all bits in `locks` to true.
locks := or(sub(0, iszero(iszero(and(modeLock, locks)))), locks)
// Caller is the deployer
// AND the contract is not a proxy
// AND `locks & _LIFEBUOY_DEPLOYER_ACCESS_LOCK` is false.
mstore(0x20, caller())
mstore(and(locks, _LIFEBUOY_DEPLOYER_ACCESS_LOCK), address())
if eq(keccak256(0x00, 0x40), h) { break }
// If the caller is `owner()`
// AND `locks & _LIFEBUOY_OWNER_ACCESS_LOCK` is false.
mstore(0x08, 0x8da5cb5b0a0362e0) // `owner()` and `RescueUnauthorizedOrLocked()`.
if and( // The arguments of `and` are evaluated from right to left.
lt(
and(locks, _LIFEBUOY_OWNER_ACCESS_LOCK),
and(gt(returndatasize(), 0x1f), eq(mload(0x00), caller()))
),
staticcall(gas(), address(), 0x20, 0x04, 0x00, 0x20)
) { break }
revert(0x24, 0x04)
}
}
}
/// @dev Modifier that calls `_checkRescuer()` at the start of the function.
modifier onlyRescuer(uint256 modeLock) virtual {
_checkRescuer(modeLock);
_;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}{
"remappings": [
"@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
"@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/",
"forge-std/=node_modules/forge-std/",
"@manifoldxyz/creator-core-solidity/=node_modules/@manifoldxyz/creator-core-solidity/",
"solady/=node_modules/solady/src/",
"@ensdomains/=node_modules/@ensdomains/",
"@limitbreak/=node_modules/@limitbreak/",
"erc721a/=node_modules/erc721a/"
],
"optimizer": {
"enabled": true,
"runs": 10000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "prague",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract INormies","name":"_normies","type":"address"},{"internalType":"contract INormiesStorage","name":"_normiesStorage","type":"address"},{"internalType":"address","name":"_signer","type":"address"},{"internalType":"uint256","name":"_mintPrice","type":"uint256"},{"internalType":"address","name":"_withdrawAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[],"name":"InsufficientPayment","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"MintLimitReached","type":"error"},{"inputs":[],"name":"MintingPaused","type":"error"},{"inputs":[],"name":"NotMinterOrDelegate","type":"error"},{"inputs":[],"name":"RescueTransferFailed","type":"error"},{"inputs":[],"name":"RescueUnauthorizedOrLocked","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"imageData","type":"bytes"},{"indexed":false,"internalType":"bytes8","name":"traits","type":"bytes8"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"DELEGATE_REGISTRY_V1","outputs":[{"internalType":"contract IDelegateRegistryV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGATE_REGISTRY_V2","outputs":[{"internalType":"contract IDelegateRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"bytes[]","name":"imageDataArray","type":"bytes[]"},{"internalType":"bytes8[]","name":"traitsArray","type":"bytes8[]"},{"internalType":"uint8","name":"maxMints","type":"uint8"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"batchMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"locksToSet","type":"uint256"}],"name":"lockRescue","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"bytes","name":"imageData","type":"bytes"},{"internalType":"bytes8","name":"traits","type":"bytes8"},{"internalType":"uint8","name":"maxMints","type":"uint8"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"normies","outputs":[{"internalType":"contract INormies","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"normiesStorage","outputs":[{"internalType":"contract INormiesStorage","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"rescueERC1155","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueERC20","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueERC6909","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"rescueERC721","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"rescueLocked","outputs":[{"internalType":"uint256","name":"locks","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_normies","type":"address"}],"name":"setNormies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_normiesStorage","type":"address"}],"name":"setNormiesStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_withdrawAddress","type":"address"}],"name":"setWithdrawAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a060405234801561000f575f5ffd5b5060405161265c38038061265c83398101604081905261002e91610103565b6100373361009d565b305f9081523260205260409020608052600180546001600160a01b039687166001600160a01b031991821617909155600280549587169582169590951790945560038054938616938516939093179092556005556004805491909316911617905561016a565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610100575f5ffd5b50565b5f5f5f5f5f60a08688031215610117575f5ffd5b8551610122816100ec565b6020870151909550610133816100ec565b6040870151909450610144816100ec565b60608701516080880151919450925061015c816100ec565b809150509295509295909350565b6080516124da6101825f395f611a7d01526124da5ff3fe6080604052600436106101ba575f3560e01c8063715018a6116100f25780639573e1c611610092578063dffc5ed311610062578063dffc5ed3146104d0578063ed9ec888146104ef578063f2fde38b1461051a578063f4a0a52814610539575f5ffd5b80639573e1c61461046a5780639865eb941461048b578063b2118a8d1461049e578063c5ff9155146104b1575f5ffd5b80637f1f0c67116100cd5780637f1f0c67146104085780638191ad911461041b5780638da5cb5b1461042e5780639311ca8914610457575f5ffd5b8063715018a6146103cc57806375794a3c146103e05780637df325e1146103f5575f5ffd5b806335facc851161015d5780634839053c116101385780634839053c146103435780635c975abb1461036f5780636817c76c146103985780636c19e783146103ad575f5ffd5b806335facc85146102e45780633ab1a494146103105780633ccfd60b1461032f575f5ffd5b806316c38b3c1161019857806316c38b3c1461023c5780631ede96201461025b578063238ac9331461027b5780633571ae8f146102a7575f5ffd5b8063099a04e5146101be5780631135c5d2146101d35780631581b600146101e6575b5f5ffd5b6101d16101cc366004611d0b565b610558565b005b6101d16101e1366004611d78565b610581565b3480156101f1575f5ffd5b506004546102129073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610247575f5ffd5b506101d1610256366004611df8565b6105f0565b348015610266575f5ffd5b506102126c447e69651d841bd8d104bed49381565b348015610286575f5ffd5b506003546102129073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b2575f5ffd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b545b604051908152602001610233565b3480156102ef575f5ffd5b506001546102129073ffffffffffffffffffffffffffffffffffffffff1681565b34801561031b575f5ffd5b506101d161032a366004611e13565b610629565b34801561033a575f5ffd5b506101d1610678565b34801561034e575f5ffd5b506002546102129073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037a575f5ffd5b506007546103889060ff1681565b6040519015158152602001610233565b3480156103a3575f5ffd5b506102d660055481565b3480156103b8575f5ffd5b506101d16103c7366004611e13565b61071a565b3480156103d7575f5ffd5b506101d1610769565b3480156103eb575f5ffd5b506102d660065481565b6101d1610403366004611e2c565b61077c565b6101d1610416366004611e66565b6107c8565b6101d1610429366004611ebc565b6107fe565b348015610439575f5ffd5b505f5473ffffffffffffffffffffffffffffffffffffffff16610212565b6101d1610465366004611f66565b610fac565b348015610475575f5ffd5b506102126d76a84fef008cdabe6409d2fe638b81565b6101d1610499366004611fe6565b610ff6565b6101d16104ac366004611e2c565b6118ad565b3480156104bc575f5ffd5b506101d16104cb366004611e13565b6118ec565b3480156104db575f5ffd5b506101d16104ea366004611e13565b61193b565b3480156104fa575f5ffd5b506102d6610509366004611e13565b60086020525f908152604090205481565b348015610525575f5ffd5b506101d1610534366004611e13565b61198a565b348015610544575f5ffd5b506101d1610553366004611e66565b611a43565b600861056381611a50565b5f385f3885875af161057c57637ec62e765f526004601cfd5b505050565b604061058c81611a50565b604051677ec62e76f242432a81523081602001528660601b60601c816040015285816060015284816080015260a08160a00152828160c00152828460e08301375f388460c401601c8401348c5af16105e657600460188201fd5b5050505050505050565b6105f8611aeb565b600780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610631611aeb565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610680611aeb565b6004546040515f9173ffffffffffffffffffffffffffffffffffffffff169047908381818185875af1925050503d805f81146106d7576040519150601f19603f3d011682016040523d82523d5f602084013e6106dc565b606091505b5050905080610717576040517f750b219c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b610722611aeb565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610771611aeb565b61077a5f611b6b565b565b602061078781611a50565b604051826060528360601b60601c60405230602052677ec62e7623b872dd5f525f386064601c34895af16107bb5760046018fd5b5f60605260405250505050565b60046107d381611a50565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b8054831790555050565b60075460ff161561083b576040517feb56075600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82421115610875576040517f0819bdcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005543410156108b1576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff88165f9081526008602052604090205460ff851611610911576040517f303b682f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff891614610c18576040517fe839bd5300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff891660248201525f60448201526c447e69651d841bd8d104bed4939063e839bd5390606401602060405180830381865afa1580156109af573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109d391906120b1565b80610a8a57506001546040517f8988eea900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808b16602483015290911660448201525f60648201526c447e69651d841bd8d104bed49390638988eea990608401602060405180830381865afa158015610a66573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8a91906120b1565b80610b3057506040517f9c395bc200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff891660248201526d76a84fef008cdabe6409d2fe638b90639c395bc290604401602060405180830381865afa158015610b0c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3091906120b1565b80610be257506001546040517f90c9a2d000000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808b16602483015290911660448201526d76a84fef008cdabe6409d2fe638b906390c9a2d090606401602060405180830381865afa158015610bbe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be291906120b1565b610c18576040517f0e1db23000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8787878b8888604051602001610c34969594939291906120cc565b6040516020818303038152906040528051906020012090505f81604051602001610c8a91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600354601f88018390048302850183019093528684529350610d169273ffffffffffffffffffffffffffffffffffffffff90921691849188908890819084018382808284375f92019190915250611bdf92505050565b610d4c576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a165f908152600860205260408120805491610d7c83612190565b9091555050600680545f9182610d9183612190565b909155506001546040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e81166004830152602482018490529293509116906340c10f19906044015f604051808303815f87803b158015610e08575f5ffd5b505af1158015610e1a573d5f5f3e3d5ffd5b50506002546040517fdb1d29ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116925063db1d29ab9150610e789084908e908e9060040161220e565b5f604051808303815f87803b158015610e8f575f5ffd5b505af1158015610ea1573d5f5f3e3d5ffd5b50506002546040517fe2fc13e0000000000000000000000000000000000000000000000000000000008152600481018590527fffffffffffffffff0000000000000000000000000000000000000000000000008c16602482015273ffffffffffffffffffffffffffffffffffffffff909116925063e2fc13e091506044015f604051808303815f87803b158015610f36575f5ffd5b505af1158015610f48573d5f5f3e3d5ffd5b50505050808b73ffffffffffffffffffffffffffffffffffffffff167f45982c0325b1855b2321d28e3e38f9c4caaa2cdc247e038e3213fb7144f0a3808c8c8c604051610f9793929190612230565b60405180910390a35050505050505050505050565b6080610fb781611a50565b604051846014528360345282605452677ec62e76095bcdb660601b5f525f3860646010348a5af1610fe8576004600cfd5b5f6060526040525050505050565b60075460ff1615611033576040517feb56075600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8242111561106d576040517f0819bdcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868581146110a7576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806005546110b59190612275565b3410156110ee576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a165f9081526008602052604090205460ff861690611123908390612292565b111561115b576040517f303b682f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8b1614611462576040517fe839bd5300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8b1660248201525f60448201526c447e69651d841bd8d104bed4939063e839bd5390606401602060405180830381865afa1580156111f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061121d91906120b1565b806112d457506001546040517f8988eea900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808d16602483015290911660448201525f60648201526c447e69651d841bd8d104bed49390638988eea990608401602060405180830381865afa1580156112b0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d491906120b1565b8061137a57506040517f9c395bc200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8b1660248201526d76a84fef008cdabe6409d2fe638b90639c395bc290604401602060405180830381865afa158015611356573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061137a91906120b1565b8061142c57506001546040517f90c9a2d000000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808d16602483015290911660448201526d76a84fef008cdabe6409d2fe638b906390c9a2d090606401602060405180830381865afa158015611408573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061142c91906120b1565b611462576040517f0e1db23000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f898989898e8a8a6040516020016114809796959493929190612304565b6040516020818303038152906040528051906020012090505f816040516020016114d691907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600354601f890183900483028501830190935287845293506115629273ffffffffffffffffffffffffffffffffffffffff90921691849189908990819084018382808284375f92019190915250611bdf92505050565b611598576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8381101561189e5773ffffffffffffffffffffffffffffffffffffffff8d165f9081526008602052604081208054916115d283612190565b9091555050600680545f91826115e783612190565b91905055905060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f198f836040518363ffffffff1660e01b815260040161166a92919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b5f604051808303815f87803b158015611681575f5ffd5b505af1158015611693573d5f5f3e3d5ffd5b505060025473ffffffffffffffffffffffffffffffffffffffff16915063db1d29ab9050828f8f868181106116ca576116ca612426565b90506020028101906116dc9190612453565b6040518463ffffffff1660e01b81526004016116fa9392919061220e565b5f604051808303815f87803b158015611711575f5ffd5b505af1158015611723573d5f5f3e3d5ffd5b505060025473ffffffffffffffffffffffffffffffffffffffff16915063e2fc13e09050828d8d8681811061175a5761175a612426565b905060200201602081019061176f91906124b4565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092527fffffffffffffffff0000000000000000000000000000000000000000000000001660248201526044015f604051808303815f87803b1580156117e4575f5ffd5b505af11580156117f6573d5f5f3e3d5ffd5b50505050808e73ffffffffffffffffffffffffffffffffffffffff167f45982c0325b1855b2321d28e3e38f9c4caaa2cdc247e038e3213fb7144f0a3808f8f8681811061184557611845612426565b90506020028101906118579190612453565b8f8f8881811061186957611869612426565b905060200201602081019061187e91906124b4565b60405161188d93929190612230565b60405180910390a35060010161159a565b50505050505050505050505050565b60106118b881611a50565b8260145281603452677ec62e76a9059cbb60601b5f525f386044601034885af16118e2576004600cfd5b5f60345250505050565b6118f4611aeb565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611943611aeb565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611992611aeb565b73ffffffffffffffffffffffffffffffffffffffff8116611a3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61071781611b6b565b611a4b611aeb565b600555565b5f611a797fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b5490565b90507f00000000000000000000000000000000000000000000000000000000000000008182841615155f03179150336020523060018316528060405f20031561057c57678da5cb5b0a0362e060085260205f60046020305afa335f5114601f3d111660028416101661057c5760046024fd5b5f5473ffffffffffffffffffffffffffffffffffffffff16331461077a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611a31565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f73ffffffffffffffffffffffffffffffffffffffff841615611cdc57604051843b611c9a57825160408114611c1d5760418114611c575750611cda565b604084015160ff81901c601b016020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16606052611c6a565b60608401515f1a60205260408401516060525b50835f5260208301516040526020600160805f60015afa5180861860601b3d119250505f60605280604052611cda565b631626ba7e60e01b808252846004830152602482016040815284516020018060448501828860045afa905060208260443d01868b5afa9151911691141691505b505b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611d06575f5ffd5b919050565b5f5f60408385031215611d1c575f5ffd5b611d2583611ce3565b946020939093013593505050565b5f5f83601f840112611d43575f5ffd5b50813567ffffffffffffffff811115611d5a575f5ffd5b602083019150836020828501011115611d71575f5ffd5b9250929050565b5f5f5f5f5f5f60a08789031215611d8d575f5ffd5b611d9687611ce3565b9550611da460208801611ce3565b94506040870135935060608701359250608087013567ffffffffffffffff811115611dcd575f5ffd5b611dd989828a01611d33565b979a9699509497509295939492505050565b8015158114610717575f5ffd5b5f60208284031215611e08575f5ffd5b8135611cdc81611deb565b5f60208284031215611e23575f5ffd5b611cdc82611ce3565b5f5f5f60608486031215611e3e575f5ffd5b611e4784611ce3565b9250611e5560208501611ce3565b929592945050506040919091013590565b5f60208284031215611e76575f5ffd5b5035919050565b80357fffffffffffffffff00000000000000000000000000000000000000000000000081168114611d06575f5ffd5b803560ff81168114611d06575f5ffd5b5f5f5f5f5f5f5f5f60c0898b031215611ed3575f5ffd5b611edc89611ce3565b9750602089013567ffffffffffffffff811115611ef7575f5ffd5b611f038b828c01611d33565b9098509650611f16905060408a01611e7d565b9450611f2460608a01611eac565b93506080890135925060a089013567ffffffffffffffff811115611f46575f5ffd5b611f528b828c01611d33565b999c989b5096995094979396929594505050565b5f5f5f5f60808587031215611f79575f5ffd5b611f8285611ce3565b9350611f9060208601611ce3565b93969395505050506040820135916060013590565b5f5f83601f840112611fb5575f5ffd5b50813567ffffffffffffffff811115611fcc575f5ffd5b6020830191508360208260051b8501011115611d71575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611ffe575f5ffd5b6120078a611ce3565b985060208a013567ffffffffffffffff811115612022575f5ffd5b61202e8c828d01611fa5565b90995097505060408a013567ffffffffffffffff81111561204d575f5ffd5b6120598c828d01611fa5565b909750955061206c905060608b01611eac565b935060808a0135925060a08a013567ffffffffffffffff81111561208e575f5ffd5b61209a8c828d01611d33565b915080935050809150509295985092959850929598565b5f602082840312156120c1575f5ffd5b8151611cdc81611deb565b858782377fffffffffffffffff000000000000000000000000000000000000000000000000949094169390940192835260609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016600883015260f81b7fff0000000000000000000000000000000000000000000000000000000000000016601c820152601d810191909152603d01919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121c0576121c0612163565b5060010190565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201525f6122276040830184866121c7565b95945050505050565b604081525f6122436040830185876121c7565b90507fffffffffffffffff00000000000000000000000000000000000000000000000083166020830152949350505050565b808202811582820484141761228c5761228c612163565b92915050565b8082018082111561228c5761228c612163565b8183526020830192505f815f5b848110156122fa577fffffffffffffffff0000000000000000000000000000000000000000000000006122e483611e7d565b16865260209586019591909101906001016122b2565b5093949350505050565b60a080825281018790525f60c0600589901b830181019083018a837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe136839003015b8c8210156123d2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408786030184528235818112612382575f5ffd5b8e0160208101903567ffffffffffffffff81111561239e575f5ffd5b8036038213156123ac575f5ffd5b6123b78782846121c7565b96505050602083019250602084019350600182019150612346565b5050505082810360208401526123e981888a6122a5565b91505061240e604083018673ffffffffffffffffffffffffffffffffffffffff169052565b60ff9390931660608201526080015295945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612486575f5ffd5b83018035915067ffffffffffffffff8211156124a0575f5ffd5b602001915036819003821315611d71575f5ffd5b5f602082840312156124c4575f5ffd5b611cdc82611e7d56fea164736f6c6343000821000a0000000000000000000000009eb6e2025b64f340691e424b7fe7022ffde124380000000000000000000000001b976baf51cf51f0e369c070d47fbc47a706e602000000000000000000000000d7ed3c08666c429f9a442f8ed15549c63847c5a50000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000007a85ac4db0042241451f6184d91d6736070a5fce
Deployed Bytecode
0x6080604052600436106101ba575f3560e01c8063715018a6116100f25780639573e1c611610092578063dffc5ed311610062578063dffc5ed3146104d0578063ed9ec888146104ef578063f2fde38b1461051a578063f4a0a52814610539575f5ffd5b80639573e1c61461046a5780639865eb941461048b578063b2118a8d1461049e578063c5ff9155146104b1575f5ffd5b80637f1f0c67116100cd5780637f1f0c67146104085780638191ad911461041b5780638da5cb5b1461042e5780639311ca8914610457575f5ffd5b8063715018a6146103cc57806375794a3c146103e05780637df325e1146103f5575f5ffd5b806335facc851161015d5780634839053c116101385780634839053c146103435780635c975abb1461036f5780636817c76c146103985780636c19e783146103ad575f5ffd5b806335facc85146102e45780633ab1a494146103105780633ccfd60b1461032f575f5ffd5b806316c38b3c1161019857806316c38b3c1461023c5780631ede96201461025b578063238ac9331461027b5780633571ae8f146102a7575f5ffd5b8063099a04e5146101be5780631135c5d2146101d35780631581b600146101e6575b5f5ffd5b6101d16101cc366004611d0b565b610558565b005b6101d16101e1366004611d78565b610581565b3480156101f1575f5ffd5b506004546102129073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610247575f5ffd5b506101d1610256366004611df8565b6105f0565b348015610266575f5ffd5b506102126c447e69651d841bd8d104bed49381565b348015610286575f5ffd5b506003546102129073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b2575f5ffd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b545b604051908152602001610233565b3480156102ef575f5ffd5b506001546102129073ffffffffffffffffffffffffffffffffffffffff1681565b34801561031b575f5ffd5b506101d161032a366004611e13565b610629565b34801561033a575f5ffd5b506101d1610678565b34801561034e575f5ffd5b506002546102129073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037a575f5ffd5b506007546103889060ff1681565b6040519015158152602001610233565b3480156103a3575f5ffd5b506102d660055481565b3480156103b8575f5ffd5b506101d16103c7366004611e13565b61071a565b3480156103d7575f5ffd5b506101d1610769565b3480156103eb575f5ffd5b506102d660065481565b6101d1610403366004611e2c565b61077c565b6101d1610416366004611e66565b6107c8565b6101d1610429366004611ebc565b6107fe565b348015610439575f5ffd5b505f5473ffffffffffffffffffffffffffffffffffffffff16610212565b6101d1610465366004611f66565b610fac565b348015610475575f5ffd5b506102126d76a84fef008cdabe6409d2fe638b81565b6101d1610499366004611fe6565b610ff6565b6101d16104ac366004611e2c565b6118ad565b3480156104bc575f5ffd5b506101d16104cb366004611e13565b6118ec565b3480156104db575f5ffd5b506101d16104ea366004611e13565b61193b565b3480156104fa575f5ffd5b506102d6610509366004611e13565b60086020525f908152604090205481565b348015610525575f5ffd5b506101d1610534366004611e13565b61198a565b348015610544575f5ffd5b506101d1610553366004611e66565b611a43565b600861056381611a50565b5f385f3885875af161057c57637ec62e765f526004601cfd5b505050565b604061058c81611a50565b604051677ec62e76f242432a81523081602001528660601b60601c816040015285816060015284816080015260a08160a00152828160c00152828460e08301375f388460c401601c8401348c5af16105e657600460188201fd5b5050505050505050565b6105f8611aeb565b600780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610631611aeb565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610680611aeb565b6004546040515f9173ffffffffffffffffffffffffffffffffffffffff169047908381818185875af1925050503d805f81146106d7576040519150601f19603f3d011682016040523d82523d5f602084013e6106dc565b606091505b5050905080610717576040517f750b219c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b610722611aeb565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610771611aeb565b61077a5f611b6b565b565b602061078781611a50565b604051826060528360601b60601c60405230602052677ec62e7623b872dd5f525f386064601c34895af16107bb5760046018fd5b5f60605260405250505050565b60046107d381611a50565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b8054831790555050565b60075460ff161561083b576040517feb56075600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82421115610875576040517f0819bdcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005543410156108b1576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff88165f9081526008602052604090205460ff851611610911576040517f303b682f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff891614610c18576040517fe839bd5300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff891660248201525f60448201526c447e69651d841bd8d104bed4939063e839bd5390606401602060405180830381865afa1580156109af573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109d391906120b1565b80610a8a57506001546040517f8988eea900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808b16602483015290911660448201525f60648201526c447e69651d841bd8d104bed49390638988eea990608401602060405180830381865afa158015610a66573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8a91906120b1565b80610b3057506040517f9c395bc200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff891660248201526d76a84fef008cdabe6409d2fe638b90639c395bc290604401602060405180830381865afa158015610b0c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3091906120b1565b80610be257506001546040517f90c9a2d000000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808b16602483015290911660448201526d76a84fef008cdabe6409d2fe638b906390c9a2d090606401602060405180830381865afa158015610bbe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be291906120b1565b610c18576040517f0e1db23000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8787878b8888604051602001610c34969594939291906120cc565b6040516020818303038152906040528051906020012090505f81604051602001610c8a91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600354601f88018390048302850183019093528684529350610d169273ffffffffffffffffffffffffffffffffffffffff90921691849188908890819084018382808284375f92019190915250611bdf92505050565b610d4c576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a165f908152600860205260408120805491610d7c83612190565b9091555050600680545f9182610d9183612190565b909155506001546040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e81166004830152602482018490529293509116906340c10f19906044015f604051808303815f87803b158015610e08575f5ffd5b505af1158015610e1a573d5f5f3e3d5ffd5b50506002546040517fdb1d29ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116925063db1d29ab9150610e789084908e908e9060040161220e565b5f604051808303815f87803b158015610e8f575f5ffd5b505af1158015610ea1573d5f5f3e3d5ffd5b50506002546040517fe2fc13e0000000000000000000000000000000000000000000000000000000008152600481018590527fffffffffffffffff0000000000000000000000000000000000000000000000008c16602482015273ffffffffffffffffffffffffffffffffffffffff909116925063e2fc13e091506044015f604051808303815f87803b158015610f36575f5ffd5b505af1158015610f48573d5f5f3e3d5ffd5b50505050808b73ffffffffffffffffffffffffffffffffffffffff167f45982c0325b1855b2321d28e3e38f9c4caaa2cdc247e038e3213fb7144f0a3808c8c8c604051610f9793929190612230565b60405180910390a35050505050505050505050565b6080610fb781611a50565b604051846014528360345282605452677ec62e76095bcdb660601b5f525f3860646010348a5af1610fe8576004600cfd5b5f6060526040525050505050565b60075460ff1615611033576040517feb56075600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8242111561106d576040517f0819bdcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868581146110a7576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806005546110b59190612275565b3410156110ee576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a165f9081526008602052604090205460ff861690611123908390612292565b111561115b576040517f303b682f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8b1614611462576040517fe839bd5300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8b1660248201525f60448201526c447e69651d841bd8d104bed4939063e839bd5390606401602060405180830381865afa1580156111f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061121d91906120b1565b806112d457506001546040517f8988eea900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808d16602483015290911660448201525f60648201526c447e69651d841bd8d104bed49390638988eea990608401602060405180830381865afa1580156112b0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d491906120b1565b8061137a57506040517f9c395bc200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8b1660248201526d76a84fef008cdabe6409d2fe638b90639c395bc290604401602060405180830381865afa158015611356573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061137a91906120b1565b8061142c57506001546040517f90c9a2d000000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808d16602483015290911660448201526d76a84fef008cdabe6409d2fe638b906390c9a2d090606401602060405180830381865afa158015611408573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061142c91906120b1565b611462576040517f0e1db23000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f898989898e8a8a6040516020016114809796959493929190612304565b6040516020818303038152906040528051906020012090505f816040516020016114d691907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600354601f890183900483028501830190935287845293506115629273ffffffffffffffffffffffffffffffffffffffff90921691849189908990819084018382808284375f92019190915250611bdf92505050565b611598576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8381101561189e5773ffffffffffffffffffffffffffffffffffffffff8d165f9081526008602052604081208054916115d283612190565b9091555050600680545f91826115e783612190565b91905055905060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f198f836040518363ffffffff1660e01b815260040161166a92919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b5f604051808303815f87803b158015611681575f5ffd5b505af1158015611693573d5f5f3e3d5ffd5b505060025473ffffffffffffffffffffffffffffffffffffffff16915063db1d29ab9050828f8f868181106116ca576116ca612426565b90506020028101906116dc9190612453565b6040518463ffffffff1660e01b81526004016116fa9392919061220e565b5f604051808303815f87803b158015611711575f5ffd5b505af1158015611723573d5f5f3e3d5ffd5b505060025473ffffffffffffffffffffffffffffffffffffffff16915063e2fc13e09050828d8d8681811061175a5761175a612426565b905060200201602081019061176f91906124b4565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092527fffffffffffffffff0000000000000000000000000000000000000000000000001660248201526044015f604051808303815f87803b1580156117e4575f5ffd5b505af11580156117f6573d5f5f3e3d5ffd5b50505050808e73ffffffffffffffffffffffffffffffffffffffff167f45982c0325b1855b2321d28e3e38f9c4caaa2cdc247e038e3213fb7144f0a3808f8f8681811061184557611845612426565b90506020028101906118579190612453565b8f8f8881811061186957611869612426565b905060200201602081019061187e91906124b4565b60405161188d93929190612230565b60405180910390a35060010161159a565b50505050505050505050505050565b60106118b881611a50565b8260145281603452677ec62e76a9059cbb60601b5f525f386044601034885af16118e2576004600cfd5b5f60345250505050565b6118f4611aeb565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611943611aeb565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611992611aeb565b73ffffffffffffffffffffffffffffffffffffffff8116611a3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61071781611b6b565b611a4b611aeb565b600555565b5f611a797fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b5490565b90507fd067ddabe98d0cdeb5eb001459828040105577dd0d99fd2bf668e130d894818f8182841615155f03179150336020523060018316528060405f20031561057c57678da5cb5b0a0362e060085260205f60046020305afa335f5114601f3d111660028416101661057c5760046024fd5b5f5473ffffffffffffffffffffffffffffffffffffffff16331461077a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611a31565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f73ffffffffffffffffffffffffffffffffffffffff841615611cdc57604051843b611c9a57825160408114611c1d5760418114611c575750611cda565b604084015160ff81901c601b016020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16606052611c6a565b60608401515f1a60205260408401516060525b50835f5260208301516040526020600160805f60015afa5180861860601b3d119250505f60605280604052611cda565b631626ba7e60e01b808252846004830152602482016040815284516020018060448501828860045afa905060208260443d01868b5afa9151911691141691505b505b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611d06575f5ffd5b919050565b5f5f60408385031215611d1c575f5ffd5b611d2583611ce3565b946020939093013593505050565b5f5f83601f840112611d43575f5ffd5b50813567ffffffffffffffff811115611d5a575f5ffd5b602083019150836020828501011115611d71575f5ffd5b9250929050565b5f5f5f5f5f5f60a08789031215611d8d575f5ffd5b611d9687611ce3565b9550611da460208801611ce3565b94506040870135935060608701359250608087013567ffffffffffffffff811115611dcd575f5ffd5b611dd989828a01611d33565b979a9699509497509295939492505050565b8015158114610717575f5ffd5b5f60208284031215611e08575f5ffd5b8135611cdc81611deb565b5f60208284031215611e23575f5ffd5b611cdc82611ce3565b5f5f5f60608486031215611e3e575f5ffd5b611e4784611ce3565b9250611e5560208501611ce3565b929592945050506040919091013590565b5f60208284031215611e76575f5ffd5b5035919050565b80357fffffffffffffffff00000000000000000000000000000000000000000000000081168114611d06575f5ffd5b803560ff81168114611d06575f5ffd5b5f5f5f5f5f5f5f5f60c0898b031215611ed3575f5ffd5b611edc89611ce3565b9750602089013567ffffffffffffffff811115611ef7575f5ffd5b611f038b828c01611d33565b9098509650611f16905060408a01611e7d565b9450611f2460608a01611eac565b93506080890135925060a089013567ffffffffffffffff811115611f46575f5ffd5b611f528b828c01611d33565b999c989b5096995094979396929594505050565b5f5f5f5f60808587031215611f79575f5ffd5b611f8285611ce3565b9350611f9060208601611ce3565b93969395505050506040820135916060013590565b5f5f83601f840112611fb5575f5ffd5b50813567ffffffffffffffff811115611fcc575f5ffd5b6020830191508360208260051b8501011115611d71575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611ffe575f5ffd5b6120078a611ce3565b985060208a013567ffffffffffffffff811115612022575f5ffd5b61202e8c828d01611fa5565b90995097505060408a013567ffffffffffffffff81111561204d575f5ffd5b6120598c828d01611fa5565b909750955061206c905060608b01611eac565b935060808a0135925060a08a013567ffffffffffffffff81111561208e575f5ffd5b61209a8c828d01611d33565b915080935050809150509295985092959850929598565b5f602082840312156120c1575f5ffd5b8151611cdc81611deb565b858782377fffffffffffffffff000000000000000000000000000000000000000000000000949094169390940192835260609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016600883015260f81b7fff0000000000000000000000000000000000000000000000000000000000000016601c820152601d810191909152603d01919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121c0576121c0612163565b5060010190565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201525f6122276040830184866121c7565b95945050505050565b604081525f6122436040830185876121c7565b90507fffffffffffffffff00000000000000000000000000000000000000000000000083166020830152949350505050565b808202811582820484141761228c5761228c612163565b92915050565b8082018082111561228c5761228c612163565b8183526020830192505f815f5b848110156122fa577fffffffffffffffff0000000000000000000000000000000000000000000000006122e483611e7d565b16865260209586019591909101906001016122b2565b5093949350505050565b60a080825281018790525f60c0600589901b830181019083018a837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe136839003015b8c8210156123d2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408786030184528235818112612382575f5ffd5b8e0160208101903567ffffffffffffffff81111561239e575f5ffd5b8036038213156123ac575f5ffd5b6123b78782846121c7565b96505050602083019250602084019350600182019150612346565b5050505082810360208401526123e981888a6122a5565b91505061240e604083018673ffffffffffffffffffffffffffffffffffffffff169052565b60ff9390931660608201526080015295945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612486575f5ffd5b83018035915067ffffffffffffffff8211156124a0575f5ffd5b602001915036819003821315611d71575f5ffd5b5f602082840312156124c4575f5ffd5b611cdc82611e7d56fea164736f6c6343000821000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009eb6e2025b64f340691e424b7fe7022ffde124380000000000000000000000001b976baf51cf51f0e369c070d47fbc47a706e602000000000000000000000000d7ed3c08666c429f9a442f8ed15549c63847c5a50000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000007a85ac4db0042241451f6184d91d6736070a5fce
-----Decoded View---------------
Arg [0] : _normies (address): 0x9Eb6E2025B64f340691e424b7fe7022fFDE12438
Arg [1] : _normiesStorage (address): 0x1B976bAf51cF51F0e369C070d47FBc47A706e602
Arg [2] : _signer (address): 0xD7eD3c08666C429F9a442F8eD15549C63847C5a5
Arg [3] : _mintPrice (uint256): 5000000000000000
Arg [4] : _withdrawAddress (address): 0x7a85AC4dB0042241451f6184d91D6736070a5FCE
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000009eb6e2025b64f340691e424b7fe7022ffde12438
Arg [1] : 0000000000000000000000001b976baf51cf51f0e369c070d47fbc47a706e602
Arg [2] : 000000000000000000000000d7ed3c08666c429f9a442f8ed15549c63847c5a5
Arg [3] : 0000000000000000000000000000000000000000000000000011c37937e08000
Arg [4] : 0000000000000000000000007a85ac4db0042241451f6184d91d6736070a5fce
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0.000001
Token Allocations
APE
100.00%
Multichain Portfolio | 33 Chains
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.