Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Contract Deployer
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 115 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Create | 21262515 | 466 days ago | IN | 0 ETH | 0.0033176 | ||||
| Create | 21234906 | 470 days ago | IN | 0 ETH | 0.00483678 | ||||
| Create | 21183635 | 477 days ago | IN | 0 ETH | 0.01569172 | ||||
| Create | 21183593 | 477 days ago | IN | 0 ETH | 0.0164765 | ||||
| Create | 21183488 | 477 days ago | IN | 0 ETH | 0.01875013 | ||||
| Create | 21017914 | 500 days ago | IN | 0 ETH | 0.00332593 | ||||
| Create | 21012370 | 501 days ago | IN | 0 ETH | 0.00431428 | ||||
| Create | 20709444 | 543 days ago | IN | 0 ETH | 0.00070942 | ||||
| Create | 20640643 | 553 days ago | IN | 0 ETH | 0.00068838 | ||||
| Create | 20627362 | 555 days ago | IN | 0 ETH | 0.00081077 | ||||
| Create | 20622604 | 555 days ago | IN | 0 ETH | 0.00108301 | ||||
| Create | 20619883 | 556 days ago | IN | 0 ETH | 0.00084685 | ||||
| Create | 20619829 | 556 days ago | IN | 0 ETH | 0.0009084 | ||||
| Create | 20619755 | 556 days ago | IN | 0 ETH | 0.00072183 | ||||
| Create | 20619702 | 556 days ago | IN | 0 ETH | 0.00068855 | ||||
| Create | 20619601 | 556 days ago | IN | 0 ETH | 0.00102334 | ||||
| Create | 20619443 | 556 days ago | IN | 0 ETH | 0.0007169 | ||||
| Create | 20584974 | 560 days ago | IN | 0 ETH | 0.00133455 | ||||
| Create | 20542167 | 566 days ago | IN | 0 ETH | 0.00295709 | ||||
| Create | 20453329 | 579 days ago | IN | 0 ETH | 0.00063235 | ||||
| Create | 20452377 | 579 days ago | IN | 0 ETH | 0.00080544 | ||||
| Create | 20414729 | 584 days ago | IN | 0 ETH | 0.00147133 | ||||
| Create | 20371214 | 590 days ago | IN | 0 ETH | 0.00375897 | ||||
| Create | 20328964 | 596 days ago | IN | 0 ETH | 0.00260068 | ||||
| Create | 20281425 | 603 days ago | IN | 0 ETH | 0.00107724 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x3d602d80 | 21262515 | 466 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 21234906 | 470 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 21183635 | 477 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 21183593 | 477 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 21183488 | 477 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 21017914 | 500 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 21012370 | 501 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20709444 | 543 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20640643 | 553 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20627362 | 555 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20622604 | 555 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20619883 | 556 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20619829 | 556 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20619755 | 556 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20619702 | 556 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20619601 | 556 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20619443 | 556 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20584974 | 560 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20542167 | 566 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20453329 | 579 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20452377 | 579 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20414729 | 584 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20371214 | 590 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20328964 | 596 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20281425 | 603 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
SoundCreatorV2
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
import { Clones } from "openzeppelin/proxy/Clones.sol";
import { ReentrancyGuard } from "openzeppelin/security/ReentrancyGuard.sol";
import { ISoundCreatorV2 } from "./interfaces/ISoundCreatorV2.sol";
import { LibMulticaller } from "multicaller/LibMulticaller.sol";
import { Ownable } from "solady/auth/Ownable.sol";
import { EIP712 } from "solady/utils/EIP712.sol";
import { LibZip } from "solady/utils/LibZip.sol";
import { LibBitmap } from "solady/utils/LibBitmap.sol";
import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";
import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol";
/**
* @title SoundCreatorV1
* @notice A factory that deploys minimal proxies of SoundEditions.
* @dev The proxies are OpenZeppelin's Clones implementation of https://eips.ethereum.org/EIPS/eip-1167
*/
contract SoundCreatorV2 is ISoundCreatorV2, EIP712, ReentrancyGuard {
using LibBitmap for LibBitmap.Bitmap;
// =============================================================
// CONSTANTS
// =============================================================
/**
* @dev For EIP-712 signature digest calculation.
*/
bytes32 public constant SOUND_CREATION_TYPEHASH =
// prettier-ignore
keccak256(
"SoundCreation("
"address implementation,"
"address owner,"
"bytes32 salt,"
"bytes initData,"
"address[] contracts,"
"bytes[] data,"
"uint256 nonce"
")"
);
/**
* @dev For EIP-712 signature digest calculation.
*/
bytes32 public constant DOMAIN_TYPEHASH = _DOMAIN_TYPEHASH;
// =============================================================
// STORAGE
// =============================================================
/**
* @dev For storing the invalidated nonces.
*/
mapping(address => LibBitmap.Bitmap) internal _invalidatedNonces;
// =============================================================
// PUBLIC / EXTERNAL WRITE FUNCTIONS
// =============================================================
/**
* @inheritdoc ISoundCreatorV2
*/
function create(SoundCreation calldata c) external nonReentrant returns (address edition, bytes[] memory results) {
if (c.owner != LibMulticaller.sender()) revert Unauthorized();
(edition, results) = _create(c);
}
/**
* @inheritdoc ISoundCreatorV2
*/
function createWithSignature(SoundCreation calldata creation, bytes calldata signature)
external
nonReentrant
returns (address soundEdition, bytes[] memory results)
{
(soundEdition, results) = _createWithSignature(creation, signature);
}
/**
* @inheritdoc ISoundCreatorV2
*/
function mint(
address minter,
bytes calldata mintData,
address refundTo
) external payable nonReentrant {
_mint(minter, mintData, refundTo);
}
/**
* @inheritdoc ISoundCreatorV2
*/
function createWithSignatureAndMint(
SoundCreation calldata c,
bytes calldata signature,
address minter,
bytes calldata mintData,
address refundTo
) external payable nonReentrant returns (address edition, bytes[] memory results) {
// We will skip the `createWithSignature` if the SoundEdtion already exists.
(, bool exists) = soundEditionAddress(c.implementation, c.owner, c.salt);
if (!exists) (edition, results) = _createWithSignature(c, signature);
_mint(minter, mintData, refundTo);
}
/**
* @inheritdoc ISoundCreatorV2
*/
function invalidateNonces(uint256[] calldata nonces) external {
unchecked {
address sender = LibMulticaller.sender();
LibBitmap.Bitmap storage s = _invalidatedNonces[sender];
for (uint256 i; i != nonces.length; ++i) {
s.set(nonces[i]);
}
emit NoncesInvalidated(sender, nonces);
}
}
/**
* @dev For compressed calldata calling.
*/
fallback() external payable {
LibZip.cdFallback();
}
/**
* @dev For compressed calldata calling.
*/
receive() external payable {
LibZip.cdFallback();
}
// =============================================================
// PUBLIC / EXTERNAL VIEW FUNCTIONS
// =============================================================
/**
* @inheritdoc ISoundCreatorV2
*/
function soundEditionAddress(
address implementation,
address owner,
bytes32 salt
) public view returns (address addr, bool exists) {
addr = Clones.predictDeterministicAddress(implementation, _saltedSalt(owner, salt), address(this));
exists = addr.code.length != 0;
}
/**
* @inheritdoc ISoundCreatorV2
*/
function isValidSignature(SoundCreation calldata c, bytes calldata signature) public view returns (bool) {
return
// Whether the signature is correctly signed. Will revert if recovery fails.
SignatureCheckerLib.isValidSignatureNowCalldata(c.owner, computeDigest(c), signature) &&
// And whether the creation's nonce is not invalidated.
!_invalidatedNonces[c.owner].get(c.nonce);
}
/**
* @inheritdoc ISoundCreatorV2
*/
function computeDigest(SoundCreation calldata c) public view returns (bytes32) {
bytes32 encodedDataHash;
unchecked {
bytes[] calldata cData = c.data;
uint256 n = cData.length;
bytes32[] memory encodedData = new bytes32[](n);
for (uint256 i = 0; i != n; ++i) {
encodedData[i] = keccak256(cData[i]);
}
encodedDataHash = keccak256(abi.encodePacked(encodedData));
}
return
_hashTypedData(
keccak256(
abi.encode(
SOUND_CREATION_TYPEHASH,
c.implementation, // address
c.owner, // address
c.salt, // bytes32
keccak256(c.initData), // bytes
keccak256(abi.encodePacked(c.contracts)), // address[]
encodedDataHash, // bytes[]
c.nonce // uint256
)
)
);
}
/**
* @inheritdoc ISoundCreatorV2
*/
function noncesInvalidated(address signer, uint256[] calldata nonces) external view returns (bool[] memory result) {
unchecked {
result = new bool[](nonces.length);
LibBitmap.Bitmap storage s = _invalidatedNonces[signer];
for (uint256 i; i != nonces.length; ++i) {
result[i] = s.get(nonces[i]);
}
}
}
// EIP712 parameters.
/**
* @inheritdoc ISoundCreatorV2
*/
function name() external pure returns (string memory name_) {
(name_, ) = _domainNameAndVersion();
}
/**
* @inheritdoc ISoundCreatorV2
*/
function version() external pure returns (string memory version_) {
(, version_) = _domainNameAndVersion();
}
/**
* @inheritdoc ISoundCreatorV2
*/
function domainSeparator() external view returns (bytes32 separator) {
separator = _domainSeparator();
}
// =============================================================
// INTERNAL / PRIVATE HELPERS
// =============================================================
/**
* @dev Override for EIP-712.
* @return name_ The EIP-712 name.
* @return version_ The EIP-712 version.
*/
function _domainNameAndVersion()
internal
pure
virtual
override
returns (string memory name_, string memory version_)
{
name_ = "SoundCreator";
version_ = "2";
}
/**
* @dev Call the `contracts` in order with `data`.
* @param contracts The addresses of the contracts.
* @param data The `abi.encodeWithSelector` calldata for each of the contracts.
* @return results The results of calling the contracts.
*/
function _callContracts(address[] calldata contracts, bytes[] calldata data)
internal
returns (bytes[] memory results)
{
if (contracts.length != data.length) revert ArrayLengthsMismatch();
assembly {
// Grab the free memory pointer.
// We will use the free memory to construct the `results` array,
// and also as a temporary space for the calldata.
results := mload(0x40)
// Set `results.length` to be equal to `data.length`.
mstore(results, data.length)
// Skip the first word, which is used to store the length
let resultsOffsets := add(results, 0x20)
// Compute the location of the last calldata offset in `data`.
// `shl(5, n)` is a gas-saving shorthand for `mul(0x20, n)`.
let dataOffsetsEnd := add(data.offset, shl(5, data.length))
// This is the start of the unused free memory.
// We use it to temporarily store the calldata to call the contracts.
let m := add(resultsOffsets, shl(5, data.length))
// Loop through `contacts` and `data` together.
// prettier-ignore
for { let i := data.offset } iszero(eq(i, dataOffsetsEnd)) { i := add(i, 0x20) } {
// Location of `bytes[i]` in calldata.
let o := add(data.offset, calldataload(i))
// Copy `bytes[i]` from calldata to the free memory.
calldatacopy(
m, // Start of the unused free memory.
add(o, 0x20), // Location of starting byte of `data[i]` in calldata.
calldataload(o) // The length of the `bytes[i]`.
)
// Grab `contracts[i]` from the calldata.
// As `contracts` is the same length as `data`,
// `sub(i, data.offset)` gives the relative offset to apply to
// `contracts.offset` for `contracts[i]` to match `data[i]`.
let c := calldataload(add(contracts.offset, sub(i, data.offset)))
// Call the contract, and revert if the call fails.
if iszero(
call(
gas(), // Gas remaining.
c, // `contracts[i]`.
0, // `msg.value` of the call: 0 ETH.
m, // Start of the copy of `bytes[i]` in memory.
calldataload(o), // The length of the `bytes[i]`.
0x00, // Start of output. Not used.
0x00 // Size of output. Not used.
)
) {
// Bubble up the revert if the call reverts.
returndatacopy(0x00, 0x00, returndatasize())
revert(0x00, returndatasize())
}
// Append the current `m` into `resultsOffsets`.
mstore(resultsOffsets, m)
resultsOffsets := add(resultsOffsets, 0x20)
// Append the `returndatasize()` to `results`.
mstore(m, returndatasize())
// Append the return data to `results`.
returndatacopy(add(m, 0x20), 0x00, returndatasize())
// Advance `m` by `returndatasize() + 0x20`,
// rounded up to the next multiple of 32.
// `0x3f = 32 + 31`. The mask is `type(uint64).max & ~31`,
// which is big enough for all purposes (see memory expansion costs).
m := and(add(add(m, returndatasize()), 0x3f), 0xffffffffffffffe0)
}
// Allocate the memory for `results` by updating the free memory pointer.
mstore(0x40, m)
}
}
/**
* @dev Returns the salted salt.
* To prevent griefing and accidental collisions from clients that don't
* generate their salt properly.
* @param owner The initial owner of the SoundEdition.
* @param salt The salt, generated on the client side.
* @return result The computed value.
*/
function _saltedSalt(address owner, bytes32 salt) internal view returns (bytes32 result) {
assembly {
mstore(0x20, owner)
mstore(0x0c, chainid())
mstore(0x00, salt)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Creates a new SoundEdtion via `c.soundCreator`, and a new split contract if needed.
* @param c The SoundCreation struct.
* @return edition The address of the created SoundEdition contract.
* @return results The results of calling the contracts.
* Use `abi.decode` to decode them.
*/
function _create(SoundCreation calldata c) internal returns (address edition, bytes[] memory results) {
if (c.implementation == address(0)) revert ImplementationAddressCantBeZero();
// Create Sound Edition proxy.
edition = payable(Clones.cloneDeterministic(c.implementation, _saltedSalt(c.owner, c.salt)));
bytes calldata initData = c.initData;
// Initialize proxy.
assembly {
// Grab the free memory pointer.
let m := mload(0x40)
// Copy the `initData` to the free memory.
calldatacopy(m, initData.offset, initData.length)
// Call the initializer, and revert if the call fails.
if iszero(
call(
gas(), // Gas remaining.
edition, // Address of the edition.
0, // `msg.value` of the call: 0 ETH.
m, // Start of input.
initData.length, // Length of input.
0x00, // Start of output. Not used.
0x00 // Size of output. Not used.
)
) {
// Bubble up the revert if the call reverts.
returndatacopy(0x00, 0x00, returndatasize())
revert(0x00, returndatasize())
}
}
results = _callContracts(c.contracts, c.data);
Ownable(edition).transferOwnership(c.owner);
emit Created(c.implementation, edition, c.owner, c.initData, c.contracts, c.data, results);
}
/**
* @dev Creates a SoundEdition on behalf of `c.owner`.
* @param c The SoundCreation struct.
* @param signature The signature for the SoundCreation struct, by `c.owner`.
* @return edition The address of the created SoundEdition contract.
* @return results The results of calling the contracts.
* Use `abi.decode` to decode them.
*/
function _createWithSignature(SoundCreation calldata c, bytes calldata signature)
internal
returns (address edition, bytes[] memory results)
{
if (!isValidSignature(c, signature)) revert InvalidSignature();
(edition, results) = _create(c);
// Invalidate the nonce and emit the event.
_invalidatedNonces[c.owner].set(c.nonce);
uint256[] memory nonces = new uint256[](1);
nonces[0] = c.nonce;
emit NoncesInvalidated(c.owner, nonces);
}
/**
* @dev Calls `minter` with `mintData`.
* After which, refunds any remaining ETH balance in the adapter contract.
* If `minter` is the zero address, the function is a no-op.
* @param minter The minter contract to call, SAM included.
* @param mintData The abi encoded calldata to the minter contract.
* @param refundTo The address to transfer any remaining ETH in the contract after the calls.
* If `address(0)`, remaining ETH will NOT be refunded.
* If `address(1)`, remaining ETH will be refunded to `msg.sender`.
* If anything else, remaining ETH will be refunded to `refundTo`.
*/
function _mint(
address minter,
bytes calldata mintData,
address refundTo
) internal {
if (minter == address(0)) return;
assembly {
// Grab the free memory pointer.
let m := mload(0x40)
// Copy the `mintData` into the free memory.
calldatacopy(m, mintData.offset, mintData.length)
// Make a call to `minter` with `mintData`, reverting if the call fails.
if iszero(
call(
gas(), // Gas remaining.
minter, // Address of the minter.
callvalue(), // All the ETH sent to this function.
m, // Start of the `mintData` in memory.
mintData.length, // Length of `mintData`.
0x00, // We'll use returndatasize instead.
0x00 // We'll use returndatasize instead.
)
) {
// If the call fails, bubble up the revert.
returndatacopy(0x00, 0x00, returndatasize())
revert(0x00, returndatasize())
}
}
if (refundTo != address(0)) {
// Refund any ETH in this contract. In the unlikely case where ETH is
// mistakenly sent to this contract, it will be combined into the refund.
if (address(this).balance != 0) {
if (refundTo == address(1)) refundTo = msg.sender;
SafeTransferLib.forceSafeTransferAllETH(refundTo);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/Clones.sol)
pragma solidity ^0.8.0;
/**
* @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
* deploying minimal proxy contracts, also known as "clones".
*
* > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
* > a minimal bytecode implementation that delegates all calls to a known, fixed address.
*
* The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
* (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
* deterministic method.
*
* _Available since v3.4._
*/
library Clones {
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create opcode, which should never revert.
*/
function clone(address implementation) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create(0, ptr, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy
* the clone. Using the same `implementation` and `salt` multiple time will revert, since
* the clones cannot be deployed twice at the same address.
*/
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create2(0, ptr, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
mstore(add(ptr, 0x38), shl(0x60, deployer))
mstore(add(ptr, 0x4c), salt)
mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
predicted := keccak256(add(ptr, 0x37), 0x55)
}
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(address implementation, bytes32 salt)
internal
view
returns (address predicted)
{
return predictDeterministicAddress(implementation, salt, address(this));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
/**
* @title ISoundCreatorV2
* @notice The interface for the Sound edition factory.
*/
interface ISoundCreatorV2 {
// =============================================================
// STRUCTS
// =============================================================
/**
* @dev A struct containing all the data required for creating a SoundEdition
* and setting up all other relevant contracts.
*/
struct SoundCreation {
// The address of the SoundEdition implementation.
address implementation;
// The initial owner of the deployed SoundEdition.
address owner;
// The salt used for deploying the SoundEdition via the SoundCreator factory.
bytes32 salt;
// The calldata passed to the SoundEdition to initialize it.
bytes initData;
// Array of contracts to call after initializing the SoundEdition.
address[] contracts;
// Array of abi encoded calldata to pass to each entry in `contracts`.
bytes[] data;
// The current nonce used to sign the SoundCreation struct, if required.
// Just generate some really random number on the client side for this.
uint256 nonce;
}
// =============================================================
// EVENTS
// =============================================================
/**
* @dev Emitted when an edition is created.
* @param implementation The address of the SoundEdition implementation.
* @param edition The address of the deployed SoundEdition.
* @param owner The address of the owner.
* @param initData The calldata to initialize SoundEdition via `abi.encodeWithSelector`.
* @param contracts The list of contracts called.
* @param data The list of calldata created via `abi.encodeWithSelector`
* @param results The results of calling the contracts. Use `abi.decode` to decode them.
*/
event Created(
address indexed implementation,
address indexed edition,
address indexed owner,
bytes initData,
address[] contracts,
bytes[] data,
bytes[] results
);
/**
* @dev Emitted when the `nonces` of `signer` are invalidated.
* @param signer The signer of the nonces.
* @param nonces The nonces.
*/
event NoncesInvalidated(address indexed signer, uint256[] nonces);
// =============================================================
// ERRORS
// =============================================================
/**
* @dev Thrown if the implementation address is zero.
*/
error ImplementationAddressCantBeZero();
/**
* @dev Thrown if the lengths of the input arrays are not equal.
*/
error ArrayLengthsMismatch();
/**
* @dev Not authorized to perfrom the action.
*/
error Unauthorized();
/**
* @dev The signature for the SoundCreation struct is invalid.
* This could be caused be an invalid parameter, signer, or invalidated nonce.
*/
error InvalidSignature();
// =============================================================
// PUBLIC / EXTERNAL WRITE FUNCTIONS
// =============================================================
/**
* @dev Creates a SoundEdition and sets up all other relevant contracts.
* @param creation The SoundCreation struct.
* @return soundEdition The address of the created SoundEdition contract.
* @return results The results of calling the contracts.
* Use `abi.decode` to decode them.
*/
function create(SoundCreation calldata creation) external returns (address soundEdition, bytes[] memory results);
/**
* @dev Creates a SoundEdition on behalf of `creation.owner`.
* @param creation The SoundCreation struct.
* @param signature The signature for the SoundCreation struct, by `creation.owner`.
* @return soundEdition The address of the created SoundEdition contract.
* @return results The results of calling the contracts.
* Use `abi.decode` to decode them.
*/
function createWithSignature(SoundCreation calldata creation, bytes calldata signature)
external
returns (address soundEdition, bytes[] memory results);
/**
* @dev Calls `minter` with `mintData`.
* After which, refunds any remaining ETH balance in the adapter contract.
* If `minter` is the zero address, the function is a no-op.
* @param minter The minter contract to call, SAM included.
* @param mintData The abi encoded calldata to the minter contract.
* @param refundTo The address to transfer any remaining ETH in the contract after the calls.
* If `address(0)`, remaining ETH will NOT be refunded.
* If `address(1)`, remaining ETH will be refunded to `msg.sender`.
* If anything else, remaining ETH will be refunded to `refundTo`.
*/
function mint(
address minter,
bytes calldata mintData,
address refundTo
) external payable;
/**
* @dev Equivalent to calling {createWithSignature}, followed by {mint}.
* @param creation The SoundCreation struct.
* @param signature The signature for the SoundCreation struct, by `creation.owner`.
* @param minter The minter contract to call, SAM included.
* @param mintData The calldata to the minter contract.
* @param refundTo The address to transfer any remaining ETH in the contract after the calls.
* If `address(0)`, remaining ETH will NOT be refunded.
* If `address(1)`, remaining ETH will be refunded to `msg.sender`.
* If anything else, remaining ETH will be refunded to `refundTo`.
* @return soundEdition The address of the created SoundEdition contract.
* @return results The results of calling the contracts.
* Use `abi.decode` to decode them.
*/
function createWithSignatureAndMint(
SoundCreation calldata creation,
bytes calldata signature,
address minter,
bytes calldata mintData,
address refundTo
) external payable returns (address soundEdition, bytes[] memory results);
/**
* @dev Invalidates the nonces for the `msg.sender`.
* @param nonces The nonces.
*/
function invalidateNonces(uint256[] calldata nonces) external;
// =============================================================
// PUBLIC / EXTERNAL VIEW FUNCTIONS
// =============================================================
/**
* @dev Returns whether each of the `nonces` of `signer` has been invalidated.
* @param signer The signer of the signature.
* @param nonces An array of nonces.
* @return A bool array representing whether each nonce has been invalidated.
*/
function noncesInvalidated(address signer, uint256[] calldata nonces) external view returns (bool[] memory);
/**
* @dev Returns the deterministic address for the SoundEdition clone.
* @param implementation The implementation of the SoundEdition.
* @param owner The initial owner of the SoundEdition.
* @param salt The salt, generated on the client side.
* @return addr The computed address.
* @return exists Whether the contract exists.
*/
function soundEditionAddress(
address implementation,
address owner,
bytes32 salt
) external view returns (address addr, bool exists);
/**
* @dev Returns if the signature for the creation struct is correctly signed,
* as well as the creation's nonce is still valid.
* @param creation The SoundCreation struct.
* @param signature The signature for the SoundCreation struct.
* @return isValid The computed result.
*/
function isValidSignature(SoundCreation calldata creation, bytes calldata signature) external view returns (bool);
/**
* @dev Computes the EIP-712 hash of the SoundCreation struct.
* @param creation The SoundCreation struct.
* @return digest The computed result.
*/
function computeDigest(SoundCreation calldata creation) external view returns (bytes32 digest);
/**
* @dev Returns the SoundCreation struct's EIP-712 typehash.
* @return The constant value.
*/
function SOUND_CREATION_TYPEHASH() external view returns (bytes32);
/**
* @dev Returns the EIP-712 domain typehash.
* @return The constant value.
*/
function DOMAIN_TYPEHASH() external view returns (bytes32);
/**
* @dev Returns the EIP-712 domain name.
* @return name_ The constant value.
*/
function name() external pure returns (string memory name_);
/**
* @dev Returns the EIP-712 domain version.
* @return version_ The constant value.
*/
function version() external pure returns (string memory version_);
/**
* @dev Returns the EIP-712 domain separator.
* @return The current value.
*/
function domainSeparator() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/**
* @title LibMulticaller
* @author vectorized.eth
* @notice Library to read the `msg.sender` of the multicaller with sender contract.
*/
library LibMulticaller {
/**
* @dev The address of the multicaller contract.
*/
address internal constant MULTICALLER = 0x0000000000009448722dAF1A55EF6D1E71FB162d;
/**
* @dev The address of the multicaller with sender contract.
*/
address internal constant MULTICALLER_WITH_SENDER = 0x00000000002Fd5Aeb385D324B580FCa7c83823A0;
/**
* @dev The address of the multicaller with signer contract.
*/
address internal constant MULTICALLER_WITH_SIGNER = 0x000000000000a89360A6a4786b9B33266F208AF4;
/**
* @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`.
*/
function multicallerSender() internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, 0x00)
if iszero(staticcall(gas(), MULTICALLER_WITH_SENDER, 0x00, 0x00, 0x00, 0x20)) {
revert(0x00, 0x00) // For better gas estimation.
}
result := mload(0x00)
}
}
/**
* @dev Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`.
*/
function multicallerSigner() internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, 0x00)
if iszero(staticcall(gas(), MULTICALLER_WITH_SIGNER, 0x00, 0x00, 0x00, 0x20)) {
revert(0x00, 0x00) // For better gas estimation.
}
result := mload(0x00)
}
}
/**
* @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`,
* if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`.
* Otherwise, returns `msg.sender`.
*/
function sender() internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, caller())
let withSender := MULTICALLER_WITH_SENDER
if eq(caller(), withSender) {
if iszero(staticcall(gas(), withSender, 0x00, 0x00, 0x00, 0x20)) {
revert(0x00, 0x00) // For better gas estimation.
}
}
result := mload(0x00)
}
}
/**
* @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`,
* if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`.
* Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`,
* if the current context's `msg.sender` is `MULTICALLER_WITH_SIGNER`.
* Otherwise, returns `msg.sender`.
*/
function senderOrSigner() internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, caller())
let withSender := MULTICALLER_WITH_SENDER
if eq(caller(), withSender) {
if iszero(staticcall(gas(), withSender, 0x00, 0x00, 0x00, 0x20)) {
revert(0x00, 0x00) // For better gas estimation.
}
}
let withSigner := MULTICALLER_WITH_SIGNER
if eq(caller(), withSigner) {
if iszero(staticcall(gas(), withSigner, 0x00, 0x00, 0x00, 0x20)) {
revert(0x00, 0x00) // For better gas estimation.
}
}
result := mload(0x00)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
/// This event is intentionally kept the same as OpenZeppelin's Ownable to be
/// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
/// despite it not being as lightweight as a single argument event.
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
/// @dev An ownership handover to `pendingOwner` has been requested.
event OwnershipHandoverRequested(address indexed pendingOwner);
/// @dev The ownership handover to `pendingOwner` has been canceled.
event OwnershipHandoverCanceled(address indexed pendingOwner);
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
/// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The owner slot is given by: `not(_OWNER_SLOT_NOT)`.
/// It is intentionally chosen to be a high value
/// to avoid collision with lower slots.
/// The choice of manual storage layout is to enable compatibility
/// with both regular and upgradeable contracts.
uint256 private constant _OWNER_SLOT_NOT = 0x8b78c6d8;
/// The ownership handover slot of `newOwner` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
/// let handoverSlot := keccak256(0x00, 0x20)
/// ```
/// It stores the expiry timestamp of the two-step ownership handover.
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Initializes the owner directly without authorization guard.
/// This function must be called upon initialization,
/// regardless of whether the contract is upgradeable or not.
/// This is to enable generalization to both regular and upgradeable contracts,
/// and to save gas in case the initial owner is not the caller.
/// For performance reasons, this function will not check if there
/// is an existing owner.
function _initializeOwner(address newOwner) internal virtual {
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(not(_OWNER_SLOT_NOT), newOwner)
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
/// @dev Sets the owner directly without authorization guard.
function _setOwner(address newOwner) internal virtual {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := not(_OWNER_SLOT_NOT)
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, newOwner)
}
}
/// @dev Throws if the sender is not the owner.
function _checkOwner() internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner, revert.
if iszero(eq(caller(), sload(not(_OWNER_SLOT_NOT)))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns how long a two-step ownership handover is valid for in seconds.
/// Override to return a different value if needed.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to transfer the ownership to `newOwner`.
function transferOwnership(address newOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
/// @dev Allows the owner to renounce their ownership.
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
/// @dev Request a two-step ownership handover to the caller.
/// The request will automatically expire in 48 hours (172800 seconds) by default.
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to `expires`.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
// Emit the {OwnershipHandoverRequested} event.
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
/// @dev Cancels the two-step ownership handover to the caller, if any.
function cancelOwnershipHandover() public payable virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
// Emit the {OwnershipHandoverCanceled} event.
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
/// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
/// Reverts if there is no existing ownership handover requested by `pendingOwner`.
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
// If the handover does not exist, or has expired.
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
revert(0x1c, 0x04)
}
// Set the handover slot to 0.
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the owner of the contract.
function owner() public view virtual returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(not(_OWNER_SLOT_NOT))
}
}
/// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
// Compute the handover slot.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
// Load the handover slot.
result := sload(keccak256(0x0c, 0x20))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by the owner.
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Contract for EIP-712 typed structured data hashing and signing.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)
/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)
///
/// @dev Note, this implementation:
/// - Uses `address(this)` for the `verifyingContract` field.
/// - Does NOT use the optional EIP-712 salt.
/// - Does NOT use any EIP-712 extensions.
/// This is for simplicity and to save gas.
/// If you need to customize, please fork / modify accordingly.
abstract contract EIP712 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS AND IMMUTABLES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
bytes32 internal constant _DOMAIN_TYPEHASH =
0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
address private immutable _cachedThis;
uint256 private immutable _cachedChainId;
bytes32 private immutable _cachedNameHash;
bytes32 private immutable _cachedVersionHash;
bytes32 private immutable _cachedDomainSeparator;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTRUCTOR */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Cache the hashes for cheaper runtime gas costs.
/// In the case of upgradeable contracts (i.e. proxies),
/// or if the chain id changes due to a hard fork,
/// the domain separator will be seamlessly calculated on-the-fly.
constructor() {
_cachedThis = address(this);
_cachedChainId = block.chainid;
string memory name;
string memory version;
if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion();
bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name));
bytes32 versionHash =
_domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version));
_cachedNameHash = nameHash;
_cachedVersionHash = versionHash;
bytes32 separator;
if (!_domainNameAndVersionMayChange()) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Load the free memory pointer.
mstore(m, _DOMAIN_TYPEHASH)
mstore(add(m, 0x20), nameHash)
mstore(add(m, 0x40), versionHash)
mstore(add(m, 0x60), chainid())
mstore(add(m, 0x80), address())
separator := keccak256(m, 0xa0)
}
}
_cachedDomainSeparator = separator;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FUNCTIONS TO OVERRIDE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Please override this function to return the domain name and version.
/// ```
/// function _domainNameAndVersion()
/// internal
/// pure
/// virtual
/// returns (string memory name, string memory version)
/// {
/// name = "Solady";
/// version = "1";
/// }
/// ```
///
/// Note: If the returned result may change after the contract has been deployed,
/// you must override `_domainNameAndVersionMayChange()` to return true.
function _domainNameAndVersion()
internal
view
virtual
returns (string memory name, string memory version);
/// @dev Returns if `_domainNameAndVersion()` may change
/// after the contract has been deployed (i.e. after the constructor).
/// Default: false.
function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the EIP-712 domain separator.
function _domainSeparator() internal view virtual returns (bytes32 separator) {
if (_domainNameAndVersionMayChange()) {
separator = _buildDomainSeparator();
} else {
separator = _cachedDomainSeparator;
if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
}
}
/// @dev Returns the hash of the fully encoded EIP-712 message for this domain,
/// given `structHash`, as defined in
/// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.
///
/// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:
/// ```
/// bytes32 digest = _hashTypedData(keccak256(abi.encode(
/// keccak256("Mail(address to,string contents)"),
/// mailTo,
/// keccak256(bytes(mailContents))
/// )));
/// address signer = ECDSA.recover(digest, signature);
/// ```
function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) {
bytes32 separator;
if (_domainNameAndVersionMayChange()) {
separator = _buildDomainSeparator();
} else {
separator = _cachedDomainSeparator;
if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
}
/// @solidity memory-safe-assembly
assembly {
// Compute the digest.
mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
mstore(0x1a, separator) // Store the domain separator.
mstore(0x3a, structHash) // Store the struct hash.
digest := keccak256(0x18, 0x42)
// Restore the part of the free memory slot that was overwritten.
mstore(0x3a, 0)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EIP-5267 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev See: https://eips.ethereum.org/EIPS/eip-5267
function eip712Domain()
public
view
virtual
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
fields = hex"0f"; // `0b01111`.
(name, version) = _domainNameAndVersion();
chainId = block.chainid;
verifyingContract = address(this);
salt = salt; // `bytes32(0)`.
extensions = extensions; // `new uint256[](0)`.
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PRIVATE HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the EIP-712 domain separator.
function _buildDomainSeparator() private view returns (bytes32 separator) {
bytes32 nameHash;
bytes32 versionHash;
if (_domainNameAndVersionMayChange()) {
(string memory name, string memory version) = _domainNameAndVersion();
nameHash = keccak256(bytes(name));
versionHash = keccak256(bytes(version));
} else {
nameHash = _cachedNameHash;
versionHash = _cachedVersionHash;
}
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Load the free memory pointer.
mstore(m, _DOMAIN_TYPEHASH)
mstore(add(m, 0x20), nameHash)
mstore(add(m, 0x40), versionHash)
mstore(add(m, 0x60), chainid())
mstore(add(m, 0x80), address())
separator := keccak256(m, 0xa0)
}
}
/// @dev Returns if the cached domain separator has been invalidated.
function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
uint256 cachedChainId = _cachedChainId;
address cachedThis = _cachedThis;
/// @solidity memory-safe-assembly
assembly {
result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Library for compressing and decompressing bytes.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibZip.sol)
/// @author Calldata compression by clabby (https://github.com/clabby/op-kompressor)
/// @author FastLZ by ariya (https://github.com/ariya/FastLZ)
///
/// @dev Note:
/// The accompanying solady.js library includes implementations of
/// FastLZ and calldata operations for convenience.
library LibZip {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FAST LZ OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// LZ77 implementation based on FastLZ.
// Equivalent to level 1 compression and decompression at the following commit:
// https://github.com/ariya/FastLZ/commit/344eb4025f9ae866ebf7a2ec48850f7113a97a42
// Decompression is backwards compatible.
/// @dev Returns the compressed `data`.
function flzCompress(bytes memory data) internal pure returns (bytes memory result) {
/// @solidity memory-safe-assembly
assembly {
function ms8(d_, v_) -> _d {
mstore8(d_, v_)
_d := add(d_, 1)
}
function u24(p_) -> _u {
let w := mload(p_)
_u := or(shl(16, byte(2, w)), or(shl(8, byte(1, w)), byte(0, w)))
}
function cmp(p_, q_, e_) -> _l {
for { e_ := sub(e_, q_) } lt(_l, e_) { _l := add(_l, 1) } {
e_ := mul(iszero(byte(0, xor(mload(add(p_, _l)), mload(add(q_, _l))))), e_)
}
}
function literals(runs_, src_, dest_) -> _o {
for { _o := dest_ } iszero(lt(runs_, 0x20)) { runs_ := sub(runs_, 0x20) } {
mstore(ms8(_o, 31), mload(src_))
_o := add(_o, 0x21)
src_ := add(src_, 0x20)
}
if iszero(runs_) { leave }
mstore(ms8(_o, sub(runs_, 1)), mload(src_))
_o := add(1, add(_o, runs_))
}
function match(l_, d_, o_) -> _o {
for { d_ := sub(d_, 1) } iszero(lt(l_, 263)) { l_ := sub(l_, 262) } {
o_ := ms8(ms8(ms8(o_, add(224, shr(8, d_))), 253), and(0xff, d_))
}
if iszero(lt(l_, 7)) {
_o := ms8(ms8(ms8(o_, add(224, shr(8, d_))), sub(l_, 7)), and(0xff, d_))
leave
}
_o := ms8(ms8(o_, add(shl(5, l_), shr(8, d_))), and(0xff, d_))
}
function setHash(i_, v_) {
let p := add(mload(0x40), shl(2, i_))
mstore(p, xor(mload(p), shl(224, xor(shr(224, mload(p)), v_))))
}
function getHash(i_) -> _h {
_h := shr(224, mload(add(mload(0x40), shl(2, i_))))
}
function hash(v_) -> _r {
_r := and(shr(19, mul(2654435769, v_)), 0x1fff)
}
function setNextHash(ip_, ipStart_) -> _ip {
setHash(hash(u24(ip_)), sub(ip_, ipStart_))
_ip := add(ip_, 1)
}
codecopy(mload(0x40), codesize(), 0x8000) // Zeroize the hashmap.
let op := add(mload(0x40), 0x8000)
let a := add(data, 0x20)
let ipStart := a
let ipLimit := sub(add(ipStart, mload(data)), 13)
for { let ip := add(2, a) } lt(ip, ipLimit) {} {
let r := 0
let d := 0
for {} 1 {} {
let s := u24(ip)
let h := hash(s)
r := add(ipStart, getHash(h))
setHash(h, sub(ip, ipStart))
d := sub(ip, r)
if iszero(lt(ip, ipLimit)) { break }
ip := add(ip, 1)
if iszero(gt(d, 0x1fff)) { if eq(s, u24(r)) { break } }
}
if iszero(lt(ip, ipLimit)) { break }
ip := sub(ip, 1)
if gt(ip, a) { op := literals(sub(ip, a), a, op) }
let l := cmp(add(r, 3), add(ip, 3), add(ipLimit, 9))
op := match(l, d, op)
ip := setNextHash(setNextHash(add(ip, l), ipStart), ipStart)
a := ip
}
op := literals(sub(add(ipStart, mload(data)), a), a, op)
result := mload(0x40)
let t := add(result, 0x8000)
let n := sub(op, t)
mstore(result, n) // Store the length.
// Copy the result to compact the memory, overwriting the hashmap.
let o := add(result, 0x20)
for { let i } lt(i, n) { i := add(i, 0x20) } { mstore(add(o, i), mload(add(t, i))) }
mstore(add(o, n), 0) // Zeroize the slot after the string.
mstore(0x40, add(add(o, n), 0x20)) // Allocate the memory.
}
}
/// @dev Returns the decompressed `data`.
function flzDecompress(bytes memory data) internal pure returns (bytes memory result) {
/// @solidity memory-safe-assembly
assembly {
let n := 0
let end := add(add(data, 0x20), mload(data))
result := mload(0x40)
let op := add(result, 0x20)
for { data := add(data, 0x20) } lt(data, end) {} {
let w := mload(data)
let c := byte(0, w)
let t := shr(5, c)
if iszero(t) {
mstore(add(op, n), mload(add(data, 1)))
data := add(data, add(2, c))
n := add(n, add(1, c))
continue
}
let g := eq(t, 7)
let l := add(2, xor(t, mul(g, xor(t, add(7, byte(1, w))))))
for {
let s := add(add(shl(8, and(0x1f, c)), byte(add(1, g), w)), 1)
let r := add(op, sub(n, s))
let o := add(op, n)
let f := xor(s, mul(gt(s, 0x20), xor(s, 0x20)))
let j := 0
} 1 {} {
mstore(add(o, j), mload(add(r, j)))
j := add(j, f)
if iszero(lt(j, l)) { break }
}
data := add(data, add(2, g))
n := add(n, l)
}
mstore(result, n) // Store the length.
let o := add(add(result, 0x20), n)
mstore(o, 0) // Zeroize the slot after the string.
mstore(0x40, add(o, 0x20)) // Allocate the memory.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CALLDATA OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Calldata compression and decompression using selective run length encoding:
// - Sequences of 0x00 (up to 128 consecutive).
// - Sequences of 0xff (up to 32 consecutive).
//
// A run length encoded block consists of two bytes:
// (0) 0x00
// (1) A control byte with the following bit layout:
// - [7] `0: 0x00, 1: 0xff`.
// - [0..6] `runLength - 1`.
//
// The first 4 bytes are bitwise negated so that the compressed calldata
// can be dispatched into the `fallback` and `receive` functions.
/// @dev Returns the compressed `data`.
function cdCompress(bytes memory data) internal pure returns (bytes memory result) {
/// @solidity memory-safe-assembly
assembly {
function rle(v_, o_, d_) -> _o, _d {
mstore(o_, shl(240, or(and(0xff, add(d_, 0xff)), and(0x80, v_))))
_o := add(o_, 2)
}
result := mload(0x40)
let o := add(result, 0x20)
let z := 0 // Number of consecutive 0x00.
let y := 0 // Number of consecutive 0xff.
for { let end := add(data, mload(data)) } iszero(eq(data, end)) {} {
data := add(data, 1)
let c := byte(31, mload(data))
if iszero(c) {
if y { o, y := rle(0xff, o, y) }
z := add(z, 1)
if eq(z, 0x80) { o, z := rle(0x00, o, 0x80) }
continue
}
if eq(c, 0xff) {
if z { o, z := rle(0x00, o, z) }
y := add(y, 1)
if eq(y, 0x20) { o, y := rle(0xff, o, 0x20) }
continue
}
if y { o, y := rle(0xff, o, y) }
if z { o, z := rle(0x00, o, z) }
mstore8(o, c)
o := add(o, 1)
}
if y { o, y := rle(0xff, o, y) }
if z { o, z := rle(0x00, o, z) }
// Bitwise negate the first 4 bytes.
mstore(add(result, 4), not(mload(add(result, 4))))
mstore(result, sub(o, add(result, 0x20))) // Store the length.
mstore(o, 0) // Zeroize the slot after the string.
mstore(0x40, add(o, 0x20)) // Allocate the memory.
}
}
/// @dev Returns the decompressed `data`.
function cdDecompress(bytes memory data) internal pure returns (bytes memory result) {
/// @solidity memory-safe-assembly
assembly {
if mload(data) {
result := mload(0x40)
let o := add(result, 0x20)
let s := add(data, 4)
let v := mload(s)
let end := add(data, mload(data))
mstore(s, not(v)) // Bitwise negate the first 4 bytes.
for {} lt(data, end) {} {
data := add(data, 1)
let c := byte(31, mload(data))
if iszero(c) {
data := add(data, 1)
let d := byte(31, mload(data))
// Fill with either 0xff or 0x00.
mstore(o, not(0))
if iszero(gt(d, 0x7f)) { codecopy(o, codesize(), add(d, 1)) }
o := add(o, add(and(d, 0x7f), 1))
continue
}
mstore8(o, c)
o := add(o, 1)
}
mstore(s, v) // Restore the first 4 bytes.
mstore(result, sub(o, add(result, 0x20))) // Store the length.
mstore(o, 0) // Zeroize the slot after the string.
mstore(0x40, add(o, 0x20)) // Allocate the memory.
}
}
}
/// @dev To be called in the `receive` and `fallback` functions.
/// ```
/// receive() external payable { LibZip.cdFallback(); }
/// fallback() external payable { LibZip.cdFallback(); }
/// ```
/// For efficiency, this function will directly return the results, terminating the context.
/// If called internally, it must be called at the end of the function.
function cdFallback() internal {
assembly {
if iszero(calldatasize()) { return(calldatasize(), calldatasize()) }
let o := 0
let f := not(3) // For negating the first 4 bytes.
for { let i := 0 } lt(i, calldatasize()) {} {
let c := byte(0, xor(add(i, f), calldataload(i)))
i := add(i, 1)
if iszero(c) {
let d := byte(0, xor(add(i, f), calldataload(i)))
i := add(i, 1)
// Fill with either 0xff or 0x00.
mstore(o, not(0))
if iszero(gt(d, 0x7f)) { codecopy(o, codesize(), add(d, 1)) }
o := add(o, add(and(d, 0x7f), 1))
continue
}
mstore8(o, c)
o := add(o, 1)
}
let success := delegatecall(gas(), address(), 0x00, o, 0x00, 0x00)
returndatacopy(0x00, 0x00, returndatasize())
if iszero(success) { revert(0x00, returndatasize()) }
return(0x00, returndatasize())
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {LibBit} from "./LibBit.sol";
/// @notice Library for storage of packed unsigned booleans.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBitmap.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibBitmap.sol)
/// @author Modified from Solidity-Bits (https://github.com/estarriolvetch/solidity-bits/blob/main/contracts/BitMaps.sol)
library LibBitmap {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The constant returned when a bitmap scan does not find a result.
uint256 internal constant NOT_FOUND = type(uint256).max;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STRUCTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev A bitmap in storage.
struct Bitmap {
mapping(uint256 => uint256) map;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the boolean value of the bit at `index` in `bitmap`.
function get(Bitmap storage bitmap, uint256 index) internal view returns (bool isSet) {
// It is better to set `isSet` to either 0 or 1, than zero vs non-zero.
// Both cost the same amount of gas, but the former allows the returned value
// to be reused without cleaning the upper bits.
uint256 b = (bitmap.map[index >> 8] >> (index & 0xff)) & 1;
/// @solidity memory-safe-assembly
assembly {
isSet := b
}
}
/// @dev Updates the bit at `index` in `bitmap` to true.
function set(Bitmap storage bitmap, uint256 index) internal {
bitmap.map[index >> 8] |= (1 << (index & 0xff));
}
/// @dev Updates the bit at `index` in `bitmap` to false.
function unset(Bitmap storage bitmap, uint256 index) internal {
bitmap.map[index >> 8] &= ~(1 << (index & 0xff));
}
/// @dev Flips the bit at `index` in `bitmap`.
/// Returns the boolean result of the flipped bit.
function toggle(Bitmap storage bitmap, uint256 index) internal returns (bool newIsSet) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, shr(8, index))
mstore(0x20, bitmap.slot)
let storageSlot := keccak256(0x00, 0x40)
let shift := and(index, 0xff)
let storageValue := sload(storageSlot)
let mask := shl(shift, 1)
storageValue := xor(storageValue, mask)
// It makes sense to return the `newIsSet`,
// as it allow us to skip an additional warm `sload`,
// and it costs minimal gas (about 15),
// which may be optimized away if the returned value is unused.
newIsSet := iszero(iszero(and(storageValue, mask)))
sstore(storageSlot, storageValue)
}
}
/// @dev Updates the bit at `index` in `bitmap` to `shouldSet`.
function setTo(Bitmap storage bitmap, uint256 index, bool shouldSet) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x20, bitmap.slot)
mstore(0x00, shr(8, index))
let storageSlot := keccak256(0x00, 0x40)
let storageValue := sload(storageSlot)
let shift := and(index, 0xff)
sstore(
storageSlot,
// Unsets the bit at `shift` via `and`, then sets its new value via `or`.
or(and(storageValue, not(shl(shift, 1))), shl(shift, iszero(iszero(shouldSet))))
)
}
}
/// @dev Consecutively sets `amount` of bits starting from the bit at `start`.
function setBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
let max := not(0)
let shift := and(start, 0xff)
mstore(0x20, bitmap.slot)
mstore(0x00, shr(8, start))
if iszero(lt(add(shift, amount), 257)) {
let storageSlot := keccak256(0x00, 0x40)
sstore(storageSlot, or(sload(storageSlot), shl(shift, max)))
let bucket := add(mload(0x00), 1)
let bucketEnd := add(mload(0x00), shr(8, add(amount, shift)))
amount := and(add(amount, shift), 0xff)
shift := 0
for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } {
mstore(0x00, bucket)
sstore(keccak256(0x00, 0x40), max)
}
mstore(0x00, bucket)
}
let storageSlot := keccak256(0x00, 0x40)
sstore(storageSlot, or(sload(storageSlot), shl(shift, shr(sub(256, amount), max))))
}
}
/// @dev Consecutively unsets `amount` of bits starting from the bit at `start`.
function unsetBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
let shift := and(start, 0xff)
mstore(0x20, bitmap.slot)
mstore(0x00, shr(8, start))
if iszero(lt(add(shift, amount), 257)) {
let storageSlot := keccak256(0x00, 0x40)
sstore(storageSlot, and(sload(storageSlot), not(shl(shift, not(0)))))
let bucket := add(mload(0x00), 1)
let bucketEnd := add(mload(0x00), shr(8, add(amount, shift)))
amount := and(add(amount, shift), 0xff)
shift := 0
for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } {
mstore(0x00, bucket)
sstore(keccak256(0x00, 0x40), 0)
}
mstore(0x00, bucket)
}
let storageSlot := keccak256(0x00, 0x40)
sstore(
storageSlot, and(sload(storageSlot), not(shl(shift, shr(sub(256, amount), not(0)))))
)
}
}
/// @dev Returns number of set bits within a range by
/// scanning `amount` of bits starting from the bit at `start`.
function popCount(Bitmap storage bitmap, uint256 start, uint256 amount)
internal
view
returns (uint256 count)
{
unchecked {
uint256 bucket = start >> 8;
uint256 shift = start & 0xff;
if (!(amount + shift < 257)) {
count = LibBit.popCount(bitmap.map[bucket] >> shift);
uint256 bucketEnd = bucket + ((amount + shift) >> 8);
amount = (amount + shift) & 0xff;
shift = 0;
for (++bucket; bucket != bucketEnd; ++bucket) {
count += LibBit.popCount(bitmap.map[bucket]);
}
}
count += LibBit.popCount((bitmap.map[bucket] >> shift) << (256 - amount));
}
}
/// @dev Returns the index of the most significant set bit before the bit at `before`.
/// If no set bit is found, returns `NOT_FOUND`.
function findLastSet(Bitmap storage bitmap, uint256 before)
internal
view
returns (uint256 setBitIndex)
{
uint256 bucket;
uint256 bucketBits;
/// @solidity memory-safe-assembly
assembly {
setBitIndex := not(0)
bucket := shr(8, before)
mstore(0x00, bucket)
mstore(0x20, bitmap.slot)
let offset := and(0xff, not(before)) // `256 - (255 & before) - 1`.
bucketBits := shr(offset, shl(offset, sload(keccak256(0x00, 0x40))))
if iszero(bucketBits) {
for {} bucket {} {
bucket := add(bucket, setBitIndex) // `sub(bucket, 1)`.
mstore(0x00, bucket)
bucketBits := sload(keccak256(0x00, 0x40))
if bucketBits { break }
}
}
}
if (bucketBits != 0) {
setBitIndex = (bucket << 8) | LibBit.fls(bucketBits);
/// @solidity memory-safe-assembly
assembly {
setBitIndex := or(setBitIndex, sub(0, gt(setBitIndex, before)))
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
/// - For ERC20s, this implementation won't check that a token has code,
/// responsibility is delegated to the caller.
library SafeTransferLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ETH transfer has failed.
error ETHTransferFailed();
/// @dev The ERC20 `transferFrom` has failed.
error TransferFromFailed();
/// @dev The ERC20 `transfer` has failed.
error TransferFailed();
/// @dev The ERC20 `approve` has failed.
error ApproveFailed();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;
/// @dev Suggested gas stipend for contract receiving ETH to perform a few
/// storage reads and writes, but low enough to prevent griefing.
uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ETH OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
//
// The regular variants:
// - Forwards all remaining gas to the target.
// - Reverts if the target reverts.
// - Reverts if the current contract has insufficient balance.
//
// The force variants:
// - Forwards with an optional gas stipend
// (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
// - If the target reverts, or if the gas stipend is exhausted,
// creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
// Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
// - Reverts if the current contract has insufficient balance.
//
// The try variants:
// - Forwards with a mandatory gas stipend.
// - Instead of reverting, returns whether the transfer succeeded.
/// @dev Sends `amount` (in wei) ETH to `to`.
function safeTransferETH(address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
if iszero(call(gas(), to, amount, gas(), 0x00, gas(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Sends all the ETH in the current contract to `to`.
function safeTransferAllETH(address to) internal {
/// @solidity memory-safe-assembly
assembly {
// Transfer all the ETH and check if it succeeded or not.
if iszero(call(gas(), to, selfbalance(), gas(), 0x00, gas(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
/// @solidity memory-safe-assembly
assembly {
if lt(selfbalance(), amount) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
if iszero(call(gasStipend, to, amount, gas(), 0x00, gas(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(amount, 0x0b, 0x16)) {
returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
}
}
}
}
/// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
/// @solidity memory-safe-assembly
assembly {
if iszero(call(gasStipend, to, selfbalance(), gas(), 0x00, gas(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(selfbalance(), 0x0b, 0x16)) {
returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
}
}
}
}
/// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
function forceSafeTransferETH(address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
if lt(selfbalance(), amount) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, gas(), 0x00, gas(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(amount, 0x0b, 0x16)) {
returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
}
}
}
}
/// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
function forceSafeTransferAllETH(address to) internal {
/// @solidity memory-safe-assembly
assembly {
if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), gas(), 0x00, gas(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(selfbalance(), 0x0b, 0x16)) {
returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
}
}
}
}
/// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
internal
returns (bool success)
{
/// @solidity memory-safe-assembly
assembly {
success := call(gasStipend, to, amount, gas(), 0x00, gas(), 0x00)
}
}
/// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
function trySafeTransferAllETH(address to, uint256 gasStipend)
internal
returns (bool success)
{
/// @solidity memory-safe-assembly
assembly {
success := call(gasStipend, to, selfbalance(), gas(), 0x00, gas(), 0x00)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC20 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
/// Reverts upon failure.
///
/// The `from` account must have at least `amount` approved for
/// the current contract to manage.
function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, amount) // Store the `amount` argument.
mstore(0x40, to) // Store the `to` argument.
mstore(0x2c, shl(96, from)) // Store the `from` argument.
mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
)
) {
mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Sends all of ERC20 `token` from `from` to `to`.
/// Reverts upon failure.
///
/// The `from` account must have their entire balance approved for
/// the current contract to manage.
function safeTransferAllFrom(address token, address from, address to)
internal
returns (uint256 amount)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x40, to) // Store the `to` argument.
mstore(0x2c, shl(96, from)) // Store the `from` argument.
mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
// Read the balance, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x1f), // At least 32 bytes returned.
staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
)
) {
mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
revert(0x1c, 0x04)
}
mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
)
) {
mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
/// Reverts upon failure.
function safeTransfer(address token, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
revert(0x1c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sends all of ERC20 `token` from the current contract to `to`.
/// Reverts upon failure.
function safeTransferAll(address token, address to) internal returns (uint256 amount) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
mstore(0x20, address()) // Store the address of the current contract.
// Read the balance, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x1f), // At least 32 bytes returned.
staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
)
) {
mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
revert(0x1c, 0x04)
}
mstore(0x14, to) // Store the `to` argument.
amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
revert(0x1c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
/// Reverts upon failure.
function safeApprove(address token, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
// Perform the approval, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
revert(0x1c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
/// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
/// then retries the approval again (some tokens, e.g. USDT, requires this).
/// Reverts upon failure.
function safeApproveWithRetry(address token, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
// Perform the approval, retrying upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x34, 0) // Store 0 for the `amount`.
mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
pop(call(gas(), token, 0, 0x10, 0x44, 0x00, 0x00)) // Reset the approval.
mstore(0x34, amount) // Store back the original `amount`.
// Retry the approval, reverting upon failure.
if iszero(
and(
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
revert(0x1c, 0x04)
}
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Returns the amount of ERC20 `token` owned by `account`.
/// Returns zero if the `token` does not exist.
function balanceOf(address token, address account) internal view returns (uint256 amount) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, account) // Store the `account` argument.
mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
amount :=
mul(
mload(0x20),
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x1f), // At least 32 bytes returned.
staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
)
)
}
}
}// 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.
///
/// WARNING! Do NOT use signatures as unique identifiers.
/// Please use EIP712 with a nonce included in the digest to prevent replay attacks.
/// This implementation does NOT check if a signature is non-malleable.
library SignatureCheckerLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SIGNATURE CHECKING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns whether `signature` is valid for `signer` and `hash`.
/// If `signer` is a smart contract, the signature is validated with ERC1271.
/// Otherwise, the signature is validated with `ECDSA.recover`.
function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits of `signer` in case they are dirty.
for { signer := shr(96, shl(96, signer)) } signer {} {
let m := mload(0x40)
if eq(mload(signature), 65) {
mstore(0x00, hash)
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x40, mload(add(signature, 0x20))) // `r`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
let t :=
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
isValid := 1
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
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))
pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
// forgefmt: disable-next-item
isValid := and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(d), f),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
add(returndatasize(), 0x44), // Length of calldata in memory.
d, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
break
}
}
}
/// @dev Returns whether `signature` is valid for `signer` and `hash`.
/// If `signer` is a smart contract, the signature is validated with ERC1271.
/// Otherwise, the signature is validated with `ECDSA.recover`.
function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits of `signer` in case they are dirty.
for { signer := shr(96, shl(96, signer)) } signer {} {
let m := mload(0x40)
if eq(signature.length, 65) {
mstore(0x00, hash)
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`.
let t :=
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
isValid := 1
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
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)
// forgefmt: disable-next-item
isValid := and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(d), f),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
add(signature.length, 0x64), // Length of calldata in memory.
d, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
break
}
}
}
/// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`.
/// If `signer` is a smart contract, the signature is validated with ERC1271.
/// Otherwise, the signature is validated with `ECDSA.recover`.
function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits of `signer` in case they are dirty.
for { signer := shr(96, shl(96, signer)) } signer {} {
let m := mload(0x40)
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
let t :=
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
isValid := 1
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), mload(0x60)) // `s`.
mstore8(add(m, 0xa4), mload(0x20)) // `v`.
// forgefmt: disable-next-item
isValid := and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(d), f),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
0xa5, // Length of calldata in memory.
d, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`.
/// If `signer` is a smart contract, the signature is validated with ERC1271.
/// Otherwise, the signature is validated with `ECDSA.recover`.
function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits of `signer` in case they are dirty.
for { signer := shr(96, shl(96, signer)) } signer {} {
let m := mload(0x40)
mstore(0x00, hash)
mstore(0x20, and(v, 0xff)) // `v`.
mstore(0x40, r) // `r`.
mstore(0x60, s) // `s`.
let t :=
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
isValid := 1
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`.
// forgefmt: disable-next-item
isValid := and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(d), f),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
0xa5, // Length of calldata in memory.
d, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC1271 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns whether `signature` is valid for `hash`
/// for an ERC1271 `signer` contract.
function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature)
internal
view
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let 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))
pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
// forgefmt: disable-next-item
isValid := and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(d), f),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
add(returndatasize(), 0x44), // Length of calldata in memory.
d, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
}
}
/// @dev Returns whether `signature` is valid for `hash`
/// for an ERC1271 `signer` contract.
function isValidERC1271SignatureNowCalldata(
address signer,
bytes32 hash,
bytes calldata signature
) internal view returns (bool isValid) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let f := shl(224, 0x1626ba7e)
mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
mstore(add(m, 0x04), hash)
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)
// forgefmt: disable-next-item
isValid := and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(d), f),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
add(signature.length, 0x64), // Length of calldata in memory.
d, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
}
}
/// @dev Returns whether the signature (`r`, `vs`) is valid for `hash`
/// for an ERC1271 `signer` contract.
function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
internal
view
returns (bool isValid)
{
/// @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`.
// forgefmt: disable-next-item
isValid := and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(d), f),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
0xa5, // Length of calldata in memory.
d, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
}
}
/// @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`.
// forgefmt: disable-next-item
isValid := and(
// Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
eq(mload(d), f),
// Whether the staticcall does not revert.
// This must be placed at the end of the `and` clause,
// as the arguments are evaluated from right to left.
staticcall(
gas(), // Remaining gas.
signer, // The `signer` address.
m, // Offset of calldata in memory.
0xa5, // Length of calldata in memory.
d, // Offset of returndata.
0x20 // Length of returndata to write.
)
)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EMPTY CALLDATA HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an empty calldata bytes.
function emptySignature() internal pure returns (bytes calldata signature) {
/// @solidity memory-safe-assembly
assembly {
signature.length := 0
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Library for bit twiddling and boolean operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBit.sol)
/// @author Inspired by (https://graphics.stanford.edu/~seander/bithacks.html)
library LibBit {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BIT TWIDDLING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Find last set.
/// Returns the index of the most significant bit of `x`,
/// counting from the least significant bit position.
/// If `x` is zero, returns 256.
function fls(uint256 x) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x)))
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffff, shr(r, x))))
r := or(r, shl(3, lt(0xff, shr(r, x))))
r := or(r, shl(2, lt(0xf, shr(r, x))))
r := or(r, byte(shr(r, x), hex"00000101020202020303030303030303"))
}
}
/// @dev Count leading zeros.
/// Returns the number of zeros preceding the most significant one bit.
/// If `x` is zero, returns 256.
function clz(uint256 x) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffff, shr(r, x))))
r := or(r, shl(3, lt(0xff, shr(r, x))))
r := or(r, shl(2, lt(0xf, shr(r, x))))
// forgefmt: disable-next-item
r := add(iszero(x), xor(255,
or(r, byte(shr(r, x), hex"00000101020202020303030303030303"))))
}
}
/// @dev Find first set.
/// Returns the index of the least significant bit of `x`,
/// counting from the least significant bit position.
/// If `x` is zero, returns 256.
/// Equivalent to `ctz` (count trailing zeros), which gives
/// the number of zeros following the least significant one bit.
function ffs(uint256 x) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
// Isolate the least significant bit.
let b := and(x, add(not(x), 1))
r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, b)))
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, b))))
r := or(r, shl(5, lt(0xffffffff, shr(r, b))))
// For the remaining 32 bits, use a De Bruijn lookup.
// forgefmt: disable-next-item
r := or(r, byte(and(div(0xd76453e0, shr(r, b)), 0x1f),
0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
}
}
/// @dev Returns the number of set bits in `x`.
function popCount(uint256 x) internal pure returns (uint256 c) {
/// @solidity memory-safe-assembly
assembly {
let max := not(0)
let isMax := eq(x, max)
x := sub(x, and(shr(1, x), div(max, 3)))
x := add(and(x, div(max, 5)), and(shr(2, x), div(max, 5)))
x := and(add(x, shr(4, x)), div(max, 17))
c := or(shl(8, isMax), shr(248, mul(x, div(max, 255))))
}
}
/// @dev Returns whether `x` is a power of 2.
function isPo2(uint256 x) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to `x && !(x & (x - 1))`.
result := iszero(add(and(x, sub(x, 1)), iszero(x)))
}
}
/// @dev Returns `x` reversed at the bit level.
function reverseBits(uint256 x) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
// Computing masks on-the-fly reduces bytecode size by about 500 bytes.
let m := not(0)
r := x
for { let s := 128 } 1 {} {
m := xor(m, shl(s, m))
r := or(and(shr(s, r), m), and(shl(s, r), not(m)))
s := shr(1, s)
if iszero(s) { break }
}
}
}
/// @dev Returns `x` reversed at the byte level.
function reverseBytes(uint256 x) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
// Computing masks on-the-fly reduces bytecode size by about 200 bytes.
let m := not(0)
r := x
for { let s := 128 } 1 {} {
m := xor(m, shl(s, m))
r := or(and(shr(s, r), m), and(shl(s, r), not(m)))
s := shr(1, s)
if eq(s, 4) { break }
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BOOLEAN OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// A Solidity bool on the stack or memory is represented as a 256-bit word.
// Non-zero values are true, zero is false.
// A clean bool is either 0 (false) or 1 (true) under the hood.
// Usually, if not always, the bool result of a regular Solidity expression,
// or the argument of a public/external function will be a clean bool.
// You can usually use the raw variants for more performance.
// If uncertain, test (best with exact compiler settings).
// Or use the non-raw variants (compiler can sometimes optimize out the double `iszero`s).
/// @dev Returns `x & y`. Inputs must be clean.
function rawAnd(bool x, bool y) internal pure returns (bool z) {
/// @solidity memory-safe-assembly
assembly {
z := and(x, y)
}
}
/// @dev Returns `x & y`.
function and(bool x, bool y) internal pure returns (bool z) {
/// @solidity memory-safe-assembly
assembly {
z := and(iszero(iszero(x)), iszero(iszero(y)))
}
}
/// @dev Returns `x | y`. Inputs must be clean.
function rawOr(bool x, bool y) internal pure returns (bool z) {
/// @solidity memory-safe-assembly
assembly {
z := or(x, y)
}
}
/// @dev Returns `x | y`.
function or(bool x, bool y) internal pure returns (bool z) {
/// @solidity memory-safe-assembly
assembly {
z := or(iszero(iszero(x)), iszero(iszero(y)))
}
}
/// @dev Returns 1 if `b` is true, else 0. Input must be clean.
function rawToUint(bool b) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := b
}
}
/// @dev Returns 1 if `b` is true, else 0.
function toUint(bool b) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := iszero(iszero(b))
}
}
}{
"remappings": [
"openzeppelin/=lib/openzeppelin-contracts/contracts/",
"openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"chiru-labs/ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
"solady/=lib/solady/src/",
"closedsea/=lib/closedsea/src/",
"preapprove/=lib/preapprove/src/",
"multicaller/=lib/multicaller/src/",
"@core/=contracts/core/",
"@modules/=contracts/modules/",
"forge-std/=lib/forge-std/src/",
"ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
"ds-test/=lib/solady/lib/ds-test/src/",
"erc4626-tests/=lib/closedsea/lib/openzeppelin-contracts/lib/erc4626-tests/",
"erc721a-upgradeable/=lib/multicaller/lib/erc721a-upgradeable/contracts/",
"erc721a/=lib/multicaller/lib/erc721a/contracts/",
"murky/=lib/murky/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"operator-filter-registry/=lib/closedsea/lib/operator-filter-registry/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"evmVersion": "paris",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"ArrayLengthsMismatch","type":"error"},{"inputs":[],"name":"ImplementationAddressCantBeZero","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"},{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes","name":"initData","type":"bytes"},{"indexed":false,"internalType":"address[]","name":"contracts","type":"address[]"},{"indexed":false,"internalType":"bytes[]","name":"data","type":"bytes[]"},{"indexed":false,"internalType":"bytes[]","name":"results","type":"bytes[]"}],"name":"Created","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"signer","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"nonces","type":"uint256[]"}],"name":"NoncesInvalidated","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SOUND_CREATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"c","type":"tuple"}],"name":"computeDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"c","type":"tuple"}],"name":"create","outputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"creation","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"createWithSignature","outputs":[{"internalType":"address","name":"soundEdition","type":"address"},{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"c","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"minter","type":"address"},{"internalType":"bytes","name":"mintData","type":"bytes"},{"internalType":"address","name":"refundTo","type":"address"}],"name":"createWithSignatureAndMint","outputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"separator","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nonces","type":"uint256[]"}],"name":"invalidateNonces","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"c","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"bytes","name":"mintData","type":"bytes"},{"internalType":"address","name":"refundTo","type":"address"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"name_","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"nonces","type":"uint256[]"}],"name":"noncesInvalidated","outputs":[{"internalType":"bool[]","name":"result","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"soundEditionAddress","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
61012060405234801561001157600080fd5b50306080524660a05260608061005e604080518082018252600c81526b29b7bab73221b932b0ba37b960a11b602080830191909152825180840190935260018352601960f91b9083015291565b815160209283012081519183019190912060c082905260e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8152938401929092529082015246606082015230608082015260a09020610100525050600160005560805160a05160c05160e05161010051611a3661011160003960008181610f420152610fa1015260006111a901526000611183015260006111e5015260006112080152611a366000f3fe6080604052600436106100ec5760003560e01c806354fd4d501161008a578063b9a257b211610059578063b9a257b2146102c1578063d38dfaf5146102e1578063e361d18f14610311578063f698da2514610331576100fb565b806354fd4d50146102115780637cf5b76314610226578063807c93101461025a57806384b0196e14610299576100fb565b806317447cf1116100c657806317447cf11461016f57806320606b701461019c5780632eb48a80146101de57806340a5468f146101fe576100fb565b806306fdde031461010357806308d1207f1461012e5780630ffc20c91461014f576100fb565b366100fb576100f9610346565b005b6100f9610346565b34801561010f57600080fd5b506101186103de565b6040516101259190611273565b60405180910390f35b61014161013c3660046112fc565b6103ee565b60405161012592919061140c565b34801561015b57600080fd5b5061014161016a366004611430565b610462565b34801561017b57600080fd5b5061018f61018a3660046114dc565b610490565b6040516101259190611521565b3480156101a857600080fd5b506101d07f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b604051908152602001610125565b3480156101ea57600080fd5b506100f96101f9366004611567565b610555565b6100f961020c3660046115a8565b6105ff565b34801561021d57600080fd5b50610118610623565b34801561023257600080fd5b506101d07f02851fd84c0125420e90b7716c63914a48e2932366cce89b4a7a0bcdf538d75981565b34801561026657600080fd5b5061027a61027536600461160c565b610633565b604080516001600160a01b039093168352901515602083015201610125565b3480156102a557600080fd5b506102ae6106c3565b6040516101259796959493929190611683565b3480156102cd57600080fd5b506101416102dc3660046116f3565b6106ea565b3480156102ed57600080fd5b506103016102fc366004611430565b61075a565b6040519015158152602001610125565b34801561031d57600080fd5b506101d061032c3660046116f3565b6107e3565b34801561033d57600080fd5b506101d06109e7565b3661034f573636f35b6000805b8036821061036157506103bd565b600180830192600319810190351860001a90816103ad57600019855260028301933560021984011860001a607f80821161039c578282013888395b169490940190930192506103539050565b8185538085019450505050610353565b50600080826000305af490503d6000803e806103d8573d6000fd5b503d6000f35b60606103e86109f6565b50919050565b600060606103fa610a34565b600061042661040c60208c018c611727565b61041c60408d0160208e01611727565b8c60400135610633565b9150508061043f576104398a8a8a610a92565b90935091505b61044b87878787610bc8565b506104566001600055565b97509795505050505050565b6000606061046e610a34565b610479858585610a92565b90925090506104886001600055565b935093915050565b6060816001600160401b038111156104aa576104aa611742565b6040519080825280602002602001820160405280156104d3578160200160208202803683370190505b506001600160a01b03851660009081526001602052604081209192505b80841461054c5761052285858381811061050c5761050c611758565b9050602002013583610c2990919063ffffffff16565b83828151811061053457610534611758565b911515602092830291909101909101526001016104f0565b50509392505050565b600061055f610c4b565b6001600160a01b03811660009081526001602052604081209192505b8084146105b5576105ad85858381811061059757610597611758565b9050602002013583610c8390919063ffffffff16565b60010161057b565b50816001600160a01b03167fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a485856040516105f192919061176e565b60405180910390a250505050565b610607610a34565b61061384848484610bc8565b61061d6001600055565b50505050565b606061062d6109f6565b92915050565b602082905246600c5260008181526040812081906106ac90869030604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b8152606093841b60148201526f5af43d82803e903d91602b57fd5bf3ff60801b6028820152921b6038830152604c8201526037808220606c830152605591012090565b956001600160a01b0387163b151595509350505050565b600f60f81b60608060008080836106d86109f6565b97989097965046955030945091925090565b600060606106f6610a34565b6106fe610c4b565b6001600160a01b03166107176040850160208601611727565b6001600160a01b03161461073d576040516282b42960e81b815260040160405180910390fd5b61074683610cac565b90925090506107556001600055565b915091565b600061077f61076f6040860160208701611727565b610778866107e3565b8585610e95565b80156107db57506107d960c0850135600160006107a26040890160208a01611727565b6001600160a01b0316815260208082019290925260409081016000908120600885901c825290925290205460ff9091161c60011690565b155b949350505050565b60008036816107f560a08601866117a7565b9092509050806000816001600160401b0381111561081557610815611742565b60405190808252806020026020018201604052801561083e578160200160208202803683370190505b50905060005b8281146108aa5784848281811061085d5761085d611758565b905060200281019061086f91906117f0565b60405161087d929190611836565b604051809103902082828151811061089757610897611758565b6020908102919091010152600101610844565b50806040516020016108bc9190611846565b604051602081830303815290604052805190602001209450505050506109e07f02851fd84c0125420e90b7716c63914a48e2932366cce89b4a7a0bcdf538d75984600001602081019061090f9190611727565b61091f6040870160208801611727565b604087013561093160608901896117f0565b60405161093f929190611836565b60405190819003902061095560808a018a6117a7565b60405160200161096692919061187c565b60408051601f198184030181528282528051602091820120908301979097526001600160a01b0395861690820152939092166060840152608083015260a082015260c08082019290925260e08101849052908501356101008201526101200160405160208183030381529060405280519060200120610f3e565b9392505050565b60006109f1610f9f565b905090565b604080518082018252600c81526b29b7bab73221b932b0ba37b960a11b602080830191909152825180840190935260018352601960f91b9083015291565b600260005403610a8b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055565b60006060610aa185858561075a565b610abe57604051638baa579f60e01b815260040160405180910390fd5b610ac785610cac565b9092509050610b2660c086013560016000610ae860408a0160208b01611727565b6001600160a01b0316815260208082019290925260409081016000908120600885901c825290925290208054600160ff9093169290921b9091179055565b604080516001808252818301909252600091602080830190803683370190505090508560c0013581600081518110610b6057610b60611758565b602002602001018181525050856020016020810190610b7f9190611727565b6001600160a01b03167fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a482604051610bb791906118bc565b60405180910390a250935093915050565b6001600160a01b0384161561061d5760405182848237600080848334895af1610bf5573d6000803e3d6000fd5b506001600160a01b0381161561061d57471561061d576000196001600160a01b03821601610c205750335b61061d81610fd8565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b6000336000526e2fd5aeb385d324b580fca7c83823a0803303610c7b5760206000806000845afa610c7b57600080fd5b505060005190565b600881901c600090815260209290925260409091208054600160ff9093169290921b9091179055565b6000606081610cbe6020850185611727565b6001600160a01b031603610ce557604051639841ec5160e01b815260040160405180910390fd5b610d23610cf56020850185611727565b610d1e610d086040870160208801611727565b60205246600c5260408087013560009081522090565b61100c565b9150366000610d3560608601866117f0565b915091506040518183823760008083836000895af1610d58573d6000803e3d6000fd5b50610d7b610d6960808701876117a7565b610d7660a08901896117a7565b6110ac565b92506001600160a01b03841663f2fde38b610d9c6040880160208901611727565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015610ddd57600080fd5b505af1158015610df1573d6000803e3d6000fd5b50610e06925050506040860160208701611727565b6001600160a01b03908116908516610e216020880188611727565b6001600160a01b03167fe94db3a31c09b7894f023c1f9114859672be916ffa8282215d7d43595bdcb3e7610e5860608a018a6117f0565b610e6560808c018c6117a7565b610e7260a08e018e6117a7565b8c604051610e8697969594939291906118f8565b60405180910390a45050915091565b6001600160a01b0390931692600084156107db5760405160418303610ef35784600052604084013560001a602052604084604037602060016080600060015afa805187183d1517610ef1575060006060526040525060016107db565b505b600060605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa905190911416915050949350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000610f696111e2565b15610f7957610f7661115a565b90505b67190100000000000060005280601a5282603a52604260182091506000603a5250919050565b7f0000000000000000000000000000000000000000000000000000000000000000610fc86111e2565b15610fd5576109f161115a565b90565b60005a60005a4785620186a0f161100957806000526073600b5360ff6020536016600b47f0611009575a60141c3d5a3e5b50565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152826037826000f59150506001600160a01b03811661062d5760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606401610a82565b60608382146110ce57604051631dc0052360e11b815260040160405180910390fd5b6040519050818152602081018260051b84018360051b8201855b82811461114b578035870180356020820184378782038a01356000808335866000855af161111a573d6000803e3d6000fd5b50508184526020840193503d82523d6000602084013e3d91909101603f0167ffffffffffffffe016906020016110e8565b50604052509095945050505050565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f00000000000000000000000000000000000000000000000000000000000000009181019190915246606082015230608082015260a0902090565b467f000000000000000000000000000000000000000000000000000000000000000014307f000000000000000000000000000000000000000000000000000000000000000014161590565b6000815180845260005b8181101561125357602081850181015186830182015201611237565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006109e0602083018461122d565b600060e082840312156103e857600080fd5b60008083601f8401126112aa57600080fd5b5081356001600160401b038111156112c157600080fd5b6020830191508360208285010111156112d957600080fd5b9250929050565b80356001600160a01b03811681146112f757600080fd5b919050565b600080600080600080600060a0888a03121561131757600080fd5b87356001600160401b038082111561132e57600080fd5b61133a8b838c01611286565b985060208a013591508082111561135057600080fd5b61135c8b838c01611298565b909850965086915061137060408b016112e0565b955060608a013591508082111561138657600080fd5b506113938a828b01611298565b90945092506113a69050608089016112e0565b905092959891949750929550565b600082825180855260208086019550808260051b84010181860160005b848110156113ff57601f198684030189526113ed83835161122d565b988401989250908301906001016113d1565b5090979650505050505050565b6001600160a01b03831681526040602082018190526000906107db908301846113b4565b60008060006040848603121561144557600080fd5b83356001600160401b038082111561145c57600080fd5b61146887838801611286565b9450602086013591508082111561147e57600080fd5b5061148b86828701611298565b9497909650939450505050565b60008083601f8401126114aa57600080fd5b5081356001600160401b038111156114c157600080fd5b6020830191508360208260051b85010111156112d957600080fd5b6000806000604084860312156114f157600080fd5b6114fa846112e0565b925060208401356001600160401b0381111561151557600080fd5b61148b86828701611498565b6020808252825182820181905260009190848201906040850190845b8181101561155b57835115158352928401929184019160010161153d565b50909695505050505050565b6000806020838503121561157a57600080fd5b82356001600160401b0381111561159057600080fd5b61159c85828601611498565b90969095509350505050565b600080600080606085870312156115be57600080fd5b6115c7856112e0565b935060208501356001600160401b038111156115e257600080fd5b6115ee87828801611298565b90945092506116019050604086016112e0565b905092959194509250565b60008060006060848603121561162157600080fd5b61162a846112e0565b9250611638602085016112e0565b9150604084013590509250925092565b600081518084526020808501945080840160005b838110156116785781518752958201959082019060010161165c565b509495945050505050565b60ff60f81b8816815260e0602082015260006116a260e083018961122d565b82810360408401526116b4818961122d565b606084018890526001600160a01b038716608085015260a0840186905283810360c085015290506116e58185611648565b9a9950505050505050505050565b60006020828403121561170557600080fd5b81356001600160401b0381111561171b57600080fd5b6107db84828501611286565b60006020828403121561173957600080fd5b6109e0826112e0565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6020808252810182905260006001600160fb1b0383111561178e57600080fd5b8260051b80856040850137919091016040019392505050565b6000808335601e198436030181126117be57600080fd5b8301803591506001600160401b038211156117d857600080fd5b6020019150600581901b36038213156112d957600080fd5b6000808335601e1984360301811261180757600080fd5b8301803591506001600160401b0382111561182157600080fd5b6020019150368190038213156112d957600080fd5b8183823760009101908152919050565b815160009082906020808601845b8381101561187057815185529382019390820190600101611854565b50929695505050505050565b60008184825b858110156118b1576001600160a01b0361189b836112e0565b1683526020928301929190910190600101611882565b509095945050505050565b6020815260006109e06020830184611648565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60808152600061190c60808301898b6118cf565b8281036020848101919091528782528891810160005b8981101561194e576001600160a01b0361193b856112e0565b1682529282019290820190600101611922565b5084810360408601528681528181019250600587901b810182018860005b898110156119db57838303601f190186528135368c9003601e1901811261199257600080fd5b8b0185810190356001600160401b038111156119ad57600080fd5b8036038213156119bc57600080fd5b6119c78582846118cf565b97870197945050509084019060010161196c565b505085810360608701526119ef81886113b4565b9d9c5050505050505050505050505056fea2646970667358221220d594684cddf3261cd3a8d49bc981d492299a30b7d35d1bd5669ccd0bcc4c29dd64736f6c63430008130033
Deployed Bytecode
0x6080604052600436106100ec5760003560e01c806354fd4d501161008a578063b9a257b211610059578063b9a257b2146102c1578063d38dfaf5146102e1578063e361d18f14610311578063f698da2514610331576100fb565b806354fd4d50146102115780637cf5b76314610226578063807c93101461025a57806384b0196e14610299576100fb565b806317447cf1116100c657806317447cf11461016f57806320606b701461019c5780632eb48a80146101de57806340a5468f146101fe576100fb565b806306fdde031461010357806308d1207f1461012e5780630ffc20c91461014f576100fb565b366100fb576100f9610346565b005b6100f9610346565b34801561010f57600080fd5b506101186103de565b6040516101259190611273565b60405180910390f35b61014161013c3660046112fc565b6103ee565b60405161012592919061140c565b34801561015b57600080fd5b5061014161016a366004611430565b610462565b34801561017b57600080fd5b5061018f61018a3660046114dc565b610490565b6040516101259190611521565b3480156101a857600080fd5b506101d07f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b604051908152602001610125565b3480156101ea57600080fd5b506100f96101f9366004611567565b610555565b6100f961020c3660046115a8565b6105ff565b34801561021d57600080fd5b50610118610623565b34801561023257600080fd5b506101d07f02851fd84c0125420e90b7716c63914a48e2932366cce89b4a7a0bcdf538d75981565b34801561026657600080fd5b5061027a61027536600461160c565b610633565b604080516001600160a01b039093168352901515602083015201610125565b3480156102a557600080fd5b506102ae6106c3565b6040516101259796959493929190611683565b3480156102cd57600080fd5b506101416102dc3660046116f3565b6106ea565b3480156102ed57600080fd5b506103016102fc366004611430565b61075a565b6040519015158152602001610125565b34801561031d57600080fd5b506101d061032c3660046116f3565b6107e3565b34801561033d57600080fd5b506101d06109e7565b3661034f573636f35b6000805b8036821061036157506103bd565b600180830192600319810190351860001a90816103ad57600019855260028301933560021984011860001a607f80821161039c578282013888395b169490940190930192506103539050565b8185538085019450505050610353565b50600080826000305af490503d6000803e806103d8573d6000fd5b503d6000f35b60606103e86109f6565b50919050565b600060606103fa610a34565b600061042661040c60208c018c611727565b61041c60408d0160208e01611727565b8c60400135610633565b9150508061043f576104398a8a8a610a92565b90935091505b61044b87878787610bc8565b506104566001600055565b97509795505050505050565b6000606061046e610a34565b610479858585610a92565b90925090506104886001600055565b935093915050565b6060816001600160401b038111156104aa576104aa611742565b6040519080825280602002602001820160405280156104d3578160200160208202803683370190505b506001600160a01b03851660009081526001602052604081209192505b80841461054c5761052285858381811061050c5761050c611758565b9050602002013583610c2990919063ffffffff16565b83828151811061053457610534611758565b911515602092830291909101909101526001016104f0565b50509392505050565b600061055f610c4b565b6001600160a01b03811660009081526001602052604081209192505b8084146105b5576105ad85858381811061059757610597611758565b9050602002013583610c8390919063ffffffff16565b60010161057b565b50816001600160a01b03167fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a485856040516105f192919061176e565b60405180910390a250505050565b610607610a34565b61061384848484610bc8565b61061d6001600055565b50505050565b606061062d6109f6565b92915050565b602082905246600c5260008181526040812081906106ac90869030604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b8152606093841b60148201526f5af43d82803e903d91602b57fd5bf3ff60801b6028820152921b6038830152604c8201526037808220606c830152605591012090565b956001600160a01b0387163b151595509350505050565b600f60f81b60608060008080836106d86109f6565b97989097965046955030945091925090565b600060606106f6610a34565b6106fe610c4b565b6001600160a01b03166107176040850160208601611727565b6001600160a01b03161461073d576040516282b42960e81b815260040160405180910390fd5b61074683610cac565b90925090506107556001600055565b915091565b600061077f61076f6040860160208701611727565b610778866107e3565b8585610e95565b80156107db57506107d960c0850135600160006107a26040890160208a01611727565b6001600160a01b0316815260208082019290925260409081016000908120600885901c825290925290205460ff9091161c60011690565b155b949350505050565b60008036816107f560a08601866117a7565b9092509050806000816001600160401b0381111561081557610815611742565b60405190808252806020026020018201604052801561083e578160200160208202803683370190505b50905060005b8281146108aa5784848281811061085d5761085d611758565b905060200281019061086f91906117f0565b60405161087d929190611836565b604051809103902082828151811061089757610897611758565b6020908102919091010152600101610844565b50806040516020016108bc9190611846565b604051602081830303815290604052805190602001209450505050506109e07f02851fd84c0125420e90b7716c63914a48e2932366cce89b4a7a0bcdf538d75984600001602081019061090f9190611727565b61091f6040870160208801611727565b604087013561093160608901896117f0565b60405161093f929190611836565b60405190819003902061095560808a018a6117a7565b60405160200161096692919061187c565b60408051601f198184030181528282528051602091820120908301979097526001600160a01b0395861690820152939092166060840152608083015260a082015260c08082019290925260e08101849052908501356101008201526101200160405160208183030381529060405280519060200120610f3e565b9392505050565b60006109f1610f9f565b905090565b604080518082018252600c81526b29b7bab73221b932b0ba37b960a11b602080830191909152825180840190935260018352601960f91b9083015291565b600260005403610a8b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055565b60006060610aa185858561075a565b610abe57604051638baa579f60e01b815260040160405180910390fd5b610ac785610cac565b9092509050610b2660c086013560016000610ae860408a0160208b01611727565b6001600160a01b0316815260208082019290925260409081016000908120600885901c825290925290208054600160ff9093169290921b9091179055565b604080516001808252818301909252600091602080830190803683370190505090508560c0013581600081518110610b6057610b60611758565b602002602001018181525050856020016020810190610b7f9190611727565b6001600160a01b03167fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a482604051610bb791906118bc565b60405180910390a250935093915050565b6001600160a01b0384161561061d5760405182848237600080848334895af1610bf5573d6000803e3d6000fd5b506001600160a01b0381161561061d57471561061d576000196001600160a01b03821601610c205750335b61061d81610fd8565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b6000336000526e2fd5aeb385d324b580fca7c83823a0803303610c7b5760206000806000845afa610c7b57600080fd5b505060005190565b600881901c600090815260209290925260409091208054600160ff9093169290921b9091179055565b6000606081610cbe6020850185611727565b6001600160a01b031603610ce557604051639841ec5160e01b815260040160405180910390fd5b610d23610cf56020850185611727565b610d1e610d086040870160208801611727565b60205246600c5260408087013560009081522090565b61100c565b9150366000610d3560608601866117f0565b915091506040518183823760008083836000895af1610d58573d6000803e3d6000fd5b50610d7b610d6960808701876117a7565b610d7660a08901896117a7565b6110ac565b92506001600160a01b03841663f2fde38b610d9c6040880160208901611727565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015610ddd57600080fd5b505af1158015610df1573d6000803e3d6000fd5b50610e06925050506040860160208701611727565b6001600160a01b03908116908516610e216020880188611727565b6001600160a01b03167fe94db3a31c09b7894f023c1f9114859672be916ffa8282215d7d43595bdcb3e7610e5860608a018a6117f0565b610e6560808c018c6117a7565b610e7260a08e018e6117a7565b8c604051610e8697969594939291906118f8565b60405180910390a45050915091565b6001600160a01b0390931692600084156107db5760405160418303610ef35784600052604084013560001a602052604084604037602060016080600060015afa805187183d1517610ef1575060006060526040525060016107db565b505b600060605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa905190911416915050949350505050565b60007ff925c052d7deab5d3e4719e7b25c61cc3fd165a61b045233d6fc4cbce22d85cc610f696111e2565b15610f7957610f7661115a565b90505b67190100000000000060005280601a5282603a52604260182091506000603a5250919050565b7ff925c052d7deab5d3e4719e7b25c61cc3fd165a61b045233d6fc4cbce22d85cc610fc86111e2565b15610fd5576109f161115a565b90565b60005a60005a4785620186a0f161100957806000526073600b5360ff6020536016600b47f0611009575a60141c3d5a3e5b50565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152826037826000f59150506001600160a01b03811661062d5760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606401610a82565b60608382146110ce57604051631dc0052360e11b815260040160405180910390fd5b6040519050818152602081018260051b84018360051b8201855b82811461114b578035870180356020820184378782038a01356000808335866000855af161111a573d6000803e3d6000fd5b50508184526020840193503d82523d6000602084013e3d91909101603f0167ffffffffffffffe016906020016110e8565b50604052509095945050505050565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f055447914107b5dcd4afdd0a0ec9b0df7575160486e48acf346f43310273a5fa60208201527fad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a59181019190915246606082015230608082015260a0902090565b467f000000000000000000000000000000000000000000000000000000000000000114307f0000000000000000000000000000000000aec84f5bfc2af15eafb943bf4e352214161590565b6000815180845260005b8181101561125357602081850181015186830182015201611237565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006109e0602083018461122d565b600060e082840312156103e857600080fd5b60008083601f8401126112aa57600080fd5b5081356001600160401b038111156112c157600080fd5b6020830191508360208285010111156112d957600080fd5b9250929050565b80356001600160a01b03811681146112f757600080fd5b919050565b600080600080600080600060a0888a03121561131757600080fd5b87356001600160401b038082111561132e57600080fd5b61133a8b838c01611286565b985060208a013591508082111561135057600080fd5b61135c8b838c01611298565b909850965086915061137060408b016112e0565b955060608a013591508082111561138657600080fd5b506113938a828b01611298565b90945092506113a69050608089016112e0565b905092959891949750929550565b600082825180855260208086019550808260051b84010181860160005b848110156113ff57601f198684030189526113ed83835161122d565b988401989250908301906001016113d1565b5090979650505050505050565b6001600160a01b03831681526040602082018190526000906107db908301846113b4565b60008060006040848603121561144557600080fd5b83356001600160401b038082111561145c57600080fd5b61146887838801611286565b9450602086013591508082111561147e57600080fd5b5061148b86828701611298565b9497909650939450505050565b60008083601f8401126114aa57600080fd5b5081356001600160401b038111156114c157600080fd5b6020830191508360208260051b85010111156112d957600080fd5b6000806000604084860312156114f157600080fd5b6114fa846112e0565b925060208401356001600160401b0381111561151557600080fd5b61148b86828701611498565b6020808252825182820181905260009190848201906040850190845b8181101561155b57835115158352928401929184019160010161153d565b50909695505050505050565b6000806020838503121561157a57600080fd5b82356001600160401b0381111561159057600080fd5b61159c85828601611498565b90969095509350505050565b600080600080606085870312156115be57600080fd5b6115c7856112e0565b935060208501356001600160401b038111156115e257600080fd5b6115ee87828801611298565b90945092506116019050604086016112e0565b905092959194509250565b60008060006060848603121561162157600080fd5b61162a846112e0565b9250611638602085016112e0565b9150604084013590509250925092565b600081518084526020808501945080840160005b838110156116785781518752958201959082019060010161165c565b509495945050505050565b60ff60f81b8816815260e0602082015260006116a260e083018961122d565b82810360408401526116b4818961122d565b606084018890526001600160a01b038716608085015260a0840186905283810360c085015290506116e58185611648565b9a9950505050505050505050565b60006020828403121561170557600080fd5b81356001600160401b0381111561171b57600080fd5b6107db84828501611286565b60006020828403121561173957600080fd5b6109e0826112e0565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6020808252810182905260006001600160fb1b0383111561178e57600080fd5b8260051b80856040850137919091016040019392505050565b6000808335601e198436030181126117be57600080fd5b8301803591506001600160401b038211156117d857600080fd5b6020019150600581901b36038213156112d957600080fd5b6000808335601e1984360301811261180757600080fd5b8301803591506001600160401b0382111561182157600080fd5b6020019150368190038213156112d957600080fd5b8183823760009101908152919050565b815160009082906020808601845b8381101561187057815185529382019390820190600101611854565b50929695505050505050565b60008184825b858110156118b1576001600160a01b0361189b836112e0565b1683526020928301929190910190600101611882565b509095945050505050565b6020815260006109e06020830184611648565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60808152600061190c60808301898b6118cf565b8281036020848101919091528782528891810160005b8981101561194e576001600160a01b0361193b856112e0565b1682529282019290820190600101611922565b5084810360408601528681528181019250600587901b810182018860005b898110156119db57838303601f190186528135368c9003601e1901811261199257600080fd5b8b0185810190356001600160401b038111156119ad57600080fd5b8036038213156119bc57600080fd5b6119c78582846118cf565b97870197945050509084019060010161196c565b505085810360608701526119ef81886113b4565b9d9c5050505050505050505050505056fea2646970667358221220d594684cddf3261cd3a8d49bc981d492299a30b7d35d1bd5669ccd0bcc4c29dd64736f6c63430008130033
Deployed Bytecode Sourcemap
881:17100:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4448:19;:17;:19::i;:::-;881:17100;;4318:19;:17;:19::i;7174:112::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3211:568;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;2637:277::-;;;;;;;;;;-1:-1:-1;2637:277:0;;;;;:::i;:::-;;:::i;6706:384::-;;;;;;;;;;-1:-1:-1;6706:384:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1721:58::-;;;;;;;;;;-1:-1:-1;1721:58:0;1250:66:6;1721:58:0;;;;;5817:25:12;;;5805:2;5790:18;1721:58:0;5671:177:12;3836:377:0;;;;;;;;;;-1:-1:-1;3836:377:0;;;;;:::i;:::-;;:::i;2971:183::-;;;;;;:::i;:::-;;:::i;7343:121::-;;;;;;;;;;;;;:::i;1250:394::-;;;;;;;;;;;;1335:309;1250:394;;4724:315;;;;;;;;;;-1:-1:-1;4724:315:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;7376:32:12;;;7358:51;;7452:14;;7445:22;7440:2;7425:18;;7418:50;7331:18;4724:315:0;7190:284:12;6926:596:6;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;2347:233:0:-;;;;;;;;;;-1:-1:-1;2347:233:0;;;;;:::i;:::-;;:::i;5096:440::-;;;;;;;;;;-1:-1:-1;5096:440:0;;;;;:::i;:::-;;:::i;:::-;;;9381:14:12;;9374:22;9356:41;;9344:2;9329:18;5096:440:0;9216:187:12;5593:1056:0;;;;;;;;;;-1:-1:-1;5593:1056:0;;;;;:::i;:::-;;:::i;7521:116::-;;;;;;;;;;;;;:::i;11272:1120:9:-;11346:14;11336:68;;11346:14;;11364:38;11336:68;11426:1;;11503:628;11522:21;11346:14;11525:1;11522:21;;;-1:-1:-1;;;11522:21:9;11643:1;11636:9;;;;-1:-1:-1;;11586:9:9;;11597:15;;11582:31;11426:1;11574:40;;;11662:394;;-1:-1:-1;;11856:17:9;;11718:9;11772;;;11729:15;-1:-1:-1;;11718:9:9;;11714:31;11426:1;11706:40;11910:4;11904:11;;;11894:61;;11643:1;11947;11943:9;11931:10;11928:1;11919:34;11894:61;11992:12;11981:28;;;;;;;;-1:-1:-1;11503:628:9;;-1:-1:-1;11503:628:9;11662:394;12084:1;12081;12073:13;11643:1;12112;12108:9;12103:14;;;;;11503:628;;;11507:14;11426:1;;12196;11426;12179:9;12172:5;12159:51;12144:66;;12250:16;11426:1;;12223:44;12290:7;12280:53;;12314:16;11426:1;12301:30;12280:53;;12359:16;11426:1;12346:30;7174:112:0;7213:19;7256:23;:21;:23::i;:::-;-1:-1:-1;7244:35:0;7174:112;-1:-1:-1;7174:112:0:o;3211:568::-;3443:15;3460:22;2246:21:4;:19;:21::i;:::-;3582:11:0::1;3597:54;3617:16;;::::0;::::1;:1:::0;:16:::1;:::i;:::-;3635:7;::::0;;;::::1;::::0;::::1;;:::i;:::-;3644:1;:6;;;3597:19;:54::i;:::-;3579:72;;;3666:6;3661:68;;3695:34;3716:1;3719:9;;3695:20;:34::i;:::-;3674:55:::0;;-1:-1:-1;3674:55:0;-1:-1:-1;3661:68:0::1;3739:33;3745:6;3753:8;;3763;3739:5;:33::i;:::-;3484:295;2288:20:4::0;1701:1;2790:7;:22;2610:209;2288:20;3211:568:0;;;;;;;;;;:::o;2637:277::-;2780:20;2802:22;2246:21:4;:19;:21::i;:::-;2866:41:0::1;2887:8;2897:9;;2866:20;:41::i;:::-;2840:67:::0;;-1:-1:-1;2840:67:0;-1:-1:-1;2288:20:4;1701:1;2790:7;:22;2610:209;2288:20;2637:277:0;;;;;;:::o;6706:384::-;6799:20;6875:6;-1:-1:-1;;;;;6864:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6864:25:0;-1:-1:-1;;;;;;6932:26:0;;6903;6932;;;:18;:26;;;;;6855:34;;-1:-1:-1;6972:102:0;6988:18;;;6972:102;;7043:16;7049:6;;7056:1;7049:9;;;;;;;:::i;:::-;;;;;;;7043:1;:5;;:16;;;;:::i;:::-;7031:6;7038:1;7031:9;;;;;;;;:::i;:::-;:28;;;:9;;;;;;;;;;;:28;7008:3;;6972:102;;;;6831:253;6706:384;;;;;:::o;3836:377::-;3932:14;3949:23;:21;:23::i;:::-;-1:-1:-1;;;;;4015:26:0;;3986;4015;;;:18;:26;;;;;3932:40;;-1:-1:-1;4055:90:0;4071:18;;;4055:90;;4114:16;4120:6;;4127:1;4120:9;;;;;;;:::i;:::-;;;;;;;4114:1;:5;;:16;;;;:::i;:::-;4091:3;;4055:90;;;;4181:6;-1:-1:-1;;;;;4163:33:0;;4189:6;;4163:33;;;;;;;:::i;:::-;;;;;;;;3908:299;;3836:377;;:::o;2971:183::-;2246:21:4;:19;:21::i;:::-;3114:33:0::1;3120:6;3128:8;;3138;3114:5;:33::i;:::-;2288:20:4::0;1701:1;2790:7;:22;2610:209;2288:20;2971:183:0;;;;:::o;7343:121::-;7385:22;7434:23;:21;:23::i;:::-;7419:38;7343:121;-1:-1:-1;;7343:121:0:o;4724:315::-;12746:4;12739:19;;;12784:9;12778:4;12771:23;4857:12;12807:18;;;12864:4;12848:21;;4857:12;;4901:91;;4936:14;;4986:4;2867::3;2861:11;-1:-1:-1;;;2885:79:3;;3004:4;3000:25;;;2993:4;2984:14;;2977:49;-1:-1:-1;;;3055:4:3;3046:14;;3039:90;3165:19;;3158:4;3149:14;;3142:43;3214:4;3205:14;;3198:28;3277:4;3262:20;;;3255:4;3246:14;;3239:44;3335:4;3319:14;;3309:31;;2609:747;4901:91:0;4894:98;-1:-1:-1;;;;;5011:16:0;;;:21;;;-1:-1:-1;4724:315:0;-1:-1:-1;;;;4724:315:0:o;6926:596:6:-;-1:-1:-1;;;7051:18:6;;7024:13;;;7051:18;7322:23;:21;:23::i;:::-;6926:596;;7304:41;;;-1:-1:-1;7365:13:6;;-1:-1:-1;7416:4:6;;-1:-1:-1;6926:596:6;;-1:-1:-1;6926:596:6;:::o;2347:233:0:-;2420:15;2437:22;2246:21:4;:19;:21::i;:::-;2486:23:0::1;:21;:23::i;:::-;-1:-1:-1::0;;;;;2475:34:0::1;:7;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;2475:34:0::1;;2471:61;;2518:14;;-1:-1:-1::0;;;2518:14:0::1;;;;;;;;;;;2471:61;2563:10;2571:1;2563:7;:10::i;:::-;2542:31:::0;;-1:-1:-1;2542:31:0;-1:-1:-1;2288:20:4;1701:1;2790:7;:22;2610:209;2288:20;2347:233:0;;;:::o;5096:440::-;5195:4;5319:85;5367:7;;;;;;;;:::i;:::-;5376:16;5390:1;5376:13;:16::i;:::-;5394:9;;5319:47;:85::i;:::-;:210;;;;-1:-1:-1;5489:40:0;5521:7;;;;5489:18;:27;5508:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;5489:27:0;;;;;;;;;;;;;;;-1:-1:-1;5489:27:0;;;2024:1:8;2015:10;;;2004:22;;;;;;;;2039:4;2031:12;;;2004:40;2048:1;2003:46;;1672:479;5489:40:0;5488:41;5319:210;5211:318;5096:440;-1:-1:-1;;;;5096:440:0:o;5593:1056::-;5663:7;;5739:22;5663:7;5764:6;;;;:1;:6;:::i;:::-;5739:31;;-1:-1:-1;5739:31:0;-1:-1:-1;5739:31:0;5784:9;5739:31;-1:-1:-1;;;;;5853:16:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5853:16:0;;5822:47;;5888:9;5883:102;5908:1;5903;:6;5883:102;;5961:5;;5967:1;5961:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;5951:19;;;;;;;:::i;:::-;;;;;;;;5934:11;5946:1;5934:14;;;;;;;;:::i;:::-;;;;;;;;;;:36;5911:3;;5883:102;;;;6043:11;6026:29;;;;;;;;:::i;:::-;;;;;;;;;;;;;6016:40;;;;;;5998:58;;5715:352;;;;6095:547;1335:309;6243:1;:16;;;;;;;;;;:::i;:::-;6296:7;;;;;;;;:::i;:::-;6340:6;;;;6393:10;;;;6340:1;6393:10;:::i;:::-;6383:21;;;;;;;:::i;:::-;;;;;;;;;6466:11;;;;:1;:11;:::i;:::-;6449:29;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;6449:29:0;;;;;;;;;6439:40;;6449:29;6439:40;;;;6158:452;;;13671:25:12;;;;-1:-1:-1;;;;;13770:15:12;;;13750:18;;;13743:43;13822:15;;;;13802:18;;;13795:43;13854:18;;;13847:34;13897:19;;;13890:35;6570:7:0;13941:19:12;;;13934:35;;;;13985:19;;;13978:35;;;6570:7:0;;;;14029:19:12;;;14022:35;13643:19;;6158:452:0;;;;;;;;;;;;6127:501;;;;;;6095:14;:547::i;:::-;6076:566;5593:1056;-1:-1:-1;;;5593:1056:0:o;7521:116::-;7571:17;7612:18;:16;:18::i;:::-;7600:30;;7521:116;:::o;7970:225::-;8142:22;;;;;;;;;;;-1:-1:-1;;;8142:22:0;;;;;;;;8174:14;;;;;;;;;;;-1:-1:-1;;;8174:14:0;;;;8142:22;7970:225::o;2321:283:4:-;1744:1;2449:7;;:19;2441:63;;;;-1:-1:-1;;;2441:63:4;;14270:2:12;2441:63:4;;;14252:21:12;14309:2;14289:18;;;14282:30;14348:33;14328:18;;;14321:61;14399:18;;2441:63:4;;;;;;;;;1744:1;2579:7;:18;2321:283::o;15196:514:0:-;15312:15;15329:22;15372:30;15389:1;15392:9;;15372:16;:30::i;:::-;15367:62;;15411:18;;-1:-1:-1;;;15411:18:0;;;;;;;;;;;15367:62;15460:10;15468:1;15460:7;:10::i;:::-;15439:31;;-1:-1:-1;15439:31:0;-1:-1:-1;15533:40:0;15565:7;;;;15533:18;:27;15552:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;15533:27:0;;;;;;;;;;;;;;;-1:-1:-1;15533:27:0;;;2308:1:8;2299:10;;;2288:22;;;;;;;:47;;2315:1;2329:4;2321:12;;;2315:19;;;;2288:47;;;;;2218:124;15533:40:0;15609:16;;;15623:1;15609:16;;;;;;;;;15583:23;;15609:16;;;;;;;;;;;-1:-1:-1;15609:16:0;15583:42;;15647:1;:7;;;15635:6;15642:1;15635:9;;;;;;;;:::i;:::-;;;;;;:19;;;;;15687:1;:7;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;15669:34:0;;15696:6;15669:34;;;;;;:::i;:::-;;;;;;;;15357:353;15196:514;;;;;;:::o;16417:1562::-;-1:-1:-1;;;;;16544:20:0;;16540:33;16566:7;16540:33;16665:4;16659:11;16773:15;16756;16753:1;16740:49;17296:4;17233;17171:15;17110:1;17039:11;16985:6;16940:5;16914:441;16887:666;;17475:16;17469:4;17463;17448:44;17522:16;17516:4;17509:30;16887:666;-1:-1:-1;;;;;;17576:22:0;;;17572:401;;17786:21;:26;17782:181;;-1:-1:-1;;;;;;;17836:22:0;;;17832:49;;-1:-1:-1;17871:10:0;17832:49;17899;17939:8;17899:39;:49::i;1672:479:8:-;2024:1;2015:10;;;1746;2004:22;;;;;;;;;;;;;2048:1;2039:4;2031:12;;;2004:40;2003:46;;1672:479::o;1961:485:2:-;2002:14;2107:8;2101:4;2094:22;2147:23;2199:10;2189:8;2186:24;2183:213;;2287:4;2281;2275;2269;2257:10;2250:5;2239:53;2229:153;;2329:4;2323;2316:18;2229:153;-1:-1:-1;;2425:4:2;2419:11;;1961:485::o;2218:124:8:-;2308:1;2299:10;;;2288;:22;;;;;;;;;;;;:47;;2315:1;2329:4;2321:12;;;2315:19;;;;2288:47;;;;;2218:124::o;13245:1545:0:-;13306:15;13323:22;13306:15;13361:16;;;;:1;:16;:::i;:::-;-1:-1:-1;;;;;13361:30:0;;13357:76;;13400:33;;-1:-1:-1;;;13400:33:0;;;;;;;;;;;13357:76;13501:73;13527:16;;;;:1;:16;:::i;:::-;13545:28;13557:7;;;;;;;;:::i;:::-;12746:4;12739:19;12784:9;12778:4;12771:23;13566:6;;;;;12690:14;12807:18;;;12848:21;;12617:268;13545:28;13501:25;:73::i;:::-;13483:92;-1:-1:-1;13586:23:0;;13612:10;;;;:1;:10;:::i;:::-;13586:36;;;;13744:4;13738:11;13850:15;13833;13830:1;13817:49;14313:4;14257;14200:15;14158:1;14100;14044:7;13999:5;13973:391;13946:617;;14485:16;14479:4;14473;14458:44;14532:16;14526:4;14519:30;13946:617;-1:-1:-1;14593:35:0;14608:11;;;;:1;:11;:::i;:::-;14621:6;;;;:1;:6;:::i;:::-;14593:14;:35::i;:::-;14583:45;-1:-1:-1;;;;;;14639:34:0;;;14674:7;;;;;;;;:::i;:::-;14639:43;;-1:-1:-1;;;;;;14639:43:0;;;;;;;-1:-1:-1;;;;;14858:32:12;;;14639:43:0;;;14840:51:12;14813:18;;14639:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;14733:7:0;;-1:-1:-1;;;14733:7:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;14698:85:0;;;;;;14706:16;;;;:1;:16;:::i;:::-;-1:-1:-1;;;;;14698:85:0;;14742:10;;;;:1;:10;:::i;:::-;14754:11;;;;:1;:11;:::i;:::-;14767:6;;;;:1;:6;:::i;:::-;14775:7;14698:85;;;;;;;;;;;;:::i;:::-;;;;;;;;13347:1443;;13245:1545;;;:::o;4820:3036:11:-;-1:-1:-1;;;;;5145:24:11;;;;4960:12;5172:6;5129:2711;;;5215:4;5209:11;5261:2;5243:16;5240:24;5237:1102;;5300:4;5294;5287:18;5382:4;5364:16;5360:27;5347:41;5344:1;5339:50;5333:4;5326:64;5456:4;5438:16;5432:4;5419:42;5863:4;5809;5757;5704;5646:1;5568:5;5528:384;6083:1;6077:8;6069:6;6065:21;6046:16;6039:24;6036:51;6026:295;;-1:-1:-1;6165:1:11;6159:4;6152:15;6225:4;6218:15;-1:-1:-1;6126:1:11;6294:5;;6026:295;;5237:1102;6369:1;6363:4;6356:15;6427:1;6421:4;6414:15;6501:10;6496:3;6492:20;6539:1;6536;6529:12;6638:4;6631;6628:1;6624:12;6617:26;6676:4;6673:1;6669:12;6708:4;6705:1;6698:15;6801:16;6794:4;6791:1;6787:12;6780:38;6926:16;6908;6901:4;6898:1;6894:12;6881:62;7726:4;7674:1;7610:4;7592:16;7588:27;7528:1;7471:6;7422:5;7386:400;7140:8;;7137:15;;;7018:786;;-1:-1:-1;;4820:3036:11;;;;;;:::o;5739:840:6:-;5814:14;5997:22;6037:35;:33;:35::i;:::-;6033:76;;;6086:23;:21;:23::i;:::-;6074:35;;6033:76;6243:18;6237:4;6230:32;6309:9;6303:4;6296:23;6376:10;6370:4;6363:24;6452:4;6446;6436:21;6426:31;;6561:1;6555:4;6548:15;6181:392;5739:840;;;:::o;4781:347::-;4999:22;5039:35;:33;:35::i;:::-;5035:76;;;5088:23;:21;:23::i;5035:76::-;4781:347;:::o;6455:614:10:-;6661:4;6654:5;6648:4;6641:5;6626:13;6622:2;6600:20;6595:71;6585:468;;6699:2;6693:4;6686:16;6772:4;6766;6758:19;6828:4;6822;6814:19;6914:4;6908;6893:13;6886:33;6876:163;;6991:5;6987:2;6983:14;6965:16;6958:5;6943:55;6876:163;6455:614;:::o;1906:593:3:-;1990:16;2101:4;2095:11;-1:-1:-1;;;2126:3:3;2119:79;2244:14;2238:4;2234:25;2227:4;2222:3;2218:14;2211:49;-1:-1:-1;;;2289:4:3;2284:3;2280:14;2273:90;2410:4;2404;2399:3;2396:1;2388:27;2376:39;-1:-1:-1;;;;;;;2442:22:3;;2434:58;;;;-1:-1:-1;;;2434:58:3;;17456:2:12;2434:58:3;;;17438:21:12;17495:2;17475:18;;;17468:30;17534:25;17514:18;;;17507:53;17577:18;;2434:58:3;17254:347:12;8478:3795:0;8589:22;8631:31;;;8627:66;;8671:22;;-1:-1:-1;;;8671:22:0;;;;;;;;;;;8627:66;8929:4;8923:11;8912:22;;9029:11;9020:7;9013:28;9159:4;9150:7;9146:18;9371:11;9368:1;9364:19;9351:11;9347:37;9575:11;9572:1;9568:19;9552:14;9548:40;9708:11;9693:2450;9735:14;9732:1;9729:21;9693:2450;;9886:1;9873:15;9860:11;9856:33;10170:1;10157:15;10075:4;10072:1;10068:12;10009:1;9975:248;10569:11;10566:1;10562:19;10544:16;10540:42;10527:56;11093:4;11033;10972:1;10959:15;10886:1;10824;10778;10729:5;10699:449;10668:699;;11281:16;11275:4;11269;11254:44;11332:16;11326:4;11319:30;10668:699;;;11472:1;11456:14;11449:25;11529:4;11513:14;11509:25;11491:43;;11625:16;11622:1;11615:27;11750:16;11744:4;11737;11734:1;11730:12;11715:52;12084:16;12077:24;;;;12103:4;12073:35;12110:18;12069:60;;9766:4;9759:12;9693:2450;;;-1:-1:-1;12249:4:0;12242:15;-1:-1:-1;8478:3795:0;;;-1:-1:-1;;;;;8478:3795:0:o;7862:879:6:-;8426:4;8420:11;;8487:16;8477:27;;8264:15;8531:4;8524:12;;8517:30;8307:18;8567:12;;;8560:33;;;;8627:9;8620:4;8613:12;;8606:31;8671:9;8664:4;8657:12;;8650:31;8720:4;8707:18;;;7862:879::o;8821:340::-;9091:9;8935:14;9088:28;9121:9;8980:11;9118:25;9084:60;9077:68;;8821:340::o;14:423:12:-;56:3;94:5;88:12;121:6;116:3;109:19;146:1;156:162;170:6;167:1;164:13;156:162;;;232:4;288:13;;;284:22;;278:29;260:11;;;256:20;;249:59;185:12;156:162;;;160:3;363:1;356:4;347:6;342:3;338:16;334:27;327:38;426:4;419:2;415:7;410:2;402:6;398:15;394:29;389:3;385:39;381:50;374:57;;;14:423;;;;:::o;442:220::-;591:2;580:9;573:21;554:4;611:45;652:2;641:9;637:18;629:6;611:45;:::i;667:162::-;733:5;778:3;769:6;764:3;760:16;756:26;753:46;;;795:1;792;785:12;834:347;885:8;895:6;949:3;942:4;934:6;930:17;926:27;916:55;;967:1;964;957:12;916:55;-1:-1:-1;990:20:12;;-1:-1:-1;;;;;1022:30:12;;1019:50;;;1065:1;1062;1055:12;1019:50;1102:4;1094:6;1090:17;1078:29;;1154:3;1147:4;1138:6;1130;1126:19;1122:30;1119:39;1116:59;;;1171:1;1168;1161:12;1116:59;834:347;;;;;:::o;1186:173::-;1254:20;;-1:-1:-1;;;;;1303:31:12;;1293:42;;1283:70;;1349:1;1346;1339:12;1283:70;1186:173;;;:::o;1364:1112::-;1513:6;1521;1529;1537;1545;1553;1561;1614:3;1602:9;1593:7;1589:23;1585:33;1582:53;;;1631:1;1628;1621:12;1582:53;1671:9;1658:23;-1:-1:-1;;;;;1741:2:12;1733:6;1730:14;1727:34;;;1757:1;1754;1747:12;1727:34;1780:73;1845:7;1836:6;1825:9;1821:22;1780:73;:::i;:::-;1770:83;;1906:2;1895:9;1891:18;1878:32;1862:48;;1935:2;1925:8;1922:16;1919:36;;;1951:1;1948;1941:12;1919:36;1990:60;2042:7;2031:8;2020:9;2016:24;1990:60;:::i;:::-;2069:8;;-1:-1:-1;1964:86:12;-1:-1:-1;1964:86:12;;-1:-1:-1;2123:38:12;2157:2;2142:18;;2123:38;:::i;:::-;2113:48;;2214:2;2203:9;2199:18;2186:32;2170:48;;2243:2;2233:8;2230:16;2227:36;;;2259:1;2256;2249:12;2227:36;;2298:60;2350:7;2339:8;2328:9;2324:24;2298:60;:::i;:::-;2377:8;;-1:-1:-1;2272:86:12;-1:-1:-1;2431:39:12;;-1:-1:-1;2465:3:12;2450:19;;2431:39;:::i;:::-;2421:49;;1364:1112;;;;;;;;;;:::o;2481:591::-;2532:3;2563;2595:5;2589:12;2622:6;2617:3;2610:19;2648:4;2677:2;2672:3;2668:12;2661:19;;2733:2;2723:6;2720:1;2716:14;2709:5;2705:26;2701:35;2770:2;2763:5;2759:14;2791:1;2801:245;2815:6;2812:1;2809:13;2801:245;;;2902:2;2898:7;2890:5;2884:4;2880:16;2876:30;2871:3;2864:43;2928:38;2961:4;2952:6;2946:13;2928:38;:::i;:::-;3024:12;;;;2920:46;-1:-1:-1;2989:15:12;;;;2837:1;2830:9;2801:245;;;-1:-1:-1;3062:4:12;;2481:591;-1:-1:-1;;;;;;;2481:591:12:o;3077:374::-;-1:-1:-1;;;;;3302:32:12;;3284:51;;3371:2;3366;3351:18;;3344:30;;;-1:-1:-1;;3391:54:12;;3426:18;;3418:6;3391:54;:::i;3456:675::-;3567:6;3575;3583;3636:2;3624:9;3615:7;3611:23;3607:32;3604:52;;;3652:1;3649;3642:12;3604:52;3692:9;3679:23;-1:-1:-1;;;;;3762:2:12;3754:6;3751:14;3748:34;;;3778:1;3775;3768:12;3748:34;3801:73;3866:7;3857:6;3846:9;3842:22;3801:73;:::i;:::-;3791:83;;3927:2;3916:9;3912:18;3899:32;3883:48;;3956:2;3946:8;3943:16;3940:36;;;3972:1;3969;3962:12;3940:36;;4011:60;4063:7;4052:8;4041:9;4037:24;4011:60;:::i;:::-;3456:675;;4090:8;;-1:-1:-1;3985:86:12;;-1:-1:-1;;;;3456:675:12:o;4136:367::-;4199:8;4209:6;4263:3;4256:4;4248:6;4244:17;4240:27;4230:55;;4281:1;4278;4271:12;4230:55;-1:-1:-1;4304:20:12;;-1:-1:-1;;;;;4336:30:12;;4333:50;;;4379:1;4376;4369:12;4333:50;4416:4;4408:6;4404:17;4392:29;;4476:3;4469:4;4459:6;4456:1;4452:14;4444:6;4440:27;4436:38;4433:47;4430:67;;;4493:1;4490;4483:12;4508:511;4603:6;4611;4619;4672:2;4660:9;4651:7;4647:23;4643:32;4640:52;;;4688:1;4685;4678:12;4640:52;4711:29;4730:9;4711:29;:::i;:::-;4701:39;;4791:2;4780:9;4776:18;4763:32;-1:-1:-1;;;;;4810:6:12;4807:30;4804:50;;;4850:1;4847;4840:12;4804:50;4889:70;4951:7;4942:6;4931:9;4927:22;4889:70;:::i;5024:642::-;5189:2;5241:21;;;5311:13;;5214:18;;;5333:22;;;5160:4;;5189:2;5412:15;;;;5386:2;5371:18;;;5160:4;5455:185;5469:6;5466:1;5463:13;5455:185;;;5544:13;;5537:21;5530:29;5518:42;;5615:15;;;;5580:12;;;;5491:1;5484:9;5455:185;;;-1:-1:-1;5657:3:12;;5024:642;-1:-1:-1;;;;;;5024:642:12:o;5853:437::-;5939:6;5947;6000:2;5988:9;5979:7;5975:23;5971:32;5968:52;;;6016:1;6013;6006:12;5968:52;6056:9;6043:23;-1:-1:-1;;;;;6081:6:12;6078:30;6075:50;;;6121:1;6118;6111:12;6075:50;6160:70;6222:7;6213:6;6202:9;6198:22;6160:70;:::i;:::-;6249:8;;6134:96;;-1:-1:-1;5853:437:12;-1:-1:-1;;;;5853:437:12:o;6295:557::-;6383:6;6391;6399;6407;6460:2;6448:9;6439:7;6435:23;6431:32;6428:52;;;6476:1;6473;6466:12;6428:52;6499:29;6518:9;6499:29;:::i;:::-;6489:39;;6579:2;6568:9;6564:18;6551:32;-1:-1:-1;;;;;6598:6:12;6595:30;6592:50;;;6638:1;6635;6628:12;6592:50;6677:58;6727:7;6718:6;6707:9;6703:22;6677:58;:::i;:::-;6754:8;;-1:-1:-1;6651:84:12;-1:-1:-1;6808:38:12;;-1:-1:-1;6842:2:12;6827:18;;6808:38;:::i;:::-;6798:48;;6295:557;;;;;;;:::o;6857:328::-;6934:6;6942;6950;7003:2;6991:9;6982:7;6978:23;6974:32;6971:52;;;7019:1;7016;7009:12;6971:52;7042:29;7061:9;7042:29;:::i;:::-;7032:39;;7090:38;7124:2;7113:9;7109:18;7090:38;:::i;:::-;7080:48;;7175:2;7164:9;7160:18;7147:32;7137:42;;6857:328;;;;;:::o;7479:435::-;7532:3;7570:5;7564:12;7597:6;7592:3;7585:19;7623:4;7652:2;7647:3;7643:12;7636:19;;7689:2;7682:5;7678:14;7710:1;7720:169;7734:6;7731:1;7728:13;7720:169;;;7795:13;;7783:26;;7829:12;;;;7864:15;;;;7756:1;7749:9;7720:169;;;-1:-1:-1;7905:3:12;;7479:435;-1:-1:-1;;;;;7479:435:12:o;7919:920::-;8325:3;8320;8316:13;8308:6;8304:26;8293:9;8286:45;8367:3;8362:2;8351:9;8347:18;8340:31;8267:4;8394:46;8435:3;8424:9;8420:19;8412:6;8394:46;:::i;:::-;8488:9;8480:6;8476:22;8471:2;8460:9;8456:18;8449:50;8522:33;8548:6;8540;8522:33;:::i;:::-;8586:2;8571:18;;8564:34;;;-1:-1:-1;;;;;8635:32:12;;8629:3;8614:19;;8607:61;8655:3;8684:19;;8677:35;;;8749:22;;;8743:3;8728:19;;8721:51;8508:47;-1:-1:-1;8789:44:12;8508:47;8818:6;8789:44;:::i;:::-;8781:52;7919:920;-1:-1:-1;;;;;;;;;;7919:920:12:o;8844:367::-;8935:6;8988:2;8976:9;8967:7;8963:23;8959:32;8956:52;;;9004:1;9001;8994:12;8956:52;9044:9;9031:23;-1:-1:-1;;;;;9069:6:12;9066:30;9063:50;;;9109:1;9106;9099:12;9063:50;9132:73;9197:7;9188:6;9177:9;9173:22;9132:73;:::i;9408:186::-;9467:6;9520:2;9508:9;9499:7;9495:23;9491:32;9488:52;;;9536:1;9533;9526:12;9488:52;9559:29;9578:9;9559:29;:::i;9599:127::-;9660:10;9655:3;9651:20;9648:1;9641:31;9691:4;9688:1;9681:15;9715:4;9712:1;9705:15;9731:127;9792:10;9787:3;9783:20;9780:1;9773:31;9823:4;9820:1;9813:15;9847:4;9844:1;9837:15;9863:443;10052:2;10034:21;;;10071:18;;10064:34;;;-1:-1:-1;;;;;;10110:31:12;;10107:51;;;10154:1;10151;10144:12;10107:51;10188:6;10185:1;10181:14;10245:6;10237;10232:2;10221:9;10217:18;10204:48;10273:22;;;;10297:2;10269:31;;9863:443;-1:-1:-1;;;9863:443:12:o;10311:556::-;10415:4;10421:6;10481:11;10468:25;10575:2;10571:7;10560:8;10544:14;10540:29;10536:43;10516:18;10512:68;10502:96;;10594:1;10591;10584:12;10502:96;10621:33;;10673:20;;;-1:-1:-1;;;;;;10705:30:12;;10702:50;;;10748:1;10745;10738:12;10702:50;10781:4;10769:17;;-1:-1:-1;10832:1:12;10828:14;;;10812;10808:35;10798:46;;10795:66;;;10857:1;10854;10847:12;10872:521;10949:4;10955:6;11015:11;11002:25;11109:2;11105:7;11094:8;11078:14;11074:29;11070:43;11050:18;11046:68;11036:96;;11128:1;11125;11118:12;11036:96;11155:33;;11207:20;;;-1:-1:-1;;;;;;11239:30:12;;11236:50;;;11282:1;11279;11272:12;11236:50;11315:4;11303:17;;-1:-1:-1;11346:14:12;11342:27;;;11332:38;;11329:58;;;11383:1;11380;11373:12;11398:271;11581:6;11573;11568:3;11555:33;11537:3;11607:16;;11632:13;;;11607:16;11398:271;-1:-1:-1;11398:271:12:o;11674:543::-;11892:13;;11835:3;;11866;;11945:4;11972:15;;;11835:3;12015:175;12029:6;12026:1;12023:13;12015:175;;;12092:13;;12078:28;;12128:14;;;;12165:15;;;;12051:1;12044:9;12015:175;;;-1:-1:-1;12206:5:12;;11674:543;-1:-1:-1;;;;;;11674:543:12:o;12772:551::-;12943:3;12974;13021:6;12943:3;13055:241;13069:6;13066:1;13063:13;13055:241;;;-1:-1:-1;;;;;13136:26:12;13155:6;13136:26;:::i;:::-;13132:52;13118:67;;13208:4;13234:14;;;;13271:15;;;;;13091:1;13084:9;13055:241;;;-1:-1:-1;13312:5:12;;12772:551;-1:-1:-1;;;;;12772:551:12:o;14428:261::-;14607:2;14596:9;14589:21;14570:4;14627:56;14679:2;14668:9;14664:18;14656:6;14627:56;:::i;14902:266::-;14990:6;14985:3;14978:19;15042:6;15035:5;15028:4;15023:3;15019:14;15006:43;-1:-1:-1;15094:1:12;15069:16;;;15087:4;15065:27;;;15058:38;;;;15150:2;15129:15;;;-1:-1:-1;;15125:29:12;15116:39;;;15112:50;;14902:266::o;15173:2076::-;15622:3;15611:9;15604:22;15585:4;15649:62;15706:3;15695:9;15691:19;15683:6;15675;15649:62;:::i;:::-;15768:22;;;15730:2;15748:18;;;15741:50;;;;15826:22;;;15902:6;;15864:15;;15926:1;15936:208;15950:6;15947:1;15944:13;15936:208;;;-1:-1:-1;;;;;16015:26:12;16034:6;16015:26;:::i;:::-;16011:52;15999:65;;16119:15;;;;16084:12;;;;15972:1;15965:9;15936:208;;;-1:-1:-1;16180:19:12;;;16175:2;16160:18;;16153:47;16234:19;;;16271:12;;;;-1:-1:-1;16323:1:12;16319:14;;;16310:24;;16306:33;;16364:6;16390:1;16400:725;16416:6;16411:3;16408:15;16400:725;;;16487:16;;;-1:-1:-1;;16483:30:12;16469:45;;16553:22;;16630:14;16626:27;;;-1:-1:-1;;16622:41:12;16598:66;;16588:94;;16678:1;16675;16668:12;16588:94;16708:31;;16813:14;;;;16766:19;-1:-1:-1;;;;;16843:30:12;;16840:50;;;16886:1;16883;16876:12;16840:50;16939:6;16923:14;16919:27;16910:7;16906:41;16903:61;;;16960:1;16957;16950:12;16903:61;16987:50;17030:6;17022;17013:7;16987:50;:::i;:::-;17101:14;;;;16977:60;-1:-1:-1;;;17062:17:12;;;;16442:1;16433:11;16400:725;;;16404:3;;17173:9;17165:6;17161:22;17156:2;17145:9;17141:18;17134:50;17201:42;17236:6;17228;17201:42;:::i;:::-;17193:50;15173:2076;-1:-1:-1;;;;;;;;;;;;;15173:2076:12:o
Swarm Source
ipfs://d594684cddf3261cd3a8d49bc981d492299a30b7d35d1bd5669ccd0bcc4c29dd
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.