Feature Tip: Add private address tag to any address under My Name Tag !
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 | 50 days ago | IN | 0 ETH | 0.0033176 | ||||
Create | 21234906 | 54 days ago | IN | 0 ETH | 0.00483678 | ||||
Create | 21183635 | 61 days ago | IN | 0 ETH | 0.01569172 | ||||
Create | 21183593 | 61 days ago | IN | 0 ETH | 0.0164765 | ||||
Create | 21183488 | 61 days ago | IN | 0 ETH | 0.01875013 | ||||
Create | 21017914 | 84 days ago | IN | 0 ETH | 0.00332593 | ||||
Create | 21012370 | 85 days ago | IN | 0 ETH | 0.00431428 | ||||
Create | 20709444 | 127 days ago | IN | 0 ETH | 0.00070942 | ||||
Create | 20640643 | 137 days ago | IN | 0 ETH | 0.00068838 | ||||
Create | 20627362 | 139 days ago | IN | 0 ETH | 0.00081077 | ||||
Create | 20622604 | 140 days ago | IN | 0 ETH | 0.00108301 | ||||
Create | 20619883 | 140 days ago | IN | 0 ETH | 0.00084685 | ||||
Create | 20619829 | 140 days ago | IN | 0 ETH | 0.0009084 | ||||
Create | 20619755 | 140 days ago | IN | 0 ETH | 0.00072183 | ||||
Create | 20619702 | 140 days ago | IN | 0 ETH | 0.00068855 | ||||
Create | 20619601 | 140 days ago | IN | 0 ETH | 0.00102334 | ||||
Create | 20619443 | 140 days ago | IN | 0 ETH | 0.0007169 | ||||
Create | 20584974 | 145 days ago | IN | 0 ETH | 0.00133455 | ||||
Create | 20542167 | 151 days ago | IN | 0 ETH | 0.00295709 | ||||
Create | 20453329 | 163 days ago | IN | 0 ETH | 0.00063235 | ||||
Create | 20452377 | 163 days ago | IN | 0 ETH | 0.00080544 | ||||
Create | 20414729 | 169 days ago | IN | 0 ETH | 0.00147133 | ||||
Create | 20371214 | 175 days ago | IN | 0 ETH | 0.00375897 | ||||
Create | 20328964 | 180 days ago | IN | 0 ETH | 0.00260068 | ||||
Create | 20281425 | 187 days ago | IN | 0 ETH | 0.00107724 |
Latest 25 internal transactions (View All)
Advanced mode:
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
[{"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
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.