Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 3,549 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Buy | 21826257 | 3 hrs ago | IN | 0.015 ETH | 0.00022043 | ||||
Buy | 21823561 | 12 hrs ago | IN | 0.05 ETH | 0.00034118 | ||||
Buy | 21823548 | 12 hrs ago | IN | 0.015 ETH | 0.00032756 | ||||
Buy | 21816419 | 36 hrs ago | IN | 0.04 ETH | 0.00022502 | ||||
Buy | 21816398 | 36 hrs ago | IN | 0.11 ETH | 0.00024923 | ||||
Buy | 21816267 | 36 hrs ago | IN | 0.09 ETH | 0.00024819 | ||||
Buy | 21816241 | 37 hrs ago | IN | 0.015 ETH | 0.0003006 | ||||
Buy | 21815204 | 40 hrs ago | IN | 0.09 ETH | 0.00025987 | ||||
Buy | 21810672 | 2 days ago | IN | 0.015 ETH | 0.00023257 | ||||
Buy | 21810664 | 2 days ago | IN | 0.11 ETH | 0.00014529 | ||||
Buy | 21810616 | 2 days ago | IN | 0.04 ETH | 0.00023737 | ||||
Buy | 21810601 | 2 days ago | IN | 0.05 ETH | 0.00021618 | ||||
Buy | 21809215 | 2 days ago | IN | 0.11 ETH | 0.00024346 | ||||
Buy | 21807427 | 2 days ago | IN | 0.05 ETH | 0.00024322 | ||||
Buy | 21803959 | 3 days ago | IN | 0.015 ETH | 0.00017845 | ||||
Buy | 21802903 | 3 days ago | IN | 0.11 ETH | 0.00026199 | ||||
Buy | 21799228 | 3 days ago | IN | 0.05 ETH | 0.00025391 | ||||
Buy | 21797083 | 4 days ago | IN | 0.015 ETH | 0.00050948 | ||||
Buy | 21797049 | 4 days ago | IN | 0.015 ETH | 0.00061747 | ||||
Buy | 21796728 | 4 days ago | IN | 0.11 ETH | 0.00033826 | ||||
Buy | 21795014 | 4 days ago | IN | 0.09 ETH | 0.00046049 | ||||
Buy | 21792273 | 4 days ago | IN | 0.05 ETH | 0.00025721 | ||||
Buy | 21789438 | 5 days ago | IN | 0.05 ETH | 0.00070036 | ||||
Buy | 21788682 | 5 days ago | IN | 0.09 ETH | 0.0010802 | ||||
Withdraw | 21787083 | 5 days ago | IN | 0 ETH | 0.00008507 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21815641 | 39 hrs ago | 0.1 ETH | ||||
21814261 | 43 hrs ago | 0.04 ETH | ||||
21796620 | 4 days ago | 0.1 ETH | ||||
21787083 | 5 days ago | 0.8 ETH | ||||
21787081 | 5 days ago | 2.5 ETH | ||||
21787078 | 5 days ago | 0.95 ETH | ||||
21787074 | 5 days ago | 0.465 ETH | ||||
21787072 | 5 days ago | 1.65 ETH | ||||
21787070 | 5 days ago | 0.225 ETH | ||||
21787061 | 5 days ago | 1.53 ETH | ||||
21787050 | 5 days ago | 0.15 ETH | ||||
21783269 | 6 days ago | 0.87 ETH | ||||
21742906 | 11 days ago | 0.09 ETH | ||||
21424949 | 56 days ago | 0.21 ETH | ||||
21394005 | 60 days ago | 0.01 ETH | ||||
21258439 | 79 days ago | 0.65 ETH | ||||
20999052 | 115 days ago | 0.2 ETH | ||||
20973389 | 119 days ago | 0.09 ETH | ||||
20856724 | 135 days ago | 0.06 ETH | ||||
20849125 | 136 days ago | 0.15 ETH | ||||
20848245 | 136 days ago | 0.024 ETH | ||||
20847953 | 136 days ago | 0.048 ETH | ||||
20742516 | 151 days ago | 0.03 ETH | ||||
20568081 | 175 days ago | 0.06 ETH | ||||
20541331 | 179 days ago | 0.03 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
FixedPrice
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 2 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {Allowlist} from "src/minters/extensions/Allowlist.sol"; import {LibBitmap} from "solady/src/utils/LibBitmap.sol"; import {LibMap} from "solady/src/utils/LibMap.sol"; import {MintPass} from "src/minters/extensions/MintPass.sol"; import {Ownable} from "solady/src/auth/Ownable.sol"; import {Pausable} from "openzeppelin/contracts/security/Pausable.sol"; import {SafeCastLib} from "solmate/src/utils/SafeCastLib.sol"; import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol"; import {IFixedPrice} from "src/interfaces/IFixedPrice.sol"; import {IToken} from "src/interfaces/IToken.sol"; import {ReserveInfo} from "src/lib/Structs.sol"; import {OPEN_EDITION_SUPPLY, TIME_UNLIMITED} from "src/utils/Constants.sol"; /** * @title FixedPrice * @author fx(hash) * @dev See the documentation in {IFixedPrice} */ contract FixedPrice is IFixedPrice, Allowlist, MintPass, Ownable, Pausable { using SafeCastLib for uint256; /*////////////////////////////////////////////////////////////////////////// STORAGE //////////////////////////////////////////////////////////////////////////*/ /** * @dev Mapping of token address to reserve ID to Bitmap of claimed merkle tree slots */ mapping(address => mapping(uint256 => LibBitmap.Bitmap)) internal claimedMerkleTreeSlots; /** * @dev Mapping of token address to reserve ID to Bitmap of claimed mint passes */ mapping(address => mapping(uint256 => LibBitmap.Bitmap)) internal claimedMintPasses; /** * @dev Mapping of token address to timestamp of latest update made for token reserves */ LibMap.Uint40Map internal latestUpdates; /** * @dev Mapping of token to the last valid reserveId that can mint on behalf of the token */ LibMap.Uint40Map internal firstValidReserve; /** * @dev Mapping of token address to sale proceeds */ LibMap.Uint128Map internal saleProceeds; /** * @inheritdoc IFixedPrice */ mapping(address => mapping(uint256 => bytes32)) public merkleRoots; /** * @inheritdoc IFixedPrice */ mapping(address => uint256[]) public prices; /** * @inheritdoc IFixedPrice */ mapping(address => ReserveInfo[]) public reserves; /*////////////////////////////////////////////////////////////////////////// EXTERNAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @inheritdoc IFixedPrice */ function buy(address _token, uint256 _reserveId, uint256 _amount, address _to) external payable whenNotPaused { bytes32 merkleRoot = _getMerkleRoot(_token, _reserveId); address signer = signingAuthorities[_token][_reserveId]; if (merkleRoot != bytes32(0)) revert NoPublicMint(); if (signer != address(0)) revert AddressZero(); _buy(_token, _reserveId, _amount, _to); } /** * @inheritdoc IFixedPrice */ function buyAllowlist( address _token, uint256 _reserveId, address _to, uint256[] calldata _indexes, bytes32[][] calldata _proofs ) external payable whenNotPaused { bytes32 merkleRoot = _getMerkleRoot(_token, _reserveId); if (merkleRoot == bytes32(0)) revert NoAllowlist(); LibBitmap.Bitmap storage claimBitmap = claimedMerkleTreeSlots[_token][_reserveId]; uint256 amount = _proofs.length; for (uint256 i; i < amount; ++i) { _claimSlot(_token, _reserveId, _indexes[i], _to, _proofs[i], claimBitmap); } _buy(_token, _reserveId, amount, _to); } /** * @inheritdoc IFixedPrice */ function buyMintPass( address _token, uint256 _reserveId, uint256 _amount, address _to, uint256 _index, bytes calldata _signature ) external payable whenNotPaused { address signer = signingAuthorities[_token][_reserveId]; if (signer == address(0)) revert NoSigningAuthority(); LibBitmap.Bitmap storage claimBitmap = claimedMintPasses[_token][_reserveId]; _claimMintPass(_token, _reserveId, _index, _to, _signature, claimBitmap); _buy(_token, _reserveId, _amount, _to); } /** * @inheritdoc IFixedPrice */ function setMintDetails(ReserveInfo calldata _reserve, bytes calldata _mintDetails) external whenNotPaused { uint256 nextReserve = reserves[msg.sender].length; if (getLatestUpdate(msg.sender) != block.timestamp) { _setLatestUpdate(msg.sender, block.timestamp); _setFirstValidReserve(msg.sender, nextReserve); } if (_reserve.allocation == 0) revert InvalidAllocation(); (uint256 price, bytes32 merkleRoot, address signer) = abi.decode(_mintDetails, (uint256, bytes32, address)); if (merkleRoot != bytes32(0)) { if (signer != address(0)) revert OnlyAuthorityOrAllowlist(); merkleRoots[msg.sender][nextReserve] = merkleRoot; } else if (signer != address(0)) { signingAuthorities[msg.sender][nextReserve] = signer; reserveNonce[msg.sender][nextReserve]++; } prices[msg.sender].push(price); reserves[msg.sender].push(_reserve); bool openEdition = _reserve.allocation == OPEN_EDITION_SUPPLY ? true : false; bool timeUnlimited = _reserve.endTime == TIME_UNLIMITED ? true : false; emit MintDetailsSet(msg.sender, nextReserve, price, _reserve, merkleRoot, signer, openEdition, timeUnlimited); } /** * @inheritdoc IFixedPrice */ function withdraw(address _token) external whenNotPaused { uint256 proceeds = getSaleProceed(_token); if (proceeds == 0) revert InsufficientFunds(); address saleReceiver = IToken(_token).primaryReceiver(); _setSaleProceeds(_token, 0); SafeTransferLib.safeTransferETH(saleReceiver, proceeds); emit Withdrawn(_token, saleReceiver, proceeds); } /*////////////////////////////////////////////////////////////////////////// OWNER FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @inheritdoc IFixedPrice */ function pause() external onlyOwner { _pause(); } /** * @inheritdoc IFixedPrice */ function unpause() external onlyOwner { _unpause(); } /*////////////////////////////////////////////////////////////////////////// READ FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @inheritdoc IFixedPrice */ function getFirstValidReserve(address _token) public view returns (uint256) { return LibMap.get(firstValidReserve, uint256(uint160(_token))); } /** * @inheritdoc IFixedPrice */ function getLatestUpdate(address _token) public view returns (uint40) { return LibMap.get(latestUpdates, uint256(uint160(_token))); } /** * @inheritdoc IFixedPrice */ function getSaleProceed(address _token) public view returns (uint128) { return LibMap.get(saleProceeds, uint256(uint160(_token))); } /*////////////////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @dev Purchases arbitrary amount of tokens at auction price and mints tokens to given account */ function _buy(address _token, uint256 _reserveId, uint256 _amount, address _to) internal { uint256 length = reserves[_token].length; uint256 validReserve = getFirstValidReserve(_token); if (length == 0) revert InvalidToken(); if (_reserveId >= length || _reserveId < validReserve) revert InvalidReserve(); ReserveInfo storage reserve = reserves[_token][_reserveId]; if (block.timestamp < reserve.startTime) revert NotStarted(); if (block.timestamp > reserve.endTime) revert Ended(); if (_amount > reserve.allocation) revert TooMany(); if (_to == address(0)) revert AddressZero(); uint256 price = _amount * prices[_token][_reserveId]; if (msg.value != price) revert InvalidPayment(); reserve.allocation -= _amount.safeCastTo128(); _setSaleProceeds(_token, getSaleProceed(_token) + price); IToken(_token).mint(_to, _amount, price); emit Purchase(_token, _reserveId, msg.sender, _amount, _to, price); } /** * @dev Sets timestamp of the latest update to token reserves */ function _setLatestUpdate(address _token, uint256 _timestamp) internal { LibMap.set(latestUpdates, uint256(uint160(_token)), uint40(_timestamp)); } /** * @dev Sets earliest valid reserve */ function _setFirstValidReserve(address _token, uint256 _reserveId) internal { LibMap.set(firstValidReserve, uint256(uint160(_token)), uint40(_reserveId)); } /** * @dev Sets the proceed amount from the token sale */ function _setSaleProceeds(address _token, uint256 _amount) internal { LibMap.set(saleProceeds, uint256(uint160(_token)), uint128(_amount)); } /** * @dev Gets the merkle root of a token reserve */ function _getMerkleRoot(address _token, uint256 _reserveId) internal view override returns (bytes32) { return merkleRoots[_token][_reserveId]; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {LibBitmap} from "solady/src/utils/LibBitmap.sol"; import {MerkleProof} from "openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; /** * @title Allowlist * @author fx(hash) * @notice Extension for claiming tokens through merkle trees */ abstract contract Allowlist { /*////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Event emitted when allowlist slot is claimed * @param _token Address of the token * @param _reserveId ID of the reserve * @param _claimer Address of the claimer * @param _index Index of purchase info inside the BitMap */ event SlotClaimed(address indexed _token, uint256 indexed _reserveId, address indexed _claimer, uint256 _index); /*////////////////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Error thrown when the merkle proof for an index is invalid */ error InvalidProof(); /** * @notice Error thrown when an index in the merkle tree has already been claimed */ error SlotAlreadyClaimed(); /*////////////////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @dev Claims a merkle tree slot * @param _token Address of the token contract * @param _reserveId ID of the reserve * @param _index Index in the merkle tree * @param _claimer Address of allowlist slot claimer * @param _proof Merkle proof used for validating claim * @param _bitmap Bitmap used for checking if index is already claimed */ function _claimSlot( address _token, uint256 _reserveId, uint256 _index, address _claimer, bytes32[] memory _proof, LibBitmap.Bitmap storage _bitmap ) internal { if (LibBitmap.get(_bitmap, _index)) revert SlotAlreadyClaimed(); bytes32 root = _getMerkleRoot(_token, _reserveId); bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(_index, _claimer)))); if (!MerkleProof.verify(_proof, root, leaf)) revert InvalidProof(); LibBitmap.set(_bitmap, _index); emit SlotClaimed(_token, _reserveId, _claimer, _index); } /** * @dev Gets the merkle root of a token reserve * @param _token Address of the token contract * @param _reserveId ID of the reserve */ function _getMerkleRoot(address _token, uint256 _reserveId) internal view virtual returns (bytes32); }
// 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 Library for storage of packed unsigned integers. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibMap.sol) library LibMap { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev A uint8 map in storage. struct Uint8Map { mapping(uint256 => uint256) map; } /// @dev A uint16 map in storage. struct Uint16Map { mapping(uint256 => uint256) map; } /// @dev A uint32 map in storage. struct Uint32Map { mapping(uint256 => uint256) map; } /// @dev A uint40 map in storage. Useful for storing timestamps up to 34841 A.D. struct Uint40Map { mapping(uint256 => uint256) map; } /// @dev A uint64 map in storage. struct Uint64Map { mapping(uint256 => uint256) map; } /// @dev A uint128 map in storage. struct Uint128Map { mapping(uint256 => uint256) map; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* GETTERS / SETTERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the uint8 value at `index` in `map`. function get(Uint8Map storage map, uint256 index) internal view returns (uint8 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(5, index)) result := byte(and(31, not(index)), sload(keccak256(0x00, 0x40))) } } /// @dev Updates the uint8 value at `index` in `map`. function set(Uint8Map storage map, uint256 index, uint8 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(5, index)) let s := keccak256(0x00, 0x40) // Storage slot. mstore(0x00, sload(s)) mstore8(and(31, not(index)), value) sstore(s, mload(0x00)) } } /// @dev Returns the uint16 value at `index` in `map`. function get(Uint16Map storage map, uint256 index) internal view returns (uint16 result) { result = uint16(map.map[index >> 4] >> ((index & 15) << 4)); } /// @dev Updates the uint16 value at `index` in `map`. function set(Uint16Map storage map, uint256 index, uint16 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(4, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(4, and(index, 15)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint32 value at `index` in `map`. function get(Uint32Map storage map, uint256 index) internal view returns (uint32 result) { result = uint32(map.map[index >> 3] >> ((index & 7) << 5)); } /// @dev Updates the uint32 value at `index` in `map`. function set(Uint32Map storage map, uint256 index, uint32 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(3, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(5, and(index, 7)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint40 value at `index` in `map`. function get(Uint40Map storage map, uint256 index) internal view returns (uint40 result) { unchecked { result = uint40(map.map[index / 6] >> ((index % 6) * 40)); } } /// @dev Updates the uint40 value at `index` in `map`. function set(Uint40Map storage map, uint256 index, uint40 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, div(index, 6)) let s := keccak256(0x00, 0x40) // Storage slot. let o := mul(40, mod(index, 6)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint64 value at `index` in `map`. function get(Uint64Map storage map, uint256 index) internal view returns (uint64 result) { result = uint64(map.map[index >> 2] >> ((index & 3) << 6)); } /// @dev Updates the uint64 value at `index` in `map`. function set(Uint64Map storage map, uint256 index, uint64 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(2, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(6, and(index, 3)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffffffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint128 value at `index` in `map`. function get(Uint128Map storage map, uint256 index) internal view returns (uint128 result) { result = uint128(map.map[index >> 1] >> ((index & 1) << 7)); } /// @dev Updates the uint128 value at `index` in `map`. function set(Uint128Map storage map, uint256 index, uint128 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(1, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(7, and(index, 1)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffffffffffffffffffffffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the value at `index` in `map`. function get(mapping(uint256 => uint256) storage map, uint256 index, uint256 bitWidth) internal view returns (uint256 result) { unchecked { uint256 d = _rawDiv(256, bitWidth); // Bucket size. uint256 m = (1 << bitWidth) - 1; // Value mask. result = (map[_rawDiv(index, d)] >> (_rawMod(index, d) * bitWidth)) & m; } } /// @dev Updates the value at `index` in `map`. function set( mapping(uint256 => uint256) storage map, uint256 index, uint256 value, uint256 bitWidth ) internal { unchecked { uint256 d = _rawDiv(256, bitWidth); // Bucket size. uint256 m = (1 << bitWidth) - 1; // Value mask. uint256 o = _rawMod(index, d) * bitWidth; // Storage slot offset (bits). map[_rawDiv(index, d)] ^= (((map[_rawDiv(index, d)] >> o) ^ value) & m) << o; } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BINARY SEARCH */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // The following functions search in the range of [`start`, `end`) // (i.e. `start <= index < end`). // The range must be sorted in ascending order. // `index` precedence: equal to > nearest before > nearest after. // An invalid search range will simply return `(found = false, index = start)`. /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint8Map storage map, uint8 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 8); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint16Map storage map, uint16 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 16); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint32Map storage map, uint32 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 32); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint40Map storage map, uint40 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 40); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint64Map storage map, uint64 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 64); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint128Map storage map, uint128 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 128); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted( mapping(uint256 => uint256) storage map, uint256 needle, uint256 start, uint256 end, uint256 bitWidth ) internal view returns (bool found, uint256 index) { unchecked { if (start >= end) end = start; uint256 t; uint256 o = start - 1; // Offset to derive the actual index. uint256 l = 1; // Low. uint256 d = _rawDiv(256, bitWidth); // Bucket size. uint256 m = (1 << bitWidth) - 1; // Value mask. uint256 h = end - start; // High. while (true) { index = (l & h) + ((l ^ h) >> 1); if (l > h) break; t = (map[_rawDiv(index + o, d)] >> (_rawMod(index + o, d) * bitWidth)) & m; if (t == needle) break; if (needle <= t) h = index - 1; else l = index + 1; } /// @solidity memory-safe-assembly assembly { m := or(iszero(index), iszero(bitWidth)) found := iszero(or(xor(t, needle), m)) index := add(o, xor(index, mul(xor(index, 1), m))) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `x / y`, returning 0 if `y` is zero. function _rawDiv(uint256 x, uint256 y) private pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(x, y) } } /// @dev Returns `x % y`, returning 0 if `y` is zero. function _rawMod(uint256 x, uint256 y) private pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mod(x, y) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {EIP712} from "openzeppelin/contracts/utils/cryptography/EIP712.sol"; import {LibBitmap} from "solady/src/utils/LibBitmap.sol"; import {SignatureChecker} from "openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import {CLAIM_TYPEHASH} from "src/utils/Constants.sol"; /** * @title MintPass * @author fx(hash) * @notice Extension for claiming tokens through mint passes */ abstract contract MintPass is EIP712 { using SignatureChecker for address; /*////////////////////////////////////////////////////////////////////////// STORAGE //////////////////////////////////////////////////////////////////////////*/ /** * @notice Mapping of token address to reserve ID to reserve nonce */ mapping(address => mapping(uint256 => uint256)) public reserveNonce; /** * @notice Mapping of token address to reserve ID to address of mint pass authority */ mapping(address => mapping(uint256 => address)) public signingAuthorities; /*////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Event emitted when mint pass is claimed * @param _token Address of the token * @param _reserveId ID of the reserve * @param _claimer Address of the mint pass claimer * @param _index Index of purchase info inside the BitMap */ event PassClaimed(address indexed _token, uint256 indexed _reserveId, address indexed _claimer, uint256 _index); /*////////////////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Error thrown when the signature of mint pass claimer is invalid */ error InvalidSignature(); /** * @notice Error thrown when a mint pass has already been claimed */ error PassAlreadyClaimed(); /*////////////////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////////////////*/ /** * @dev Initializes EIP-712 */ constructor() EIP712("MINT_PASS", "1") {} /*////////////////////////////////////////////////////////////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Generates the typed data hash for a mint pass claim * @param _token address of token for the reserve * @param _reserveId Id of the reserve to mint the token from * @param _index Index of the mint pass * @param _claimer Address of mint pass claimer * @return Digest of typed data hash claimer */ function generateTypedDataHash( address _token, uint256 _reserveId, uint256 _reserveNonce, uint256 _index, address _claimer ) public view returns (bytes32) { bytes32 structHash = keccak256(abi.encode(CLAIM_TYPEHASH, _token, _reserveNonce, _reserveId, _index, _claimer)); return _hashTypedDataV4(structHash); } /*////////////////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @dev Validates a mint pass claim * @param _token Address of the token contract * @param _reserveId ID of the reserve * @param _index Index of the mint pass * @param _claimer Account associated with the mint pass * @param _signature Signature of the mint pass claimer * @param _bitmap Bitmap used for checking if index is already claimed */ function _claimMintPass( address _token, uint256 _reserveId, uint256 _index, address _claimer, bytes calldata _signature, LibBitmap.Bitmap storage _bitmap ) internal { if (LibBitmap.get(_bitmap, _index)) revert PassAlreadyClaimed(); uint256 nonce = reserveNonce[_token][_reserveId]; bytes32 hash = generateTypedDataHash(_token, _reserveId, nonce, _index, _claimer); address signer = signingAuthorities[_token][_reserveId]; if (!signer.isValidSignatureNow(hash, _signature)) revert InvalidSignature(); LibBitmap.set(_bitmap, _index); emit PassClaimed(_token, _reserveId, _claimer, _index); } }
// 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 // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Safe unsigned integer casting library that reverts on overflow. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeCastLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol) library SafeCastLib { function safeCastTo248(uint256 x) internal pure returns (uint248 y) { require(x < 1 << 248); y = uint248(x); } function safeCastTo240(uint256 x) internal pure returns (uint240 y) { require(x < 1 << 240); y = uint240(x); } function safeCastTo232(uint256 x) internal pure returns (uint232 y) { require(x < 1 << 232); y = uint232(x); } function safeCastTo224(uint256 x) internal pure returns (uint224 y) { require(x < 1 << 224); y = uint224(x); } function safeCastTo216(uint256 x) internal pure returns (uint216 y) { require(x < 1 << 216); y = uint216(x); } function safeCastTo208(uint256 x) internal pure returns (uint208 y) { require(x < 1 << 208); y = uint208(x); } function safeCastTo200(uint256 x) internal pure returns (uint200 y) { require(x < 1 << 200); y = uint200(x); } function safeCastTo192(uint256 x) internal pure returns (uint192 y) { require(x < 1 << 192); y = uint192(x); } function safeCastTo184(uint256 x) internal pure returns (uint184 y) { require(x < 1 << 184); y = uint184(x); } function safeCastTo176(uint256 x) internal pure returns (uint176 y) { require(x < 1 << 176); y = uint176(x); } function safeCastTo168(uint256 x) internal pure returns (uint168 y) { require(x < 1 << 168); y = uint168(x); } function safeCastTo160(uint256 x) internal pure returns (uint160 y) { require(x < 1 << 160); y = uint160(x); } function safeCastTo152(uint256 x) internal pure returns (uint152 y) { require(x < 1 << 152); y = uint152(x); } function safeCastTo144(uint256 x) internal pure returns (uint144 y) { require(x < 1 << 144); y = uint144(x); } function safeCastTo136(uint256 x) internal pure returns (uint136 y) { require(x < 1 << 136); y = uint136(x); } function safeCastTo128(uint256 x) internal pure returns (uint128 y) { require(x < 1 << 128); y = uint128(x); } function safeCastTo120(uint256 x) internal pure returns (uint120 y) { require(x < 1 << 120); y = uint120(x); } function safeCastTo112(uint256 x) internal pure returns (uint112 y) { require(x < 1 << 112); y = uint112(x); } function safeCastTo104(uint256 x) internal pure returns (uint104 y) { require(x < 1 << 104); y = uint104(x); } function safeCastTo96(uint256 x) internal pure returns (uint96 y) { require(x < 1 << 96); y = uint96(x); } function safeCastTo88(uint256 x) internal pure returns (uint88 y) { require(x < 1 << 88); y = uint88(x); } function safeCastTo80(uint256 x) internal pure returns (uint80 y) { require(x < 1 << 80); y = uint80(x); } function safeCastTo72(uint256 x) internal pure returns (uint72 y) { require(x < 1 << 72); y = uint72(x); } function safeCastTo64(uint256 x) internal pure returns (uint64 y) { require(x < 1 << 64); y = uint64(x); } function safeCastTo56(uint256 x) internal pure returns (uint56 y) { require(x < 1 << 56); y = uint56(x); } function safeCastTo48(uint256 x) internal pure returns (uint48 y) { require(x < 1 << 48); y = uint48(x); } function safeCastTo40(uint256 x) internal pure returns (uint40 y) { require(x < 1 << 40); y = uint40(x); } function safeCastTo32(uint256 x) internal pure returns (uint32 y) { require(x < 1 << 32); y = uint32(x); } function safeCastTo24(uint256 x) internal pure returns (uint24 y) { require(x < 1 << 24); y = uint24(x); } function safeCastTo16(uint256 x) internal pure returns (uint16 y) { require(x < 1 << 16); y = uint16(x); } function safeCastTo8(uint256 x) internal pure returns (uint8 y) { require(x < 1 << 8); y = uint8(x); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {IMinter} from "src/interfaces/IMinter.sol"; import {ReserveInfo} from "src/lib/Structs.sol"; /** * @title IFixedPrice * @author fx(hash) * @notice Minter for distributing tokens at fixed prices */ interface IFixedPrice is IMinter { /*////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Event emitted when a new fixed price mint has been set * @param _token Address of the token being minted * @param _reserveId ID of the reserve * @param _price Amount of fixed price mint * @param _merkleRoot The merkle root allowlisted buyers * @param _mintPassSigner The signing account for mint passes * @param _reserveInfo Reserve information for the mint * @param _openEdition Status of an open edition mint * @param _timeUnlimited Status of a mint with unlimited time */ event MintDetailsSet( address indexed _token, uint256 indexed _reserveId, uint256 _price, ReserveInfo _reserveInfo, bytes32 _merkleRoot, address _mintPassSigner, bool _openEdition, bool _timeUnlimited ); /** * @notice Event emitted when a purchase is made * @param _token Address of the token being purchased * @param _reserveId ID of the mint * @param _buyer Address purchasing the tokens * @param _amount Amount of tokens being purchased * @param _to Address to which the tokens are being transferred * @param _price Price of the purchase */ event Purchase( address indexed _token, uint256 indexed _reserveId, address indexed _buyer, uint256 _amount, address _to, uint256 _price ); /** * @notice Event emitted when sale proceeds are withdrawn * @param _token Address of the token * @param _creator Address of the project creator * @param _proceeds Amount of proceeds being withdrawn */ event Withdrawn(address indexed _token, address indexed _creator, uint256 _proceeds); /*////////////////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Error thrown when receiver is zero address */ error AddressZero(); /** * @notice Error thrown when the sale has already ended */ error Ended(); /** * @notice Error thrown when no funds available to withdraw */ error InsufficientFunds(); /** * @notice Error thrown when the allocation amount is zero */ error InvalidAllocation(); /** * @notice Error thrown when payment does not equal price */ error InvalidPayment(); /** * @notice Error thrown thrown when reserve does not exist */ error InvalidReserve(); /** * @notice Error thrown when reserve start and end times are invalid */ error InvalidTimes(); /** * @notice Error thrown when token address is invalid */ error InvalidToken(); /** * @notice Error thrown when buying through allowlist and no allowlist exists */ error NoAllowlist(); /** * @notice Error thrown when calling buy when either an allowlist or signer exists */ error NoPublicMint(); /** * @notice Error thrown when buy with a mint pass and no signing authority exists */ error NoSigningAuthority(); /** * @notice Error thrown when the auction has not started */ error NotStarted(); /** * @notice Error thrown when setting both an allowlist and mint signer */ error OnlyAuthorityOrAllowlist(); /** * @notice Error thrown when amount purchased exceeds remaining allocation */ error TooMany(); /*////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Purchases tokens at a fixed price * @param _token Address of the token contract * @param _reserveId ID of the reserve * @param _amount Amount of tokens being purchased * @param _to Address receiving the purchased tokens */ function buy(address _token, uint256 _reserveId, uint256 _amount, address _to) external payable; /** * @notice Purchases tokens through an allowlist at a fixed price * @param _token Address of the token being purchased * @param _reserveId ID of the reserve * @param _to Address receiving the purchased tokens * @param _indexes Array of indices regarding purchase info inside the BitMap * @param _proofs Array of merkle proofs used for verifying the purchase */ function buyAllowlist( address _token, uint256 _reserveId, address _to, uint256[] calldata _indexes, bytes32[][] calldata _proofs ) external payable; /** * @notice Purchases tokens through a mint pass at a fixed price * @param _token Address of the token being purchased * @param _reserveId ID of the reserve * @param _amount Number of tokens being purchased * @param _to Address receiving the purchased tokens * @param _index Index of puchase info inside the BitMap * @param _signature Array of merkle proofs used for verifying the purchase */ function buyMintPass( address _token, uint256 _reserveId, uint256 _amount, address _to, uint256 _index, bytes calldata _signature ) external payable; /** * @notice Returns the earliest valid reserveId that can mint a token */ function getFirstValidReserve(address _token) external view returns (uint256); /** * @notice Gets the latest timestamp update made to token reserves * @param _token Address of the token contract * @return Timestamp of latest update */ function getLatestUpdate(address _token) external view returns (uint40); /** * @notice Gets the proceed amount from a token sale * @param _token Address of the token contract * @return Amount of proceeds */ function getSaleProceed(address _token) external view returns (uint128); /** * @notice Mapping of token address to reserve ID to merkle roots */ function merkleRoots(address, uint256) external view returns (bytes32); /** * @notice Pauses all function executions where modifier is applied */ function pause() external; /** * @notice Mapping of token address to reserve ID to prices */ function prices(address, uint256) external view returns (uint256); /** * @notice Mapping of token address to reserve ID to reserve information */ function reserves(address, uint256) external view returns (uint64, uint64, uint128); /** * @inheritdoc IMinter * @dev Mint Details: token price, merkle root, and signer address */ function setMintDetails(ReserveInfo calldata _reserveInfo, bytes calldata _mintDetails) external; /** * @notice Unpauses all function executions where modifier is applied */ function unpause() external; /** * @notice Withdraws the sale proceeds to the sale receiver * @param _token Address of the token withdrawing proceeds from */ function withdraw(address _token) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /** * @title IToken * @author fx(hash) * @notice Interface for minters to interact with tokens */ interface IToken { /*////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Mints arbitrary number of tokens * @dev Only callable by registered minter contracts * @param _to Address receiving tokens * @param _amount Number of tokens being minted * @param _payment Total payment amount of the transaction */ function mint(address _to, uint256 _amount, uint256 _payment) external; /** * @notice Returns address of primary receiver for token sales */ function primaryReceiver() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /*////////////////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Struct of dutch auction information * - `refunded` Flag indicating if refunds are enabled * - `stepLength` Duration (in seconds) of each auction step * - `prices` Array of prices for each step of the auction */ struct AuctionInfo { bool refunded; uint248 stepLength; uint256[] prices; } /** * @notice Struct of system config information * - `feeReceiver` Address receiving platform fees * - `primaryFeeAllocation` Amount of basis points allocated to calculate platform fees on primary sale proceeds * - `secondaryFeeAllocation` Amount of basis points allocated to calculate platform fees on royalty payments * - `lockTime` Locked time duration added to mint start time for unverified creators * - `referrerShare` Share amount distributed to accounts referring tokens * - `defaultMetadataURI` Default base URI of token metadata * - `externalURI` External URI for displaying tokens */ struct ConfigInfo { address feeReceiver; uint32 primaryFeeAllocation; uint32 secondaryFeeAllocation; uint32 lockTime; uint64 referrerShare; string defaultMetadataURI; string externalURI; } /** * @notice Struct of generative art information * - `minter` Address of initial token owner * - `seed` Hash of randomly generated seed * - `fxParams` Random sequence of fixed-length bytes used as token input */ struct GenArtInfo { address minter; bytes32 seed; bytes fxParams; } /** * @notice Struct of initialization information used on project creation * - `name` Name of project * - `symbol` Symbol of project * - `primaryReceiver` Address of splitter contract receiving primary sales * - `randomizer` Address of Randomizer contract * - `renderer` Address of Renderer contract * - `tagIds` Array of tag IDs describing the project * - 'onchainData' Onchain data to be stored using SSTORE2 and available to renderers */ struct InitInfo { string name; string symbol; address[] primaryReceivers; uint32[] allocations; address randomizer; address renderer; uint256[] tagIds; bytes onchainData; } /** * @notice Struct of issuer information * - `primaryReceiver` Address of splitter contract receiving primary sales * - `projectInfo` Project information * - `activeMinters` Array of authorized minter contracts used for enumeration * - `minters` Mapping of minter contract to authorization status */ struct IssuerInfo { address primaryReceiver; ProjectInfo projectInfo; address[] activeMinters; mapping(address => uint8) minters; } /** * @notice Struct of metadata information * - `baseURI` Decoded URI of content identifier * - `onchainPointer` Address of bytes-encoded data rendered onchain */ struct MetadataInfo { bytes baseURI; address onchainPointer; } /** * @notice Struct of mint information * - `minter` Address of the minter contract * - `reserveInfo` Reserve information * - `params` Optional bytes data decoded inside minter */ struct MintInfo { address minter; ReserveInfo reserveInfo; bytes params; } /** * @notice Struct of minter information * - `totalMints` Total number of mints executed by the minter * - `totalPaid` Total amount paid by the minter */ struct MinterInfo { uint128 totalMints; uint128 totalPaid; } /** * @notice Struct of project information * - `mintEnabled` Flag inidicating if minting is enabled * - `burnEnabled` Flag inidicating if burning is enabled * - `maxSupply` Maximum supply of tokens * - `inputSize` Maximum input size of fxParams bytes data * - `earliestStartTime` Earliest possible start time for registering minters */ struct ProjectInfo { bool mintEnabled; bool burnEnabled; uint120 maxSupply; uint88 inputSize; uint32 earliestStartTime; } /** * @notice Struct of refund information * - `lastPrice` Price of last sale before selling out * - `minterInfo` Mapping of minter address to struct of minter information */ struct RefundInfo { uint256 lastPrice; mapping(address minter => MinterInfo) minterInfo; } /** * @notice Struct of reserve information * - `startTime` Start timestamp of minter * - `endTime` End timestamp of minter * - `allocation` Allocation amount for minter */ struct ReserveInfo { uint64 startTime; uint64 endTime; uint128 allocation; } /** * @notice Struct of royalty information * - `receiver` Address receiving royalties * - `basisPoints` Points used to calculate the royalty payment (0.01%) */ struct RoyaltyInfo { address receiver; uint96 basisPoints; } /** * @notice Struct of tax information * - `startTime` Timestamp of when harberger taxation begins * - `foreclosureTime` Timestamp of token foreclosure * - `currentPrice` Current listing price of token * - `depositAmount` Total amount of taxes deposited */ struct TaxInfo { uint48 startTime; uint48 foreclosureTime; uint80 currentPrice; uint80 depositAmount; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /*////////////////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////////////////*/ // Core string constant FX_CONTRACT_REGISTRY = "FX_CONTRACT_REGISTRY"; string constant FX_GEN_ART_721 = "FX_GEN_ART_721"; string constant FX_ISSUER_FACTORY = "FX_ISSUER_FACTORY"; string constant FX_MINT_TICKET_721 = "FX_MINT_TICKET_721"; string constant FX_ROLE_REGISTRY = "FX_ROLE_REGISTRY"; string constant FX_TICKET_FACTORY = "FX_TICKET_FACTORY"; // Periphery string constant DUTCH_AUCTION = "DUTCH_AUCTION"; string constant FIXED_PRICE = "FIXED_PRICE"; string constant ONCHFS_RENDERER = "ONCHFS_RENDERER"; string constant IPFS_RENDERER = "IPFS_RENDERER"; string constant PSEUDO_RANDOMIZER = "PSEUDO_RANDOMIZER"; string constant TICKET_REDEEMER = "TICKET_REDEEMER"; // EIP-712 bytes32 constant CLAIM_TYPEHASH = keccak256( "Claim(address token,uint256 reserveId,uint96 nonce,uint256 index,address user)" ); bytes32 constant SET_ONCHAIN_POINTER_TYPEHASH = keccak256("SetOnchainPointer(bytes onchainData,uint96 nonce)"); bytes32 constant SET_PRIMARY_RECEIVER_TYPEHASH = keccak256("SetPrimaryReceiver(address receiver,uint96 nonce)"); bytes32 constant SET_RENDERER_TYPEHASH = keccak256("SetRenderer(address renderer,uint96 nonce)"); // IPFS bytes constant IPFS_URL = hex"697066733a2f2f172c151325290607391d2c391b242225180a020b291b260929391d1b31222525202804120031280917120b280400"; string constant IPFS_PREFIX = "ipfs://"; // Metadata string constant API_VERSION = "0.2"; string constant ATTRIBUTES_ENDPOINT = "/attributes.json"; string constant METADATA_ENDPOINT = "/metadata.json"; string constant THUMBNAIL_ENDPOINT = "/thumbnail.json"; // ONCHFS string constant FX_HASH_QUERY = "/?fxhash="; string constant FX_PARAMS_QUERY = "#0x"; string constant ITERATION_QUERY = "&fxiteration="; string constant MINTER_QUERY = "&fxminter="; string constant ONCHFS_PREFIX = "onchfs://"; // Minters uint8 constant UNINITIALIZED = 0; uint8 constant FALSE = 1; uint8 constant TRUE = 2; // Project uint32 constant LOCK_TIME = 3600; // 1 hour uint64 constant TIME_UNLIMITED = type(uint64).max; uint120 constant OPEN_EDITION_SUPPLY = type(uint120).max; uint256 constant LAUNCH_TIMESTAMP = 1702558800; // 12/14/23 14:00 CET // Roles bytes32 constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); bytes32 constant BANNED_USER_ROLE = keccak256("BANNED_USER_ROLE"); bytes32 constant CREATOR_ROLE = keccak256("CREATOR_ROLE"); bytes32 constant METADATA_ROLE = keccak256("METADATA_ROLE"); bytes32 constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 constant MODERATOR_ROLE = keccak256("MODERATOR_ROLE"); bytes32 constant SIGNER_ROLE = keccak256("SIGNER_ROLE"); // Royalties uint32 constant ALLOCATION_DENOMINATOR = 1_000_000; uint96 constant FEE_DENOMINATOR = 10_000; uint96 constant MAX_ROYALTY_BPS = 2500; // 25% // Splits address constant SPLITS_MAIN = 0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE; // Ticket uint256 constant AUCTION_DECAY_RATE = 200; // 2% uint256 constant DAILY_TAX_RATE = 27; // 0.274% uint256 constant MINIMUM_PRICE = 0.001 ether; uint256 constant ONE_DAY = 86_400; uint256 constant SCALING_FACTOR = 10_000; uint256 constant TEN_MINUTES = 600;
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// 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. /// Equivalent to `log2(x)`, but without reverting for the zero case. function fls(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { r := shl(8, iszero(x)) r := or(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)))) // For the remaining 32 bits, use a De Bruijn lookup. x := shr(r, x) x := or(x, shr(1, x)) x := or(x, shr(2, x)) x := or(x, shr(4, x)) x := or(x, shr(8, x)) x := or(x, shr(16, x)) // forgefmt: disable-next-item r := or(r, byte(shr(251, mul(x, shl(224, 0x07c4acdd))), 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f)) } } /// @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 { let t := add(iszero(x), 255) 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)))) // For the remaining 32 bits, use a De Bruijn lookup. x := shr(r, x) x := or(x, shr(1, x)) x := or(x, shr(2, x)) x := or(x, shr(4, x)) x := or(x, shr(8, x)) x := or(x, shr(16, x)) // forgefmt: disable-next-item r := sub(t, or(r, byte(shr(251, mul(x, shl(224, 0x07c4acdd))), 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f))) } } /// @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 { r := shl(8, iszero(x)) // Isolate the least significant bit. x := and(x, add(not(x), 1)) r := or(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)))) // For the remaining 32 bits, use a De Bruijn lookup. // forgefmt: disable-next-item r := or(r, byte(shr(251, mul(shr(r, x), shl(224, 0x077cb531))), 0x00011c021d0e18031e16140f191104081f1b0d17151310071a0c12060b050a09)) } } /// @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 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `x & y`. function and(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := and(x, y) } } /// @dev Returns `x | y`. function or(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := or(x, y) } } /// @dev Returns a non-zero number if `b` is true, else 0. /// If `b` is from plain Solidity, the non-zero number will be 1. function toUint(bool b) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := b } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.8; import "./ECDSA.sol"; import "../ShortStrings.sol"; import "../../interfaces/IERC5267.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * _Available since v3.4._ * * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {EIP-5267}. * * _Available since v4.9._ */ function eip712Domain() public view virtual override returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", // 01111 _name.toStringWithFallback(_nameFallback), _version.toStringWithFallback(_versionFallback), block.chainid, address(this), bytes32(0), new uint256[](0) ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; import "../../interfaces/IERC1271.sol"; /** * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like * Argent and Gnosis Safe. * * _Available since v4.1._ */ library SignatureChecker { /** * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) { (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature); return (error == ECDSA.RecoverError.NoError && recovered == signer) || isValidERC1271SignatureNow(signer, hash, signature); } /** * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated * against the signer smart contract using ERC1271. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidERC1271SignatureNow( address signer, bytes32 hash, bytes memory signature ) internal view returns (bool) { (bool success, bytes memory result) = signer.staticcall( abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature) ); return (success && result.length >= 32 && abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {ReserveInfo} from "src/lib/Structs.sol"; /** * @title IMinter * @author fx(hash) * @notice Interface for FxGenArt721 tokens to interact with minters */ interface IMinter { /*////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Sets the mint details for token reserves * @param _reserveInfo Reserve information for the token * @param _mintDetails Details of the mint pertaining to the minter */ function setMintDetails(ReserveInfo calldata _reserveInfo, bytes calldata _mintDetails) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol) pragma solidity ^0.8.8; import "./StorageSlot.sol"; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(_FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.0; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
{ "remappings": [ "openzeppelin/=lib/openzeppelin-contracts/", "openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "forge-std/=lib/forge-std/src/", "scripty.sol/=lib/scripty.sol/", "solady/=lib/solady/", "solmate/=lib/solmate/", "sstore2/=lib/sstore2/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 2 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"AddressZero","type":"error"},{"inputs":[],"name":"Ended","type":"error"},{"inputs":[],"name":"InsufficientFunds","type":"error"},{"inputs":[],"name":"InvalidAllocation","type":"error"},{"inputs":[],"name":"InvalidPayment","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidReserve","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidTimes","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoAllowlist","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NoPublicMint","type":"error"},{"inputs":[],"name":"NoSigningAuthority","type":"error"},{"inputs":[],"name":"NotStarted","type":"error"},{"inputs":[],"name":"OnlyAuthorityOrAllowlist","type":"error"},{"inputs":[],"name":"PassAlreadyClaimed","type":"error"},{"inputs":[],"name":"SlotAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[],"name":"TooMany","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_reserveId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"},{"components":[{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint128","name":"allocation","type":"uint128"}],"indexed":false,"internalType":"struct ReserveInfo","name":"_reserveInfo","type":"tuple"},{"indexed":false,"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"indexed":false,"internalType":"address","name":"_mintPassSigner","type":"address"},{"indexed":false,"internalType":"bool","name":"_openEdition","type":"bool"},{"indexed":false,"internalType":"bool","name":"_timeUnlimited","type":"bool"}],"name":"MintDetailsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_reserveId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_claimer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_index","type":"uint256"}],"name":"PassClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_reserveId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"}],"name":"Purchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_reserveId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_claimer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_index","type":"uint256"}],"name":"SlotClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"address","name":"_creator","type":"address"},{"indexed":false,"internalType":"uint256","name":"_proceeds","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_reserveId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_reserveId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"},{"internalType":"bytes32[][]","name":"_proofs","type":"bytes32[][]"}],"name":"buyAllowlist","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_reserveId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"buyMintPass","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","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":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_reserveId","type":"uint256"},{"internalType":"uint256","name":"_reserveNonce","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"address","name":"_claimer","type":"address"}],"name":"generateTypedDataHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getFirstValidReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getLatestUpdate","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getSaleProceed","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"merkleRoots","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"prices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"reserveNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"reserves","outputs":[{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint128","name":"allocation","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint128","name":"allocation","type":"uint128"}],"internalType":"struct ReserveInfo","name":"_reserve","type":"tuple"},{"internalType":"bytes","name":"_mintDetails","type":"bytes"}],"name":"setMintDetails","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"signingAuthorities","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101606040523480156200001257600080fd5b5060408051808201825260098152684d494e545f5041535360b81b602080830191909152825180840190935260018352603160f81b90830152906200005982600062000111565b610120526200006a81600162000111565b61014052815160208084019190912060e052815190820120610100524660a052620000f860e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c0526004805460ff191690556200037f565b6000602083511015620001315762000129836200014a565b905062000144565b816200013e84826200023d565b5060ff90505b92915050565b600080829050601f8151111562000181578260405163305a27a960e01b815260040162000178919062000309565b60405180910390fd5b80516200018e826200035a565b179392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620001c157607f821691505b602082108103620001e257634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000238576000816000526020600020601f850160051c81016020861015620002135750805b601f850160051c820191505b8181101562000234578281556001016200021f565b5050505b505050565b81516001600160401b0381111562000259576200025962000196565b62000271816200026a8454620001ac565b84620001e8565b602080601f831160018114620002a95760008415620002905750858301515b600019600386901b1c1916600185901b17855562000234565b600085815260208120601f198616915b82811015620002da57888601518255948401946001909101908401620002b9565b5085821015620002f95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020808352835180602085015260005b8181101562000339578581018301518582016040015282016200031b565b506000604082860101526040601f19601f8301168501019250505092915050565b80516020808301519190811015620001e25760001960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161224f620003da600039600061080f015260006107e5015260006117c70152600061179f015260006116fa015260006117240152600061174e015261224f6000f3fe6080604052600436106101265760003560e01c80631774e7ca1461012b5780631a010e191461016857806325692962146101ae57806332a46e4b146101b85780633f4ba83a146101d85780633f60b633146101ed5780634bfbb5321461020057806351cff8d91461021357806354d1f13d146102335780635c975abb1461023b578063715018a61461025e5780638456cb591461026657806384b0196e1461027b5780638a274f3c146102a35780638da5cb5b146102c3578063b490abde146102e5578063bbc492c014610305578063d171f02514610325578063de25de5014610338578063e369f9f514610387578063e6070b92146103c8578063f04e283e146103fe578063f091335c14610411578063f2fde38b14610449578063fee81cf41461045c575b600080fd5b34801561013757600080fd5b5061014b610146366004611b05565b61048f565b6040516001600160801b0390911681526020015b60405180910390f35b34801561017457600080fd5b506101a0610183366004611b22565b600a60209081526000928352604080842090915290825290205481565b60405190815260200161015f565b6101b66104bc565b005b3480156101c457600080fd5b506101a06101d3366004611b05565b61050b565b3480156101e457600080fd5b506101b661052e565b6101b66101fb366004611b4e565b610540565b6101b661020e366004611bd9565b6105d8565b34801561021f57600080fd5b506101b661022e366004611b05565b61066d565b6101b6610779565b34801561024757600080fd5b5060045460ff16604051901515815260200161015f565b6101b66107b5565b34801561027257600080fd5b506101b66107c7565b34801561028757600080fd5b506102906107d7565b60405161015f9796959493929190611cae565b3480156102af57600080fd5b506101a06102be366004611d47565b61085f565b3480156102cf57600080fd5b50638b78c6d819545b60405161015f9190611d9d565b3480156102f157600080fd5b506101b6610300366004611db1565b6108ec565b34801561031157600080fd5b506101a0610320366004611b22565b610b3e565b6101b6610333366004611e4f565b610b6f565b34801561034457600080fd5b50610358610353366004611b22565b610c6f565b604080516001600160401b0394851681529390921660208401526001600160801b03169082015260600161015f565b34801561039357600080fd5b506102d86103a2366004611b22565b60036020908152600092835260408084209091529082529020546001600160a01b031681565b3480156103d457600080fd5b506103e86103e3366004611b05565b610cc1565b60405164ffffffffff909116815260200161015f565b6101b661040c366004611b05565b610cd7565b34801561041d57600080fd5b506101a061042c366004611b22565b600260209081526000928352604080842090915290825290205481565b6101b6610457366004611b05565b610d17565b34801561046857600080fd5b506101a0610477366004611b05565b63389a75e1600c908152600091909152602090205490565b60016001609f1b03600182901c16600090815260096020526040812054600783901b6080161c5b92915050565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60006105216008836001600160a01b0316610d3e565b64ffffffffff1692915050565b610536610d5e565b61053e610d79565b565b610548610dc5565b60006105548585610e10565b6001600160a01b03808716600090815260036020908152604080832089845290915290205491925016811561059c57604051636e0d060560e01b815260040160405180910390fd5b6001600160a01b038116156105c457604051639fabe1c160e01b815260040160405180910390fd5b6105d086868686610e38565b505050505050565b6105e0610dc5565b6001600160a01b0380881660009081526003602090815260408083208a84529091529020541680610624576040516303161cbd60e41b815260040160405180910390fd5b6001600160a01b03881660009081526006602090815260408083208a8452909152902061065689898789888887611135565b61066289898989610e38565b505050505050505050565b610675610dc5565b60006106808261048f565b6001600160801b03169050806000036106ac5760405163356680b760e01b815260040160405180910390fd5b6000826001600160a01b031663899308a86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107109190611eda565b905061071d836000611285565b61072781836112c6565b806001600160a01b0316836001600160a01b03167fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb8460405161076c91815260200190565b60405180910390a3505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6107bd610d5e565b61053e600061131c565b6107cf610d5e565b61053e61135a565b60006060808280808361080a7f000000000000000000000000000000000000000000000000000000000000000083611397565b6108357f00000000000000000000000000000000000000000000000000000000000000006001611397565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b604080517fdd7e41b6fe4a3be49851f7dea65a88ec7a32cc99679bf27a9078e21908588b0960208201526001600160a01b0380881692820192909252606081018590526080810186905260a0810184905290821660c0820152600090819060e0016040516020818303038152906040528051906020012090506108e181611442565b979650505050505050565b6108f4610dc5565b336000818152600c602052604090205490429061091090610cc1565b64ffffffffff161461093057610926334261146f565b6109303382611484565b6109406060850160408601611f0c565b6001600160801b0316600003610969576040516305d7ba1960e11b815260040160405180910390fd5b6000808061097985870187611f29565b9194509250905081156109d0576001600160a01b038116156109ae5760405163298ec65560e01b815260040160405180910390fd5b336000908152600a602090815260408083208784529091529020829055610a36565b6001600160a01b03811615610a3657336000818152600360209081526040808320888452825280832080546001600160a01b0319166001600160a01b038716179055928252600281528282208783529052908120805491610a3083611f78565b91905055505b336000818152600b6020908152604080832080546001818101835591855283852001889055938352600c825282208054938401815582529020889101610a7c8282611fa6565b50600090506001600160781b03610a9960608a0160408b01611f0c565b6001600160801b031614610aae576000610ab1565b60015b905060006001600160401b03610acd60408b0160208c0161201f565b6001600160401b031614610ae2576000610ae5565b60015b905085336001600160a01b03167f9bbb0d43f3d669c2a9c2bdcbb746c9f968d09d2277c9e9a39ced456e4d8a8213878c88888888604051610b2b9695949392919061203c565b60405180910390a3505050505050505050565b600b6020528160005260406000208181548110610b5a57600080fd5b90600052602060002001600091509150505481565b610b77610dc5565b6000610b838888610e10565b905080610ba35760405163849c744960e01b815260040160405180910390fd5b6001600160a01b03881660009081526005602090815260408083208a845290915281209083905b81811015610c5657610c4e8b8b8a8a85818110610be957610be96120c3565b905060200201358c8a8a87818110610c0357610c036120c3565b9050602002810190610c1591906120d9565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508b9250611499915050565b600101610bca565b50610c638a8a838b610e38565b50505050505050505050565b600c6020528160005260406000208181548110610c8b57600080fd5b6000918252602090912001546001600160401b038082169350600160401b8204169150600160801b90046001600160801b031683565b60006104b66007836001600160a01b0316610d3e565b610cdf610d5e565b63389a75e1600c52806000526020600c208054421115610d0757636f5e88186000526004601cfd5b60009055610d148161131c565b50565b610d1f610d5e565b8060601b610d3557637448fbae6000526004601cfd5b610d148161131c565b600680820460009081526020939093526040909220549190066028021c90565b638b78c6d81954331461053e576382b429006000526004601cfd5b610d816115a3565b6004805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051610dbb9190611d9d565b60405180910390a1565b60045460ff161561053e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064015b60405180910390fd5b6001600160a01b03919091166000908152600a60209081526040808320938352929052205490565b6001600160a01b0384166000908152600c602052604081205490610e5b8661050b565b905081600003610e7e5760405163c1ab6dc160e01b815260040160405180910390fd5b8185101580610e8c57508085105b15610eaa5760405163e46aea0960e01b815260040160405180910390fd5b6001600160a01b0386166000908152600c60205260408120805487908110610ed457610ed46120c3565b600091825260209091200180549091506001600160401b0316421015610f0d57604051636f312cbd60e01b815260040160405180910390fd5b8054600160401b90046001600160401b0316421115610f3f5760405163477383f360e01b815260040160405180910390fd5b8054600160801b90046001600160801b0316851115610f7157604051636b2d630f60e11b815260040160405180910390fd5b6001600160a01b038416610f9857604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b0387166000908152600b60205260408120805488908110610fc257610fc26120c3565b906000526020600020015486610fd89190612122565b9050803414610ffa5760405163078d696560e31b815260040160405180910390fd5b611003866115ec565b82548390601090611025908490600160801b90046001600160801b0316612139565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555061106f88826110578b61048f565b6001600160801b031661106a9190612160565b611285565b604051630ab714fb60e11b81526001600160a01b038681166004830152602482018890526044820183905289169063156e29f690606401600060405180830381600087803b1580156110c057600080fd5b505af11580156110d4573d6000803e3d6000fd5b5050604080518981526001600160a01b0389811660208301529181018590523393508a9250908b16907f1ed291f7d8423022df7d587aba59cfed69a7c95aeb081171cc756b396b31557f906060015b60405180910390a45050505050505050565b61113f8186611602565b1561115d576040516334a4ecb960e11b815260040160405180910390fd5b6001600160a01b03871660009081526002602090815260408083208984529091528120549061118f8989848a8a61085f565b6001600160a01b03808b1660009081526003602090815260408083208d8452825291829020548251601f8a0183900483028101830190935288835293945092909116916112049184918990899081908401838280828437600092019190915250506001600160a01b0386169392915050611624565b61122157604051638baa579f60e01b815260040160405180910390fd5b61122b8489611685565b866001600160a01b0316898b6001600160a01b03167f494f010c97f6ccb9604ae91b0030ffe42d4e29e25cc0f97acd0c81d0744baba18b60405161127191815260200190565b60405180910390a450505050505050505050565b600960205260016001609f1b03600183901c1660009081526040902080546080600785901b1681811c84186001600160801b0316901b1890555050565b5050565b600080600080600085875af19050806113175760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610e07565b505050565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b611362610dc5565b6004805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610dae3390565b606060ff83146113b1576113aa836116ae565b90506104b6565b8180546113bd90612173565b80601f01602080910402602001604051908101604052809291908181526020018280546113e990612173565b80156114365780601f1061140b57610100808354040283529160200191611436565b820191906000526020600020905b81548152906001019060200180831161141957829003601f168201915b505050505090506104b6565b60006104b661144f6116ed565b8360405161190160f01b8152600281019290925260228201526042902090565b6112c26007836001600160a01b03168361181d565b6112c26008836001600160a01b03168361181d565b6114a38185611602565b156114c15760405163e788928f60e01b815260040160405180910390fd5b60006114cd8787610e10565b9050600085856040516020016114f69291909182526001600160a01b0316602082015260400190565b60408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001209050611536848383611852565b611553576040516309bde33960e01b815260040160405180910390fd5b61155d8387611685565b846001600160a01b031687896001600160a01b03167f8de988e4fefdaa217f4ce185855faba54b1a03355ef824e83cc4014d9e4a72658960405161112391815260200190565b60045460ff1661053e5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e07565b6000600160801b82106115fe57600080fd5b5090565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b60008060006116338585611868565b9092509050600081600481111561164c5761164c6121ad565b14801561166a5750856001600160a01b0316826001600160a01b0316145b8061167b575061167b8686866118ad565b9695505050505050565b600881901c600090815260209290925260409091208054600160ff9093169290921b9091179055565b606060006116bb83611999565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561174657507f000000000000000000000000000000000000000000000000000000000000000046145b1561177057507f000000000000000000000000000000000000000000000000000000000000000090565b611818604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b8260205260068204600052604060002060068306602802815464ffffffffff8482841c188116831b8218845550505050505050565b60008261185f85846119c1565b14949350505050565b600080825160410361189e5760208301516040840151606085015160001a61189287828585611a04565b945094505050506118a6565b506000905060025b9250929050565b6000806000856001600160a01b0316631626ba7e60e01b86866040516024016118d79291906121c3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161191591906121e4565b600060405180830381855afa9150503d8060008114611950576040519150601f19603f3d011682016040523d82523d6000602084013e611955565b606091505b509150915081801561196957506020815110155b801561167b57508051630b135d3f60e11b9061198e9083016020908101908401612200565b149695505050505050565b600060ff8216601f8111156104b657604051632cd44ac360e21b815260040160405180910390fd5b600081815b84518110156119fc576119f2828683815181106119e5576119e56120c3565b6020026020010151611abe565b91506001016119c6565b509392505050565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831115611a315750600090506003611ab5565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611a85573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611aae57600060019250925050611ab5565b9150600090505b94509492505050565b6000818310611ada576000828152602084905260409020611ae9565b60008381526020839052604090205b9392505050565b6001600160a01b0381168114610d1457600080fd5b600060208284031215611b1757600080fd5b8135611ae981611af0565b60008060408385031215611b3557600080fd5b8235611b4081611af0565b946020939093013593505050565b60008060008060808587031215611b6457600080fd5b8435611b6f81611af0565b935060208501359250604085013591506060850135611b8d81611af0565b939692955090935050565b60008083601f840112611baa57600080fd5b5081356001600160401b03811115611bc157600080fd5b6020830191508360208285010111156118a657600080fd5b600080600080600080600060c0888a031215611bf457600080fd5b8735611bff81611af0565b965060208801359550604088013594506060880135611c1d81611af0565b93506080880135925060a08801356001600160401b03811115611c3f57600080fd5b611c4b8a828b01611b98565b989b979a50959850939692959293505050565b60005b83811015611c79578181015183820152602001611c61565b50506000910152565b60008151808452611c9a816020860160208601611c5e565b601f01601f19169290920160200192915050565b60ff60f81b881681526000602060e06020840152611ccf60e084018a611c82565b8381036040850152611ce1818a611c82565b606085018990526001600160a01b038816608086015260a0850187905284810360c08601528551808252602080880193509091019060005b81811015611d3557835183529284019291840191600101611d19565b50909c9b505050505050505050505050565b600080600080600060a08688031215611d5f57600080fd5b8535611d6a81611af0565b94506020860135935060408601359250606086013591506080860135611d8f81611af0565b809150509295509295909350565b6001600160a01b0391909116815260200190565b60008060008385036080811215611dc757600080fd5b6060811215611dd557600080fd5b5083925060608301356001600160401b03811115611df257600080fd5b611dfe86828701611b98565b9497909650939450505050565b60008083601f840112611e1d57600080fd5b5081356001600160401b03811115611e3457600080fd5b6020830191508360208260051b85010111156118a657600080fd5b600080600080600080600060a0888a031215611e6a57600080fd5b8735611e7581611af0565b9650602088013595506040880135611e8c81611af0565b945060608801356001600160401b0380821115611ea857600080fd5b611eb48b838c01611e0b565b909650945060808a0135915080821115611ecd57600080fd5b50611c4b8a828b01611e0b565b600060208284031215611eec57600080fd5b8151611ae981611af0565b6001600160801b0381168114610d1457600080fd5b600060208284031215611f1e57600080fd5b8135611ae981611ef7565b600080600060608486031215611f3e57600080fd5b83359250602084013591506040840135611f5781611af0565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b600060018201611f8a57611f8a611f62565b5060010190565b6001600160401b0381168114610d1457600080fd5b8135611fb181611f91565b81546001600160401b031981166001600160401b039290921691821783556020840135611fdd81611f91565b600160401b600160801b03604091821b166001600160801b0319928316841781178555908501359161200e83611ef7565b921760809190911b90911617905550565b60006020828403121561203157600080fd5b8135611ae981611f91565b8681526101008101863561204f81611f91565b6001600160401b039081166020848101919091528801359061207082611f91565b1660408381019190915287013561208681611ef7565b6001600160801b0316606083015260808201959095526001600160a01b039390931660a084015290151560c0830152151560e09091015292915050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e198436030181126120f057600080fd5b8301803591506001600160401b0382111561210a57600080fd5b6020019150600581901b36038213156118a657600080fd5b80820281158282048414176104b6576104b6611f62565b6001600160801b0382811682821603908082111561215957612159611f62565b5092915050565b808201808211156104b6576104b6611f62565b600181811c9082168061218757607f821691505b6020821081036121a757634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052602160045260246000fd5b8281526040602082015260006121dc6040830184611c82565b949350505050565b600082516121f6818460208701611c5e565b9190910192915050565b60006020828403121561221257600080fd5b505191905056fea264697066735822122099242ccc2f387cd9ad5e7d9d269c036b0c0e3bfc17f0a6b7cf1a15d37966702964736f6c63430008170033
Deployed Bytecode
0x6080604052600436106101265760003560e01c80631774e7ca1461012b5780631a010e191461016857806325692962146101ae57806332a46e4b146101b85780633f4ba83a146101d85780633f60b633146101ed5780634bfbb5321461020057806351cff8d91461021357806354d1f13d146102335780635c975abb1461023b578063715018a61461025e5780638456cb591461026657806384b0196e1461027b5780638a274f3c146102a35780638da5cb5b146102c3578063b490abde146102e5578063bbc492c014610305578063d171f02514610325578063de25de5014610338578063e369f9f514610387578063e6070b92146103c8578063f04e283e146103fe578063f091335c14610411578063f2fde38b14610449578063fee81cf41461045c575b600080fd5b34801561013757600080fd5b5061014b610146366004611b05565b61048f565b6040516001600160801b0390911681526020015b60405180910390f35b34801561017457600080fd5b506101a0610183366004611b22565b600a60209081526000928352604080842090915290825290205481565b60405190815260200161015f565b6101b66104bc565b005b3480156101c457600080fd5b506101a06101d3366004611b05565b61050b565b3480156101e457600080fd5b506101b661052e565b6101b66101fb366004611b4e565b610540565b6101b661020e366004611bd9565b6105d8565b34801561021f57600080fd5b506101b661022e366004611b05565b61066d565b6101b6610779565b34801561024757600080fd5b5060045460ff16604051901515815260200161015f565b6101b66107b5565b34801561027257600080fd5b506101b66107c7565b34801561028757600080fd5b506102906107d7565b60405161015f9796959493929190611cae565b3480156102af57600080fd5b506101a06102be366004611d47565b61085f565b3480156102cf57600080fd5b50638b78c6d819545b60405161015f9190611d9d565b3480156102f157600080fd5b506101b6610300366004611db1565b6108ec565b34801561031157600080fd5b506101a0610320366004611b22565b610b3e565b6101b6610333366004611e4f565b610b6f565b34801561034457600080fd5b50610358610353366004611b22565b610c6f565b604080516001600160401b0394851681529390921660208401526001600160801b03169082015260600161015f565b34801561039357600080fd5b506102d86103a2366004611b22565b60036020908152600092835260408084209091529082529020546001600160a01b031681565b3480156103d457600080fd5b506103e86103e3366004611b05565b610cc1565b60405164ffffffffff909116815260200161015f565b6101b661040c366004611b05565b610cd7565b34801561041d57600080fd5b506101a061042c366004611b22565b600260209081526000928352604080842090915290825290205481565b6101b6610457366004611b05565b610d17565b34801561046857600080fd5b506101a0610477366004611b05565b63389a75e1600c908152600091909152602090205490565b60016001609f1b03600182901c16600090815260096020526040812054600783901b6080161c5b92915050565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60006105216008836001600160a01b0316610d3e565b64ffffffffff1692915050565b610536610d5e565b61053e610d79565b565b610548610dc5565b60006105548585610e10565b6001600160a01b03808716600090815260036020908152604080832089845290915290205491925016811561059c57604051636e0d060560e01b815260040160405180910390fd5b6001600160a01b038116156105c457604051639fabe1c160e01b815260040160405180910390fd5b6105d086868686610e38565b505050505050565b6105e0610dc5565b6001600160a01b0380881660009081526003602090815260408083208a84529091529020541680610624576040516303161cbd60e41b815260040160405180910390fd5b6001600160a01b03881660009081526006602090815260408083208a8452909152902061065689898789888887611135565b61066289898989610e38565b505050505050505050565b610675610dc5565b60006106808261048f565b6001600160801b03169050806000036106ac5760405163356680b760e01b815260040160405180910390fd5b6000826001600160a01b031663899308a86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107109190611eda565b905061071d836000611285565b61072781836112c6565b806001600160a01b0316836001600160a01b03167fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb8460405161076c91815260200190565b60405180910390a3505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6107bd610d5e565b61053e600061131c565b6107cf610d5e565b61053e61135a565b60006060808280808361080a7f4d494e545f50415353000000000000000000000000000000000000000000000983611397565b6108357f31000000000000000000000000000000000000000000000000000000000000016001611397565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b604080517fdd7e41b6fe4a3be49851f7dea65a88ec7a32cc99679bf27a9078e21908588b0960208201526001600160a01b0380881692820192909252606081018590526080810186905260a0810184905290821660c0820152600090819060e0016040516020818303038152906040528051906020012090506108e181611442565b979650505050505050565b6108f4610dc5565b336000818152600c602052604090205490429061091090610cc1565b64ffffffffff161461093057610926334261146f565b6109303382611484565b6109406060850160408601611f0c565b6001600160801b0316600003610969576040516305d7ba1960e11b815260040160405180910390fd5b6000808061097985870187611f29565b9194509250905081156109d0576001600160a01b038116156109ae5760405163298ec65560e01b815260040160405180910390fd5b336000908152600a602090815260408083208784529091529020829055610a36565b6001600160a01b03811615610a3657336000818152600360209081526040808320888452825280832080546001600160a01b0319166001600160a01b038716179055928252600281528282208783529052908120805491610a3083611f78565b91905055505b336000818152600b6020908152604080832080546001818101835591855283852001889055938352600c825282208054938401815582529020889101610a7c8282611fa6565b50600090506001600160781b03610a9960608a0160408b01611f0c565b6001600160801b031614610aae576000610ab1565b60015b905060006001600160401b03610acd60408b0160208c0161201f565b6001600160401b031614610ae2576000610ae5565b60015b905085336001600160a01b03167f9bbb0d43f3d669c2a9c2bdcbb746c9f968d09d2277c9e9a39ced456e4d8a8213878c88888888604051610b2b9695949392919061203c565b60405180910390a3505050505050505050565b600b6020528160005260406000208181548110610b5a57600080fd5b90600052602060002001600091509150505481565b610b77610dc5565b6000610b838888610e10565b905080610ba35760405163849c744960e01b815260040160405180910390fd5b6001600160a01b03881660009081526005602090815260408083208a845290915281209083905b81811015610c5657610c4e8b8b8a8a85818110610be957610be96120c3565b905060200201358c8a8a87818110610c0357610c036120c3565b9050602002810190610c1591906120d9565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508b9250611499915050565b600101610bca565b50610c638a8a838b610e38565b50505050505050505050565b600c6020528160005260406000208181548110610c8b57600080fd5b6000918252602090912001546001600160401b038082169350600160401b8204169150600160801b90046001600160801b031683565b60006104b66007836001600160a01b0316610d3e565b610cdf610d5e565b63389a75e1600c52806000526020600c208054421115610d0757636f5e88186000526004601cfd5b60009055610d148161131c565b50565b610d1f610d5e565b8060601b610d3557637448fbae6000526004601cfd5b610d148161131c565b600680820460009081526020939093526040909220549190066028021c90565b638b78c6d81954331461053e576382b429006000526004601cfd5b610d816115a3565b6004805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051610dbb9190611d9d565b60405180910390a1565b60045460ff161561053e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064015b60405180910390fd5b6001600160a01b03919091166000908152600a60209081526040808320938352929052205490565b6001600160a01b0384166000908152600c602052604081205490610e5b8661050b565b905081600003610e7e5760405163c1ab6dc160e01b815260040160405180910390fd5b8185101580610e8c57508085105b15610eaa5760405163e46aea0960e01b815260040160405180910390fd5b6001600160a01b0386166000908152600c60205260408120805487908110610ed457610ed46120c3565b600091825260209091200180549091506001600160401b0316421015610f0d57604051636f312cbd60e01b815260040160405180910390fd5b8054600160401b90046001600160401b0316421115610f3f5760405163477383f360e01b815260040160405180910390fd5b8054600160801b90046001600160801b0316851115610f7157604051636b2d630f60e11b815260040160405180910390fd5b6001600160a01b038416610f9857604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b0387166000908152600b60205260408120805488908110610fc257610fc26120c3565b906000526020600020015486610fd89190612122565b9050803414610ffa5760405163078d696560e31b815260040160405180910390fd5b611003866115ec565b82548390601090611025908490600160801b90046001600160801b0316612139565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555061106f88826110578b61048f565b6001600160801b031661106a9190612160565b611285565b604051630ab714fb60e11b81526001600160a01b038681166004830152602482018890526044820183905289169063156e29f690606401600060405180830381600087803b1580156110c057600080fd5b505af11580156110d4573d6000803e3d6000fd5b5050604080518981526001600160a01b0389811660208301529181018590523393508a9250908b16907f1ed291f7d8423022df7d587aba59cfed69a7c95aeb081171cc756b396b31557f906060015b60405180910390a45050505050505050565b61113f8186611602565b1561115d576040516334a4ecb960e11b815260040160405180910390fd5b6001600160a01b03871660009081526002602090815260408083208984529091528120549061118f8989848a8a61085f565b6001600160a01b03808b1660009081526003602090815260408083208d8452825291829020548251601f8a0183900483028101830190935288835293945092909116916112049184918990899081908401838280828437600092019190915250506001600160a01b0386169392915050611624565b61122157604051638baa579f60e01b815260040160405180910390fd5b61122b8489611685565b866001600160a01b0316898b6001600160a01b03167f494f010c97f6ccb9604ae91b0030ffe42d4e29e25cc0f97acd0c81d0744baba18b60405161127191815260200190565b60405180910390a450505050505050505050565b600960205260016001609f1b03600183901c1660009081526040902080546080600785901b1681811c84186001600160801b0316901b1890555050565b5050565b600080600080600085875af19050806113175760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610e07565b505050565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b611362610dc5565b6004805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610dae3390565b606060ff83146113b1576113aa836116ae565b90506104b6565b8180546113bd90612173565b80601f01602080910402602001604051908101604052809291908181526020018280546113e990612173565b80156114365780601f1061140b57610100808354040283529160200191611436565b820191906000526020600020905b81548152906001019060200180831161141957829003601f168201915b505050505090506104b6565b60006104b661144f6116ed565b8360405161190160f01b8152600281019290925260228201526042902090565b6112c26007836001600160a01b03168361181d565b6112c26008836001600160a01b03168361181d565b6114a38185611602565b156114c15760405163e788928f60e01b815260040160405180910390fd5b60006114cd8787610e10565b9050600085856040516020016114f69291909182526001600160a01b0316602082015260400190565b60408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001209050611536848383611852565b611553576040516309bde33960e01b815260040160405180910390fd5b61155d8387611685565b846001600160a01b031687896001600160a01b03167f8de988e4fefdaa217f4ce185855faba54b1a03355ef824e83cc4014d9e4a72658960405161112391815260200190565b60045460ff1661053e5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e07565b6000600160801b82106115fe57600080fd5b5090565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b60008060006116338585611868565b9092509050600081600481111561164c5761164c6121ad565b14801561166a5750856001600160a01b0316826001600160a01b0316145b8061167b575061167b8686866118ad565b9695505050505050565b600881901c600090815260209290925260409091208054600160ff9093169290921b9091179055565b606060006116bb83611999565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000306001600160a01b037f000000000000000000000000b645cffd9bfb93c2c181d5be0d6a8c1d81c2aef31614801561174657507f000000000000000000000000000000000000000000000000000000000000000146145b1561177057507f31ec3ff2435ec82061d8c3707301d7db4d082cb46909b77a83f9d2df3e0acde390565b611818604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f1124dc85820b9e5ce354d22596b28435f8b4b3e3cbaa636b09163ced4d74fbe0918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b8260205260068204600052604060002060068306602802815464ffffffffff8482841c188116831b8218845550505050505050565b60008261185f85846119c1565b14949350505050565b600080825160410361189e5760208301516040840151606085015160001a61189287828585611a04565b945094505050506118a6565b506000905060025b9250929050565b6000806000856001600160a01b0316631626ba7e60e01b86866040516024016118d79291906121c3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161191591906121e4565b600060405180830381855afa9150503d8060008114611950576040519150601f19603f3d011682016040523d82523d6000602084013e611955565b606091505b509150915081801561196957506020815110155b801561167b57508051630b135d3f60e11b9061198e9083016020908101908401612200565b149695505050505050565b600060ff8216601f8111156104b657604051632cd44ac360e21b815260040160405180910390fd5b600081815b84518110156119fc576119f2828683815181106119e5576119e56120c3565b6020026020010151611abe565b91506001016119c6565b509392505050565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831115611a315750600090506003611ab5565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611a85573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611aae57600060019250925050611ab5565b9150600090505b94509492505050565b6000818310611ada576000828152602084905260409020611ae9565b60008381526020839052604090205b9392505050565b6001600160a01b0381168114610d1457600080fd5b600060208284031215611b1757600080fd5b8135611ae981611af0565b60008060408385031215611b3557600080fd5b8235611b4081611af0565b946020939093013593505050565b60008060008060808587031215611b6457600080fd5b8435611b6f81611af0565b935060208501359250604085013591506060850135611b8d81611af0565b939692955090935050565b60008083601f840112611baa57600080fd5b5081356001600160401b03811115611bc157600080fd5b6020830191508360208285010111156118a657600080fd5b600080600080600080600060c0888a031215611bf457600080fd5b8735611bff81611af0565b965060208801359550604088013594506060880135611c1d81611af0565b93506080880135925060a08801356001600160401b03811115611c3f57600080fd5b611c4b8a828b01611b98565b989b979a50959850939692959293505050565b60005b83811015611c79578181015183820152602001611c61565b50506000910152565b60008151808452611c9a816020860160208601611c5e565b601f01601f19169290920160200192915050565b60ff60f81b881681526000602060e06020840152611ccf60e084018a611c82565b8381036040850152611ce1818a611c82565b606085018990526001600160a01b038816608086015260a0850187905284810360c08601528551808252602080880193509091019060005b81811015611d3557835183529284019291840191600101611d19565b50909c9b505050505050505050505050565b600080600080600060a08688031215611d5f57600080fd5b8535611d6a81611af0565b94506020860135935060408601359250606086013591506080860135611d8f81611af0565b809150509295509295909350565b6001600160a01b0391909116815260200190565b60008060008385036080811215611dc757600080fd5b6060811215611dd557600080fd5b5083925060608301356001600160401b03811115611df257600080fd5b611dfe86828701611b98565b9497909650939450505050565b60008083601f840112611e1d57600080fd5b5081356001600160401b03811115611e3457600080fd5b6020830191508360208260051b85010111156118a657600080fd5b600080600080600080600060a0888a031215611e6a57600080fd5b8735611e7581611af0565b9650602088013595506040880135611e8c81611af0565b945060608801356001600160401b0380821115611ea857600080fd5b611eb48b838c01611e0b565b909650945060808a0135915080821115611ecd57600080fd5b50611c4b8a828b01611e0b565b600060208284031215611eec57600080fd5b8151611ae981611af0565b6001600160801b0381168114610d1457600080fd5b600060208284031215611f1e57600080fd5b8135611ae981611ef7565b600080600060608486031215611f3e57600080fd5b83359250602084013591506040840135611f5781611af0565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b600060018201611f8a57611f8a611f62565b5060010190565b6001600160401b0381168114610d1457600080fd5b8135611fb181611f91565b81546001600160401b031981166001600160401b039290921691821783556020840135611fdd81611f91565b600160401b600160801b03604091821b166001600160801b0319928316841781178555908501359161200e83611ef7565b921760809190911b90911617905550565b60006020828403121561203157600080fd5b8135611ae981611f91565b8681526101008101863561204f81611f91565b6001600160401b039081166020848101919091528801359061207082611f91565b1660408381019190915287013561208681611ef7565b6001600160801b0316606083015260808201959095526001600160a01b039390931660a084015290151560c0830152151560e09091015292915050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e198436030181126120f057600080fd5b8301803591506001600160401b0382111561210a57600080fd5b6020019150600581901b36038213156118a657600080fd5b80820281158282048414176104b6576104b6611f62565b6001600160801b0382811682821603908082111561215957612159611f62565b5092915050565b808201808211156104b6576104b6611f62565b600181811c9082168061218757607f821691505b6020821081036121a757634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052602160045260246000fd5b8281526040602082015260006121dc6040830184611c82565b949350505050565b600082516121f6818460208701611c5e565b9190910192915050565b60006020828403121561221257600080fd5b505191905056fea264697066735822122099242ccc2f387cd9ad5e7d9d269c036b0c0e3bfc17f0a6b7cf1a15d37966702964736f6c63430008170033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $2,618.66 | 9.0871 | $23,795.97 |
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.