ERC-721
Overview
Max Total Supply
0 GUV
Holders
294
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
0 GUVLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
UserVault
Compiler Version
v0.8.21+commit.d9974bed
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.21; import "@openzeppelin/utils/Strings.sol"; import "@solmate/auth/Owned.sol"; import "@solmate/tokens/ERC721.sol"; import "@solmate/tokens/ERC1155.sol"; import "@solmate/utils/SafeTransferLib.sol"; import "../interfaces/IOldERC721.sol"; import "../interfaces/IUserVault.sol"; import "./AddressManager.sol"; /// @title Auction Loan Liquidator /// @author Florida St /// @notice NFTs that represent bundles. /// @dev This vault does not support rebasing tokens. Rebasing tokens can cause accounting /// @dev errors since the vault tracks balances internally and won't update when rebases occur. contract UserVault is ERC721, ERC721TokenReceiver, ERC1155TokenReceiver, IUserVault { using SafeTransferLib for ERC20; string private constant _BASE_URI = "https://gondi.xyz/user_vaults/"; uint256 private _nextId = 0; address public constant ETH = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); /// @notice IDs that were burnt are pending withdrawal mapping(uint256 vaultId => address claimer) _readyForWithdrawal; /// @notice NFT balances for a given vault: collection => (tokenId => vaultId) mapping(address collection => mapping(uint256 tokenId => uint256 vaultId)) _vaultERC721s; /// @notice ERC20 balances for a given vault: token => (vaultId => amount). address(0) = ETH mapping(address token => mapping(uint256 vaultId => uint256 amount)) _vaultERC20s; /// @notice ERC1155 balances for a given vault: token => (vaultId => amount). address(0) = ETH mapping(address token => mapping(uint256 tokenId => mapping(uint256 vaultId => uint256 amount))) _vaultERC1155s; AddressManager private immutable _currencyManager; AddressManager private immutable _collectionManager; event ERC721Deposited(uint256 vaultId, address collection, uint256 tokenId); event ERC20Deposited(uint256 vaultId, address token, uint256 amount); event ERC1155Deposited( uint256 vaultId, address token, uint256 tokenId, uint256 amount ); event ERC721Withdrawn(uint256 vaultId, address collection, uint256 tokenId); event ERC20Withdrawn(uint256 vaultId, address token, uint256 amount); event ERC1155Withdrawn( uint256 vaultId, address token, uint256 tokenId, uint256 amount ); error CurrencyNotWhitelistedError(); error CollectionNotWhitelistedError(); error LengthMismatchError(); error NotApprovedError(uint256 vaultId); error WithdrawingETHError(); error WrongMethodError(); error AssetNotOwnedError(); error VaultNotExistsError(); error InvalidCallerError(); /// @param currencyManager Address of the CurrencyManager contract. /// @param collectionManager Address of the CollectionManager contract. constructor( address currencyManager, address collectionManager ) ERC721("GONDI_USER_VAULT", "GUV") { _currencyManager = AddressManager(currencyManager); _collectionManager = AddressManager(collectionManager); } /// @inheritdoc IUserVault function mint() external returns (uint256) { uint256 _vaultId; unchecked { _vaultId = ++_nextId; } _mint(msg.sender, _vaultId); return _vaultId; } /// @inheritdoc IUserVault function burn(uint256 _vaultId, address _assetRecipient) external { _thisBurn(_vaultId, _assetRecipient); } /// @inheritdoc IUserVault function burnAndWithdraw( uint256 _vaultId, address[] calldata _collections, uint256[] calldata _tokenIds, address[] calldata _tokens, address[] calldata _erc1155Tokens, uint256[] calldata _erc1155TokensIds ) external { _thisBurn(_vaultId, msg.sender); uint256 totalCollections = _collections.length; if (totalCollections != _tokenIds.length) { revert LengthMismatchError(); } for (uint256 i = 0; i < totalCollections; ) { _withdrawERC721(_vaultId, _collections[i], _tokenIds[i]); unchecked { ++i; } } uint256 totalTokens = _tokens.length; for (uint256 i = 0; i < totalTokens; ) { _withdrawERC20(_vaultId, _tokens[i]); unchecked { ++i; } } uint256 totalERC1155Tokens = _erc1155Tokens.length; for (uint256 i = 0; i < totalERC1155Tokens; ) { _withdrawERC1155(_vaultId, _erc1155Tokens[i], _erc1155TokensIds[i]); unchecked { ++i; } } _withdrawEth(_vaultId); } function ERC721OwnerOf( address _collection, uint256 _tokenId ) external view returns (uint256) { return _vaultERC721s[_collection][_tokenId]; } function ERC20BalanceOf( uint256 _vaultId, address _token ) external view returns (uint256) { return _vaultERC20s[_token][_vaultId]; } function ERC1155BalanceOf( uint256 _vaultId, address _token, uint256 _tokenId ) external view returns (uint256) { return _vaultERC1155s[_token][_tokenId][_vaultId]; } /// @inheritdoc IUserVault function depositERC721( uint256 _vaultId, address _collection, uint256 _tokenId ) external { _vaultExists(_vaultId); if (!_collectionManager.isWhitelisted(_collection)) { revert CollectionNotWhitelistedError(); } _depositERC721(msg.sender, _vaultId, _collection, _tokenId); } /// @inheritdoc IUserVault /// @dev Read `depositERC721`. function depositERC721s( uint256 _vaultId, address _collection, uint256[] calldata _tokenIds ) external { _vaultExists(_vaultId); if (!_collectionManager.isWhitelisted(_collection)) { revert CollectionNotWhitelistedError(); } uint256 totalTokens = _tokenIds.length; for (uint256 i = 0; i < totalTokens; ) { _depositERC721(msg.sender, _vaultId, _collection, _tokenIds[i]); unchecked { ++i; } } } /// @inheritdoc IUserVault /// @dev Read `depositERC721`. function depositERC20( uint256 _vaultId, address _token, uint256 _amount ) external { _vaultExists(_vaultId); if (_token == ETH) { revert WrongMethodError(); } _depositERC20(msg.sender, _vaultId, _token, _amount); } /// @inheritdoc IUserVault /// @dev Read `depositERC1155`. function depositERC1155( uint256 _vaultId, address _token, uint256 _tokenId, uint256 _amount ) external { _vaultExists(_vaultId); if (!_collectionManager.isWhitelisted(_token)) { revert CollectionNotWhitelistedError(); } _depositERC1155(msg.sender, _vaultId, _token, _tokenId, _amount); } /// @inheritdoc IUserVault /// @dev Read `depositERC1155s`. function depositERC1155s( uint256 _vaultId, address _collection, uint256[] calldata _tokenIds, uint256[] calldata _amounts ) external { _vaultExists(_vaultId); if (!_collectionManager.isWhitelisted(_collection)) { revert CollectionNotWhitelistedError(); } uint256 totalTokens = _tokenIds.length; for (uint256 i = 0; i < totalTokens; ) { _depositERC1155( msg.sender, _vaultId, _collection, _tokenIds[i], _amounts[i] ); unchecked { ++i; } } } /// @inheritdoc IUserVault /// @dev Read `depositERC721`. function depositEth(uint256 _vaultId) external payable { _vaultExists(_vaultId); _vaultERC20s[ETH][_vaultId] += msg.value; emit ERC20Deposited(_vaultId, ETH, msg.value); } /// @inheritdoc IUserVault function withdrawERC721( uint256 _vaultId, address _collection, uint256 _tokenId ) external { _withdrawERC721(_vaultId, _collection, _tokenId); } /// @inheritdoc IUserVault function withdrawERC721s( uint256 _vaultId, address[] calldata _collections, uint256[] calldata _tokenIds ) external { if (_collections.length != _tokenIds.length) { revert LengthMismatchError(); } uint256 totalCollections = _collections.length; for (uint256 i = 0; i < totalCollections; ) { _withdrawERC721(_vaultId, _collections[i], _tokenIds[i]); unchecked { ++i; } } } /// @inheritdoc IUserVault function withdrawERC20(uint256 _vaultId, address _token) external { _withdrawERC20(_vaultId, _token); } /// @inheritdoc IUserVault function withdrawERC20s( uint256 _vaultId, address[] calldata _tokens ) external { for (uint256 i = 0; i < _tokens.length; ) { _withdrawERC20(_vaultId, _tokens[i]); unchecked { ++i; } } } /// @inheritdoc IUserVault function withdrawERC1155( uint256 _vaultId, address _token, uint256 _tokenId ) external { _withdrawERC1155(_vaultId, _token, _tokenId); } /// @inheritdoc IUserVault function withdrawERC1155s( uint256 _vaultId, address[] calldata _tokens, uint256[] calldata _tokenIds ) external { if (_tokens.length != _tokenIds.length) { revert LengthMismatchError(); } uint256 totalCollections = _tokens.length; for (uint256 i = 0; i < totalCollections; ) { _withdrawERC1155(_vaultId, _tokens[i], _tokenIds[i]); unchecked { ++i; } } } /// @inheritdoc IUserVault function withdrawEth(uint256 _vaultId) external { _withdrawEth(_vaultId); } /// @inheritdoc ERC721 function tokenURI( uint256 _vaultId ) public pure override returns (string memory) { return string.concat(_BASE_URI, Strings.toString(_vaultId)); } function _depositERC721( address _depositor, uint256 _vaultId, address _collection, uint256 _tokenId ) private { ERC721(_collection).transferFrom(_depositor, address(this), _tokenId); _vaultERC721s[_collection][_tokenId] = _vaultId; emit ERC721Deposited(_vaultId, _collection, _tokenId); } function _depositERC20( address _depositor, uint256 _vaultId, address _token, uint256 _amount ) private { if (!_currencyManager.isWhitelisted(_token)) { revert CurrencyNotWhitelistedError(); } ERC20(_token).safeTransferFrom(_depositor, address(this), _amount); _vaultERC20s[_token][_vaultId] += _amount; emit ERC20Deposited(_vaultId, _token, _amount); } function _depositERC1155( address _depositor, uint256 _vaultId, address _token, uint256 _tokenId, uint256 _amount ) private { ERC1155(_token).safeTransferFrom( _depositor, address(this), _tokenId, _amount, "" ); _vaultERC1155s[_token][_tokenId][_vaultId] += _amount; emit ERC1155Deposited(_vaultId, _token, _tokenId, _amount); } /// @dev We are allowing anyone to deposit NFTs into a vault (not just the owner). Because of this we call transferFrom /// and not safeTransferFrom to avoid someone locking assets by transferring an ERC721 with the hook corrupted (we do /// have a whitelist to avoid this but being extra cautious.) function _withdrawERC721( uint256 _vaultId, address _collection, uint256 _tokenId ) private { _onlyReadyForWithdrawal(_vaultId); if (_vaultERC721s[_collection][_tokenId] != _vaultId) { revert AssetNotOwnedError(); } ERC721(_collection).transferFrom(address(this), msg.sender, _tokenId); delete _vaultERC721s[_collection][_tokenId]; emit ERC721Withdrawn(_vaultId, _collection, _tokenId); } function _withdrawERC20(uint256 _vaultId, address _token) private { _onlyReadyForWithdrawal(_vaultId); uint256 amount = _vaultERC20s[_token][_vaultId]; if (amount == 0) { return; } delete _vaultERC20s[_token][_vaultId]; ERC20(_token).safeTransfer(msg.sender, amount); emit ERC20Withdrawn(_vaultId, _token, amount); } function _withdrawERC1155( uint256 _vaultId, address _token, uint256 _tokenId ) private { _onlyReadyForWithdrawal(_vaultId); uint256 amount = _vaultERC1155s[_token][_tokenId][_vaultId]; if (amount == 0) { return; } delete _vaultERC1155s[_token][_tokenId][_vaultId]; ERC1155(_token).safeTransferFrom( address(this), msg.sender, _tokenId, amount, "" ); emit ERC1155Withdrawn(_vaultId, _token, _tokenId, amount); } function _thisBurn(uint256 _vaultId, address _assetRecipient) private { _onlyApproved(_vaultId); _burn(_vaultId); _readyForWithdrawal[_vaultId] = _assetRecipient; } function _withdrawEth(uint256 _vaultId) private { _onlyReadyForWithdrawal(_vaultId); uint256 amount = _vaultERC20s[ETH][_vaultId]; if (amount == 0) { return; } delete _vaultERC20s[ETH][_vaultId]; (bool sent, ) = payable(msg.sender).call{value: amount}(""); if (!sent) { revert WithdrawingETHError(); } emit ERC20Withdrawn(_vaultId, ETH, amount); } function _vaultExists(uint256 _vaultId) private view { bytes4 errorSelector = VaultNotExistsError.selector; address owner = _ownerOf[_vaultId]; assembly { if iszero(owner) { mstore(0x00, errorSelector) revert(0x00, 0x04) } } } function _onlyApproved(uint256 _vaultId) private view { if ( msg.sender != ownerOf(_vaultId) && !isApprovedForAll[ownerOf(_vaultId)][msg.sender] && getApproved[_vaultId] != msg.sender ) { revert NotApprovedError(_vaultId); } } function _onlyReadyForWithdrawal(uint256 _vaultId) private view { if (_readyForWithdrawal[_vaultId] != msg.sender) { revert NotApprovedError(_vaultId); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @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), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(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) { uint256 localValue = value; 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] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } 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 bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Minimalist and gas efficient standard ERC1155 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); /*////////////////////////////////////////////////////////////// ERC1155 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// METADATA LOGIC //////////////////////////////////////////////////////////////*/ function uri(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC1155 LOGIC //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; for (uint256 i = 0; i < ids.length; ) { id = ids[i]; amount = amounts[i]; balanceOf[from][id] -= amount; balanceOf[to][id] += amount; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { require(owners.length == ids.length, "LENGTH_MISMATCH"); balances = new uint256[](owners.length); // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < owners.length; ++i) { balances[i] = balanceOf[owners[i]][ids[i]]; } } } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[to][ids[i]] += amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, address(0), to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function _batchBurn( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[from][ids[i]] -= amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, address(0), ids, amounts); } function _burn( address from, uint256 id, uint256 amount ) internal virtual { balanceOf[from][id] -= amount; emit TransferSingle(msg.sender, from, address(0), id, amount); } } /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155TokenReceiver { function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// 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: AGPL-3.0 pragma solidity ^0.8.21; /// @title IOldERC721 /// @notice Interface for the old ERC721 standard. interface IOldERC721 { function balanceOf(address _owner) external view returns (uint256 _balance); function ownerOf(uint256 _tokenId) external view returns (address _owner); function transfer(address _to, uint256 _tokenId) external; function approve(address _to, uint256 _tokenId) external; function takeOwnership(uint256 _tokenId) external; function tokenURI( uint256 _tokenId ) external view returns (string memory _uri); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.20; interface IUserVault { /// @notice Mint a new vault to msg.sender /// @return newId The id of the new vault function mint() external returns (uint256); /// @notice Burn a vault and return all assets to owner. function burn(uint256 _vaultId, address _assetRecipient) external; /// @notice Burn a vault and return all assets to owner. /// @param _vaultId The vault to burn. /// @param _collections The NFT collections to withdraw. /// @param _tokenIds The NFT token IDs to burn. /// @param _tokens The ERC20 tokens to withdraw. /// @param _collections The ERC1155 collections to withdraw. /// @param _tokenIds The ERC1155 token IDs to burn. function burnAndWithdraw( uint256 _vaultId, address[] calldata _collections, uint256[] calldata _tokenIds, address[] calldata _tokens, address[] calldata _erc1155Tokens, uint256[] calldata _erc1155TokensIds ) external; /// @notice Get the vault owner of an NFT. Will return 0 if none. /// @param _collection The NFT collection. /// @param _tokenId The NFT token ID. /// @return vaultId The vault owning the NFT. function ERC721OwnerOf( address _collection, uint256 _tokenId ) external view returns (uint256); /// @notice Get the balance for a given token for a given vault. address(0) = ETH /// @param _vaultId The vault to check. /// @param _token The token to check. /// @return Balance The balance of the token in the vault. function ERC20BalanceOf( uint256 _vaultId, address _token ) external view returns (uint256); /// @notice Deposit an NFT into the vault. /// @param _vaultId The vault to deposit into. /// @param _collection The NFT collection. /// @param _tokenId The NFT token ID. function depositERC721( uint256 _vaultId, address _collection, uint256 _tokenId ) external; /// @notice Deposit multiple NFTs. /// @param _vaultId The vault to deposit into. /// @param _collection The NFT collection. /// @param _tokenIds The NFT token IDs. function depositERC721s( uint256 _vaultId, address _collection, uint256[] calldata _tokenIds ) external; /// @notice Deposit an ERC20 token into the vault. /// @param _vaultId The vault to deposit into. /// @param _token The ERC20 token. /// @param _amount The amount to deposit. function depositERC20( uint256 _vaultId, address _token, uint256 _amount ) external; /// @notice Deposit an ERC1155 token into the vault. /// @param _vaultId The vault to deposit into. /// @param _token The ERC1155 token. /// @param _tokenId The ERC1155 token. /// @param _amount The amount to deposit. function depositERC1155( uint256 _vaultId, address _token, uint256 _tokenId, uint256 _amount ) external; /// @notice Deposit multiple ERC1155 tokens into the vault. /// @param _vaultId The vault to deposit into. /// @param _token The ERC1155 token. /// @param _tokenIds The ERC1155 token. /// @param _amounts The amount to deposit. function depositERC1155s( uint256 _vaultId, address _token, uint256[] calldata _tokenIds, uint256[] calldata _amounts ) external; /// @notice Deposit ETH into the vault. /// @param _vaultId The vault to deposit into. function depositEth(uint256 _vaultId) external payable; /// @notice Withdraw an NFT from the vault. /// @param _vaultId The vault to withdraw from. /// @param _collection The NFT collection. /// @param _tokenId The NFT token ID. function withdrawERC721( uint256 _vaultId, address _collection, uint256 _tokenId ) external; /// @notice Withdraw multiple NFTs. /// @param _vaultId The vault to withdraw from. /// @param _collections The NFT collections. /// @param _tokenIds The NFT token IDs. function withdrawERC721s( uint256 _vaultId, address[] calldata _collections, uint256[] calldata _tokenIds ) external; /// @notice Withdraw an ERC20 token from the vault. /// @param _vaultId The vault to withdraw from. /// @param _token The ERC20 token. function withdrawERC20(uint256 _vaultId, address _token) external; /// @notice Withdraw ERC20s from the vault. /// @param _vaultId The vault to withdraw from. /// @param _tokens The ERC20 tokens. function withdrawERC20s( uint256 _vaultId, address[] calldata _tokens ) external; /// @notice Withdraw an ERC20 token from the vault. /// @param _vaultId The vault to withdraw from. /// @param _token The ERC20 token. function withdrawERC1155( uint256 _vaultId, address _token, uint256 _tokenId ) external; /// @notice Withdraw ERC20s from the vault. /// @param _vaultId The vault to withdraw from. /// @param _tokens The ERC20 tokens. function withdrawERC1155s( uint256 _vaultId, address[] calldata _tokens, uint256[] calldata _tokenIds ) external; /// @notice Withdraw ETH from the vault. /// @param _vaultId The vault to withdraw from. function withdrawEth(uint256 _vaultId) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.21; import "@solmate/auth/Owned.sol"; import "@solmate/utils/ReentrancyGuard.sol"; import "./InputChecker.sol"; /// @title AddressManager /// @notice A contract that handles a whitelist of addresses and their indexes. /// @dev We assume no more than 65535 addresses will be added to the directory. contract AddressManager is Owned, ReentrancyGuard { using InputChecker for address; event AddressAdded(address address_added); event AddressRemovedFromWhitelist(address address_removed); event AddressWhitelisted(address address_whitelisted); error AddressAlreadyAddedError(address _address); error AddressNotAddedError(address _address); mapping(address => uint16) private _directory; mapping(uint16 => address) private _inverseDirectory; mapping(address => bool) private _whitelist; uint16 private _lastAdded; constructor(address[] memory _original) Owned(tx.origin) { uint256 total = _original.length; for (uint256 i; i < total;) { _add(_original[i]); unchecked { ++i; } } } /// @notice Adds an address to the directory. If it already exists, /// reverts. It assumes it's whitelisted. /// @param _entry The address to add. /// @return The index of the address in the directory. function add(address _entry) external payable onlyOwner returns (uint16) { return _add(_entry); } /// @notice Whitelist an address that's already part of the directory. /// @param _entry The address to whitelist. function addToWhitelist(address _entry) external payable onlyOwner { if (_directory[_entry] == 0) { revert AddressNotAddedError(_entry); } _whitelist[_entry] = true; emit AddressWhitelisted(_entry); } /// @notice Removes an address from the whitelist. We still keep it /// in the directory since this mapping is relevant across time. /// @param _entry The address to remove from the whitelist. function removeFromWhitelist(address _entry) external payable onlyOwner { _whitelist[_entry] = false; emit AddressRemovedFromWhitelist(_entry); } /// @param _address The address to get the index for. /// @return The index for a given address. function addressToIndex(address _address) external view returns (uint16) { return _directory[_address]; } /// @param _index The index to get the address for. /// @return The address for a given index. function indexToAddress(uint16 _index) external view returns (address) { return _inverseDirectory[_index]; } /// @param _entry The address to check if it's whitelisted. /// @return Whether the address is whitelisted or not. function isWhitelisted(address _entry) external view returns (bool) { return _whitelist[_entry]; } function _add(address _entry) private returns (uint16) { _entry.checkNotZero(); if (_directory[_entry] != 0) { revert AddressAlreadyAddedError(_entry); } unchecked { ++_lastAdded; } _directory[_entry] = _lastAdded; _inverseDirectory[_lastAdded] = _entry; _whitelist[_entry] = true; emit AddressAdded(_entry); return _lastAdded; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; import {Panic} from "../Panic.sol"; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an success flag (no overflow). */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). */ function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). */ function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a success flag (no division by zero). */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). */ function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * SafeCast.toUint(condition)); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(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 towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. Panic.panic(Panic.DIVISION_BY_ZERO); } // The following calculation ensures accurate ceiling division without overflow. // Since a is non-zero, (a - 1) / b will not overflow. // The largest possible result occurs when (a - 1) / b is type(uint256).max, // but the largest value we can obtain is type(uint256).max - 1, which happens // when a = type(uint256).max and b = 1. unchecked { return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); } } /** * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * * 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²⁵⁶ and mod 2²⁵⁶ - 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²⁵⁶ + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) 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²⁵⁶. Also prevents denominator == 0. if (denominator <= prod1) { Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_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. uint256 twos = denominator & (0 - denominator); 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²⁵⁶ / 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²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv ≡ 1 mod 2⁴. 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⁸ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ inverse *= 2 - denominator * inverse; // inverse mod 2³² inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ // 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²⁵⁶. Since the preconditions guarantee that the outcome is // less than 2²⁵⁶, 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; } } /** * @dev 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) { return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, expect 0. * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. * * If the input value is not inversible, 0 is returned. * * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Ferma's little theorem and get the * inverse using `Math.modExp(a, n - 2, n)`. */ function invMod(uint256 a, uint256 n) internal pure returns (uint256) { unchecked { if (n == 0) return 0; // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) // Used to compute integers x and y such that: ax + ny = gcd(a, n). // When the gcd is 1, then the inverse of a modulo n exists and it's x. // ax + ny = 1 // ax = 1 + (-y)n // ax ≡ 1 (mod n) # x is the inverse of a modulo n // If the remainder is 0 the gcd is n right away. uint256 remainder = a % n; uint256 gcd = n; // Therefore the initial coefficients are: // ax + ny = gcd(a, n) = n // 0a + 1n = n int256 x = 0; int256 y = 1; while (remainder != 0) { uint256 quotient = gcd / remainder; (gcd, remainder) = ( // The old remainder is the next gcd to try. remainder, // Compute the next remainder. // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd // where gcd is at most n (capped to type(uint256).max) gcd - remainder * quotient ); (x, y) = ( // Increment the coefficient of a. y, // Decrement the coefficient of n. // Can overflow, but the result is casted to uint256 so that the // next value of y is "wrapped around" to a value between 0 and n - 1. x - y * int256(quotient) ); } if (gcd != 1) return 0; // No inverse exists. return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. } } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) * * Requirements: * - modulus can't be zero * - underlying staticcall to precompile must succeed * * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make * sure the chain you're using it on supports the precompiled contract for modular exponentiation * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, * the underlying function will succeed given the lack of a revert, but the result may be incorrectly * interpreted as 0. */ function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { (bool success, uint256 result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). * It includes a success flag indicating if the operation succeeded. Operation will be marked has failed if trying * to operate modulo 0 or if the underlying precompile reverted. * * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack * of a revert, but the result may be incorrectly interpreted as 0. */ function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { if (m == 0) return (false, 0); /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) // | Offset | Content | Content (Hex) | // |-----------|------------|--------------------------------------------------------------------| // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x60:0x7f | value of b | 0x<.............................................................b> | // | 0x80:0x9f | value of e | 0x<.............................................................e> | // | 0xa0:0xbf | value of m | 0x<.............................................................m> | mstore(ptr, 0x20) mstore(add(ptr, 0x20), 0x20) mstore(add(ptr, 0x40), 0x20) mstore(add(ptr, 0x60), b) mstore(add(ptr, 0x80), e) mstore(add(ptr, 0xa0), m) // Given the result < m, it's guaranteed to fit in 32 bytes, // so we can use the memory scratch space located at offset 0. success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) result := mload(0x00) } } /** * @dev Variant of {modExp} that supports inputs of arbitrary length. */ function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { (bool success, bytes memory result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Variant of {tryModExp} that supports inputs of arbitrary length. */ function tryModExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bool success, bytes memory result) { if (_zeroBytes(m)) return (false, new bytes(0)); uint256 mLen = m.length; // Encode call args in result and move the free memory pointer result = abi.encodePacked(b.length, e.length, mLen, b, e, m); /// @solidity memory-safe-assembly assembly { let dataPtr := add(result, 0x20) // Write result on top of args to avoid allocating extra memory. success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) // Overwrite the length. // result.length > returndatasize() is guaranteed because returndatasize() == m.length mstore(result, mLen) // Set the memory pointer after the returned data. mstore(0x40, add(dataPtr, mLen)) } } /** * @dev Returns whether the provided byte array is zero. */ function _zeroBytes(bytes memory byteArray) private pure returns (bool) { for (uint256 i = 0; i < byteArray.length; ++i) { if (byteArray[i] != 0) { return false; } } return true; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * This method is based on Newton's method for computing square roots; the algorithm is restricted to only * using integer operations. */ function sqrt(uint256 a) internal pure returns (uint256) { unchecked { // Take care of easy edge cases when a == 0 or a == 1 if (a <= 1) { return a; } // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between // the current value as `ε_n = | x_n - sqrt(a) |`. // // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is // bigger than any uint256. // // By noticing that // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar // to the msb function. uint256 aa = a; uint256 xn = 1; if (aa >= (1 << 128)) { aa >>= 128; xn <<= 64; } if (aa >= (1 << 64)) { aa >>= 64; xn <<= 32; } if (aa >= (1 << 32)) { aa >>= 32; xn <<= 16; } if (aa >= (1 << 16)) { aa >>= 16; xn <<= 8; } if (aa >= (1 << 8)) { aa >>= 8; xn <<= 4; } if (aa >= (1 << 4)) { aa >>= 4; xn <<= 2; } if (aa >= (1 << 2)) { xn <<= 1; } // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). // // We can refine our estimation by noticing that the middle of that interval minimizes the error. // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). // This is going to be our x_0 (and ε_0) xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) // From here, Newton's method give us: // x_{n+1} = (x_n + a / x_n) / 2 // // One should note that: // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a // = ((x_n² + a) / (2 * x_n))² - a // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) // = (x_n² - a)² / (2 * x_n)² // = ((x_n² - a) / (2 * x_n))² // ≥ 0 // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n // // This gives us the proof of quadratic convergence of the sequence: // ε_{n+1} = | x_{n+1} - sqrt(a) | // = | (x_n + a / x_n) / 2 - sqrt(a) | // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | // = | (x_n - sqrt(a))² / (2 * x_n) | // = | ε_n² / (2 * x_n) | // = ε_n² / | (2 * x_n) | // // For the first iteration, we have a special case where x_0 is known: // ε_1 = ε_0² / | (2 * x_0) | // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) // ≤ 2**(2*e-4) / (3 * 2**(e-1)) // ≤ 2**(e-3) / 3 // ≤ 2**(e-3-log2(3)) // ≤ 2**(e-4.5) // // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: // ε_{n+1} = ε_n² / | (2 * x_n) | // ≤ (2**(e-k))² / (2 * 2**(e-1)) // ≤ 2**(2*e-2*k) / 2**e // ≤ 2**(e-2*k) xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either // sqrt(a) or sqrt(a) + 1. return xn - SafeCast.toUint(xn > a / xn); } } /** * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 exp; unchecked { exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; result += SafeCast.toUint(value > 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * 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; uint256 isGt; unchecked { isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; result += SafeCast.toUint(value > (1 << 8) - 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * int256(SafeCast.toUint(condition))); } } /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return ternary(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 { // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson. // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift, // taking advantage of the most significant (or "sign" bit) in two's complement representation. // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result, // the mask will either be `bytes(0)` (if n is positive) or `~bytes32(0)` (if n is negative). int256 mask = n >> 255; // A `bytes(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it. return uint256((n + mask) ^ mask); } } }
// 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: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Gas optimized reentrancy protection for smart contracts. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) abstract contract ReentrancyGuard { uint256 private locked = 1; modifier nonReentrant() virtual { require(locked == 1, "REENTRANCY"); locked = 2; _; locked = 1; } }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.21; /// @title InputChecker /// @author Florida St /// @notice Some basic input checks. library InputChecker { error AddressZeroError(); function checkNotZero(address _address) internal pure { if (_address == address(0)) { revert AddressZeroError(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @dev Helper library for emitting standardized panic codes. * * ```solidity * contract Example { * using Panic for uint256; * * // Use any of the declared internal constants * function foo() { Panic.GENERIC.panic(); } * * // Alternatively * function foo() { Panic.panic(Panic.GENERIC); } * } * ``` * * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. */ // slither-disable-next-line unused-state library Panic { /// @dev generic / unspecified error uint256 internal constant GENERIC = 0x00; /// @dev used by the assert() builtin uint256 internal constant ASSERT = 0x01; /// @dev arithmetic underflow or overflow uint256 internal constant UNDER_OVERFLOW = 0x11; /// @dev division or modulo by zero uint256 internal constant DIVISION_BY_ZERO = 0x12; /// @dev enum conversion error uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; /// @dev invalid encoding in storage uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; /// @dev empty array pop uint256 internal constant EMPTY_ARRAY_POP = 0x31; /// @dev array out of bounds access uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; /// @dev resource error (too large allocation or too large array) uint256 internal constant RESOURCE_ERROR = 0x41; /// @dev calling invalid internal function uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; /// @dev Reverts with a panic code. Recommended to use with /// the internal constants with predefined codes. function panic(uint256 code) internal pure { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x4e487b71) mstore(0x20, code) revert(0x1c, 0x24) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { /// @solidity memory-safe-assembly assembly { u := iszero(iszero(b)) } } }
{ "remappings": [ "@forge-std/=lib/forge-std/src/", "@openzeppelin/=lib/openzeppelin-contracts/contracts/", "@solady/=lib/solady/src/", "@solmate/=lib/solmate/src/", "@zora/=lib/v3/contracts/", "@chainlink/=lib/chainlink/contracts/src/v0.8/", "@delegate/=lib/delegate-registry/src/", "@seaport/=lib/seaport/lib/", "test/=test/", "@const/=src/const/default/", "@manifoldxyz/=lib/v3/node_modules/@manifoldxyz/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@rari-capital/=lib/v3/node_modules/@rari-capital/", "@rari-capital/solmate/=lib/seaport/lib/solmate/", "chainlink/=lib/chainlink/contracts/", "delegate-registry/=lib/delegate-registry/", "ds-test/=lib/seaport/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "murky/=lib/delegate-registry/lib/murky/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/delegate-registry/lib/openzeppelin-contracts/contracts/", "seaport-core/=lib/seaport/lib/seaport-core/", "seaport-sol/=lib/seaport/lib/seaport-sol/", "seaport-types/=lib/seaport/lib/seaport-types/", "seaport/=lib/seaport/", "solady/=lib/solady/src/", "solarray/=lib/seaport/lib/solarray/src/", "solmate/=lib/solmate/src/", "v3/=lib/v3/contracts/" ], "optimizer": { "enabled": true, "runs": 20 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"currencyManager","type":"address"},{"internalType":"address","name":"collectionManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AssetNotOwnedError","type":"error"},{"inputs":[],"name":"CollectionNotWhitelistedError","type":"error"},{"inputs":[],"name":"CurrencyNotWhitelistedError","type":"error"},{"inputs":[],"name":"InvalidCallerError","type":"error"},{"inputs":[],"name":"LengthMismatchError","type":"error"},{"inputs":[{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"NotApprovedError","type":"error"},{"inputs":[],"name":"VaultNotExistsError","type":"error"},{"inputs":[],"name":"WithdrawingETHError","type":"error"},{"inputs":[],"name":"WrongMethodError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC1155Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC1155Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ERC1155BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"ERC20BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ERC721OwnerOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_assetRecipient","type":"address"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address[]","name":"_collections","type":"address[]"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address[]","name":"_erc1155Tokens","type":"address[]"},{"internalType":"uint256[]","name":"_erc1155TokensIds","type":"uint256[]"}],"name":"burnAndWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"depositERC1155s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"depositERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"depositERC721s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"depositEth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"withdrawERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"withdrawERC1155s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"withdrawERC20s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"withdrawERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address[]","name":"_collections","type":"address[]"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"withdrawERC721s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"withdrawEth","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c034620003a0576001600160401b0390601f90601f19906200283738819003848101841683019190868311848410176200038a578084926040948552833981010312620003a0576200005281620003c5565b93620000626020809301620003c5565b936200006d620003a5565b92601084526f11d3d3911257d554d15497d59055531560821b8185015262000094620003a5565b90600382526223aaab60e91b818301528451958487116200038a576000968754966001978881811c911680156200037f575b858210146200036b5790818784931162000318575b508490878311600114620002b7578a92620002ab575b5050600019600383901b1c191690871b1787555b8251948511620002975785548681811c911680156200028c575b8382101462000278579081858796959493116200021f575b5081938511600114620001ba5750508592620001ae575b5050600019600383901b1c191690821b1790555b6006556001600160a01b039182166080521660a05260405161245c9081620003db823960805181611212015260a051818181610a0501528181610bfb01528181610ca401526110c00152f35b0151905038806200014e565b869593929193168588528388209388905b828210620002055750508411620001eb575b505050811b01905562000162565b015160001960f88460031b161c19169055388080620001dd565b8484015186558897909501949384019390810190620001cb565b9091929394508688528288208580880160051c8201928589106200026e575b9188978a9297969594930160051c01915b8281106200025f57505062000137565b8a81558897508991016200024f565b925081926200023e565b634e487b7160e01b88526022600452602488fd5b90607f16906200011f565b634e487b7160e01b87526041600452602487fd5b015190503880620000f1565b90848a9416918b8052868c20928c5b88828210620003015750508411620002e7575b505050811b01875562000105565b015160001960f88460031b161c19169055388080620002d9565b8385015186558d97909501949384019301620002c6565b909150898052848a208780850160051c82019287861062000361575b918b91869594930160051c01915b82811062000352575050620000db565b8c81558594508b910162000342565b9250819262000334565b634e487b7160e01b8a52602260045260248afd5b90607f1690620000c6565b634e487b7160e01b600052604160045260246000fd5b600080fd5b60408051919082016001600160401b038111838210176200038a57604052565b51906001600160a01b0382168203620003a05756fe6080604052600436101561001257600080fd5b60003560e01c806301b3fab11461025757806301ffc9a71461025257806306fdde031461024d578063081812fc14610248578063095ea7b3146102435780630f4d14e91461023e5780631249c58b14610239578063150b7a02146102345780631b8d7cac1461022f57806323b872dd1461022a5780632440932f1461022557806336fa5e6e1461022057806342842e0e1461021b5780634ec028901461021657806357c8dbbf146102115780635882e1951461020c5780636352211e1461020757806370a08231146102025780638322fff2146101fd57806384437725146101f85780638736e13b146101f357806395d89b41146101ee578063a22cb465146101e9578063a72cefe2146101e4578063a7323f9d146101df578063b0facab3146101da578063b88d4fde146101d5578063bc197c81146101d0578063c20938e0146101cb578063c311d049146101c6578063c87b56dd146101c1578063e985e9c5146101bc578063ede41a90146101b7578063f23a6e61146101b2578063f63b9b38146101ad5763fcd3533c146101a857600080fd5b6117ea565b6117d3565b611779565b611711565b6116b9565b6114c4565b6114a8565b611480565b6113f1565b611316565b6111af565b611156565b611038565b610faf565b610ee4565b610e79565b610dec565b610dbd565b610d3b565b610d0b565b610c6a565b610bb0565b610b99565b610ab5565b61099a565b61094f565b610938565b610866565b610812565b6106d1565b61062c565b610562565b61052e565b610401565b6102cf565b610272565b6001600160a01b0381160361026d57565b600080fd5b3461026d57604036600319011261026d5760043561028f8161025c565b60018060a01b0316600052600860205260406000206024356000526020526020604060002054604051908152f35b6001600160e01b031981160361026d57565b3461026d57602036600319011261026d5760206004356102ee816102bd565b63ffffffff60e01b166301ffc9a760e01b811490811561032c575b811561031b575b506040519015158152f35b635b5e139f60e01b14905038610310565b6380ac58cd60e01b81149150610309565b600091031261026d57565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161037157604052565b610348565b604081019081106001600160401b0382111761037157604052565b90601f801991011681019081106001600160401b0382111761037157604052565b60005b8381106103c55750506000910152565b81810151838201526020016103b5565b604091602082526103f581518092816020860152602086860191016103b2565b601f01601f1916010190565b3461026d5760008060031936011261050857604051908080549060019180831c928082169283156104fe575b60209283861085146104ea5785885260208801949081156104c95750600114610471575b61046d8761046181890382610391565b604051918291826103d5565b0390f35b6000805294509192917f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8386106104b857505050910190506104618261046d3880610451565b80548587015294820194810161049c565b60ff191685525050505090151560051b0190506104618261046d3880610451565b634e487b7160e01b82526022600452602482fd5b93607f169361042d565b80fd5b6000526004602052604060002090565b6001600160a01b03909116815260200190565b3461026d57602036600319011261026d576004356000526004602052602060018060a01b0360406000205416604051908152f35b3461026d57604036600319011261026d5760043561057f8161025c565b60243560008181526002602052604081205490926001600160a01b0391821691903383148015610608575b6105b390611871565b6105df816105c08661050b565b80546001600160a01b0319166001600160a01b03909216919091179055565b16907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258480a480f35b5082855260056020526105b360ff61062333604089206116a2565b541690506105aa565b602036600319011261026d576004356106448161239d565b60008181527ea206b70d87cacff7a19f3d98e0957b781c25fb4ae954252c87bcf40626174260205260408120805491927f29e8ab3a5ee1054a4bad5627fd68b00e7cb87684fe0d98f8625af41385ff5afe9260609273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee916106ba903490611bba565b90556040519182526020820152346040820152a180f35b3461026d576000806003193601126105085760016006540190816006556106f93315156118ae565b818152600260205260408120546001600160a01b03166107625761071c33611654565b8054600101905561073b336105c0846000526002602052604060002090565b61046d8260405193849333906000805160206124078339815191528180a482526020820190565b60405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606490fd5b9181601f8401121561026d578235916001600160401b03831161026d576020838186019501011161026d57565b90608060031983011261026d576004356107de8161025c565b916024356107eb8161025c565b9160443591606435906001600160401b03821161026d5761080e91600401610798565b9091565b3461026d57610820366107c5565b50505050506020604051630a85bd0160e11b8152f35b9181601f8401121561026d578235916001600160401b03831161026d576020808501948460051b01011161026d57565b3461026d5760c036600319011261026d576001600160401b03600460243582811161026d576108989036908301610836565b60449291923584811161026d576108b29036908401610836565b60649291923586811161026d576108cc9036908601610836565b9160843588811161026d576108e49036908801610836565b95909460a435998a1161026d5761090161090a9a36908a01610836565b99909835611ad8565b005b606090600319011261026d576004356109248161025c565b906024356109318161025c565b9060443590565b3461026d5761090a6109493661090c565b916118ee565b3461026d57604036600319011261026d5760243561096c8161025c565b60018060a01b0316600052600960205260406000206004356000526020526020604060002054604051908152f35b3461026d57606036600319011261026d576004356024356109ba8161025c565b6044356001600160401b03811161026d576109d9903690600401610836565b926109e38161239d565b604051633af32abf60e01b815260208180610a01876004830161051b565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610ab057600091610a82575b5015610a705760005b848110610a5057005b80610a6a610a616001938887611aa8565b35868533611cae565b01610a47565b6040516378d31c7360e11b8152600490fd5b610aa3915060203d8111610aa9575b610a9b8183610391565b810190611ba5565b38610a3e565b503d610a91565b611a5d565b3461026d57610ac33661090c565b91610acf8383836118ee565b813b15918215610ae3575b61090a83611a69565b602091925060a460018060a01b03946000604051968794859382630a85bd0160e11b998a8752336004880152166024860152604485015260806064850152826084850152165af18015610ab05761090a92600091610b4f575b506001600160e01b031916143880610ada565b610b70915060203d8111610b76575b610b688183610391565b810190611a45565b38610b3c565b503d610b5e565b606090600319011261026d57600435906024356109318161025c565b3461026d5761090a610baa36610b7d565b916120b2565b3461026d57608036600319011261026d57600435602435610bd08161025c565b610bd98261239d565b604051633af32abf60e01b815260208180610bf7856004830161051b565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610ab057600091610c4c575b5015610a705761090a91606435916044359133611e34565b610c64915060203d8111610aa957610a9b8183610391565b38610c34565b3461026d57610c7836610b7d565b90610c828361239d565b604051633af32abf60e01b815260208180610ca0856004830161051b565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610ab057600091610ced575b5015610a705761090a9233611cae565b610d05915060203d8111610aa957610a9b8183610391565b38610cdd565b3461026d57602036600319011261026d576020610d2960043561184b565b6040516001600160a01b039091168152f35b3461026d57602036600319011261026d57600435610d588161025c565b6001600160a01b03168015610d8957600052600360205261046d604060002054604051918291829190602083019252565b60405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606490fd5b3461026d57600036600319011261026d57602060405173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8152f35b3461026d5760206040610dfe36610b7d565b6001600160a01b039091166000908152600a85528381209181529084528281209181529083522054604051908152f35b90606060031983011261026d57600435916001600160401b039160243583811161026d5782610e5f91600401610836565b9390939260443591821161026d5761080e91600401610836565b3461026d57610e8736610e2e565b91929390828403610ed25760005b848110610e9e57005b80610ecc610eaf600193888a611aa8565b35610eb98161025c565b610ec4838887611aa8565b3590866120b2565b01610e95565b604051637736a16d60e01b8152600490fd5b3461026d57600080600319360112610508576040519080600190815480831c92808216928315610f9b575b60209283861085146104ea5785885260208801949081156104c95750600114610f425761046d8761046181890382610391565b600160005294509192917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b838610610f8a57505050910190506104618261046d3880610451565b805485870152948201948101610f6e565b93607f1693610f0f565b8015150361026d57565b3461026d57604036600319011261026d57600435610fcc8161025c565b60243590610fd982610fa5565b336000526005602052610ff08160406000206116a2565b9115159160ff1981541660ff841617905560405191825260018060a01b0316907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b3461026d57608036600319011261026d576024356004356110588261025c565b6001600160401b039160443583811161026d57611079903690600401610836565b92909360643590811161026d57611094903690600401610836565b9261109e8361239d565b604051633af32abf60e01b8152602081806110bc856004830161051b565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610ab057600091611138575b5015610a705760005b85811061110b57005b8061113261111c600193898b611aa8565b35611128838988611aa8565b3590858833611e34565b01611102565b611150915060203d8111610aa957610a9b8183610391565b386110f9565b3461026d5761116436610e2e565b91929390828403610ed25760005b84811061117b57005b806111a961118c600193888a611aa8565b356111968161025c565b6111a1838887611aa8565b359086611eee565b01611172565b3461026d576111bd36610b7d565b916111c78161239d565b6001600160a01b038281169073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee82146113045760206040518092633af32abf60e01b8252818061120e896004830161051b565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa908115610ab0576000916112e6575b50156112d4578361127c7f29e8ab3a5ee1054a4bad5627fd68b00e7cb87684fe0d98f8625af41385ff5afe956112cf9330903390611d55565b6001600160a01b03841660009081526009602052604090206112b69084600052602052604060002090565b90600052602052604060002090565b6112c1828254611bba565b905560405193849384611bdd565b0390a1005b60405163a212b5d360e01b8152600490fd5b6112fe915060203d8111610aa957610a9b8183610391565b38611243565b604051630130141160e61b8152600490fd5b3461026d57611324366107c5565b939192906113338483856118ee565b813b15938415611347575b61090a85611a69565b602093945090600086939260a460018060a01b0391604051998a978896879386630a85bd0160e11b9d8e8752336004880152166024860152604485015260806064850152816084850152848401378181018301859052601f01601f19168101030193165af18015610ab05761090a926000916113d3575b506001600160e01b031916143880808061133e565b6113eb915060203d8111610b7657610b688183610391565b386113be565b3461026d5760a036600319011261026d5761140d60043561025c565b61141860243561025c565b6001600160401b0360443581811161026d57611438903690600401610836565b505060643581811161026d57611452903690600401610836565b505060843590811161026d5761146c903690600401610798565b505060405163bc197c8160e01b8152602090f35b3461026d57604036600319011261026d5761090a6024356114a08161025c565b600435611fbe565b3461026d57602036600319011261026d5761090a60043561228c565b3461026d57602036600319011261026d576004356040516114e481610376565b601e81527f68747470733a2f2f676f6e64692e78797a2f757365725f7661756c74732f000060208201526000918072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8181811015611646575b506904ee2d6d415b85acef8160201b905080831015611637575b50662386f26fc1000080831015611628575b506305f5e10080831015611619575b506127108083101561160a575b5060648210156115fa575b600a809210156115f0575b6001908160216115a2828801611c5a565b96870101905b6115ba575b61046d6104618787611c19565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353049182156115eb579190826115a8565b6115ad565b9260010192611591565b9290606460029104910192611586565b6004919492049101923861157b565b6008919492049101923861156e565b6010919492049101923861155f565b6020919492049101923861154d565b604095500491503880611533565b6001600160a01b0316600090815260036020526040902090565b6001600160a01b0316600090815260086020526040902090565b6001600160a01b03166000908152600a6020526040902090565b9060018060a01b0316600052602052604060002090565b3461026d57604036600319011261026d57602060ff6117056004356116dd8161025c565b602435906116ea8261025c565b6001600160a01b0316600090815260058552604090206116a2565b54166040519015158152f35b3461026d57604036600319011261026d576004356024356001600160401b03811161026d57611744903690600401610836565b919060005b83811061175257005b806117736117636001938786611aa8565b3561176d8161025c565b85611fbe565b01611749565b3461026d5760a036600319011261026d5761179560043561025c565b6117a060243561025c565b6084356001600160401b03811161026d576117bf903690600401610798565b505060405163f23a6e6160e01b8152602090f35b3461026d5761090a6117e436610b7d565b91611eee565b3461026d57604036600319011261026d5761090a60243561180a8161025c565b60043561217a565b1561181957565b60405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606490fd5b6000908152600260205260409020546001600160a01b03169061186f821515611812565b565b1561187857565b60405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606490fd5b156118b557565b60405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606490fd5b9060018060a01b038061190b856000526002602052604060002090565b541691818416928303611a135761194c6119789282169461192d8615156118ae565b84331480156119de575b80156119a9575b61194790611871565b611654565b805460001901905561195d81611654565b805460010190556105c0856000526002602052604060002090565b6119946119848461050b565b80546001600160a01b0319169055565b600080516020612407833981519152600080a4565b506119476119d56119c96119bc8a61050b565b546001600160a01b031690565b6001600160a01b031690565b3314905061193e565b50611a0e611a0733611a028460018060a01b03166000526005602052604060002090565b6116a2565b5460ff1690565b611937565b60405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606490fd5b9081602091031261026d5751611a5a816102bd565b90565b6040513d6000823e3d90fd5b15611a7057565b60405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606490fd5b9190811015611ab85760051b0190565b634e487b7160e01b600052603260045260246000fd5b35611a5a8161025c565b999698979593909291611aeb338c61217a565b818103610ed25760005b818110611b7857505050505060005b818110611b585750505060005b818110611b2657505050505061186f9061228c565b80611b52611b3f611b3a600194868a611aa8565b611ace565b611b4a838789611aa8565b3590896120b2565b01611b11565b80611b72611b6c611b3a6001948688611aa8565b8a611fbe565b01611b04565b80611b9f8d611b8d611b3a600195878b611aa8565b611b9884888a611aa8565b3591611eee565b01611af5565b9081602091031261026d5751611a5a81610fa5565b91908201809211611bc757565b634e487b7160e01b600052601160045260246000fd5b9081526001600160a01b039091166020820152604081019190915260600190565b6001600160401b03811161037157601f01601f191660200190565b602061186f919392936040519481611c3a87935180928680870191016103b2565b8201611c4e825180938680850191016103b2565b01038085520183610391565b90611c6482611bfe565b611c716040519182610391565b8281528092611c82601f1991611bfe565b0190602036910137565b6001600160a01b03918216815291166020820152604081019190915260600190565b926001600160a01b038316803b1561026d5781600091611ce796836040518099819582946323b872dd60e01b8452309060048501611c8c565b03925af1908115610ab0577f4e92356bc3e014711be5e60ba880885e904c8baded8441e59854b2cf1f89f8b094611d4192611d46575b50611d278461166e565b816000526020528260406000205560405193849384611bdd565b0390a1565b611d4f9061035e565b38611d1d565b9160008093602095606494604051946323b872dd60e01b865260018060a01b03809216600487015216602485015260448401525af13d15601f3d1160016000511416171615611da057565b60405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606490fd5b929060c0949260018060a01b0380921685521660208401526040830152606082015260a06080820152600060a08201520190565b909493926060926080830196835260018060a01b0316602083015260408201520152565b919290916001600160a01b03841691823b1561026d5780869260405194858092637921219560e11b825281611e7460009c8d978894309060048601611ddc565b03925af18015610ab0577f591c45c6cd9259632b4e9a5cfa0dd0a5ad5dd72470c757c25c184309f44d9da396611d4194604092611edf575b50611eb687611688565b83825260205281812086825260205220611ed1838254611bba565b905560405194859485611e10565b611ee89061035e565b38611eac565b611ef7816123cd565b80611f05846112a78561166e565b5403611fac576001600160a01b03821692833b1561026d57600060405180956323b872dd60e01b8252818381611f4087333060048501611c8c565b03925af1908115610ab0577f20289891ea20aca7d12a5b330123469398894b00725c9e8564c7981114abdc0f94611d4192611f93575b506000611f86826112a78761166e565b5560405193849384611bdd565b80611fa0611fa69261035e565b8061033d565b38611f76565b6040516349e11b0360e01b8152600490fd5b9190611fc9836123cd565b6001600160a01b038116600081815260096020908152604080832087845282528083205490969390929083156120a8578160448285938352600984528a83208884528452828b812055828b519163a9059cbb60e01b83523360048401528860248401525af19051600114601f3d11163d151716156120735750611d41907f893699b7a610f8ef1d97bd0dcc4cc672bc257f1b1ddd063cf2e218153eaf0a8a94955193849384611bdd565b60649086519062461bcd60e51b82526004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152fd5b5050505050509050565b6120bb816123cd565b6120cc816112a7856112a786611688565b549283156121745760006120e7836112a7846112a788611688565b556001600160a01b03831693843b1561026d5760006040518096637921219560e11b825281838161211e8789333060048601611ddc565b03925af1918215610ab0577fabe6b5b858802d850f86c44c35989762d5c479134363a0d7a57c5ef51789ec3095611d4193612161575b5060405194859485611e10565b80611fa061216e9261035e565b38612154565b50505050565b91906001600160a01b038061218e8561184b565b1633141580612260575b8061224b575b612232578361186f93946105c09260009082825260026020526040822054166121c8811515611812565b80825260036020526040822060001981540190556121f0836000526002602052604060002090565b80546001600160a01b031990811690915561220a8461050b565b9081541690556000805160206124078339815191528280a46000526007602052604060002090565b604051633f7d787960e11b815260048101859052602490fd5b5033816122578661050b565b5416141561219e565b508061226b8561184b565b16600052600560205260ff6122843360406000206116a2565b541615612198565b90612296826123cd565b60008281527ea206b70d87cacff7a19f3d98e0957b781c25fb4ae954252c87bcf4062617426020526040808220549093909173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8315612395578152600960205284812082825260205280858120558080808086335af1903d1561238f573d9061231282611bfe565b9161231f88519384610391565b825260203d92013e5b1561237e57925192835273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60208401526040830152907f893699b7a610f8ef1d97bd0dcc4cc672bc257f1b1ddd063cf2e218153eaf0a8a908060608101611d41565b835163439e708560e11b8152600490fd5b50612328565b505050509050565b6000908152600260205260409020546001600160a01b0316156123bc57565b63be7238f360e01b60005260046000fd5b6000818152600760205260409020546001600160a01b031633036123ee5750565b60249060405190633f7d787960e11b82526004820152fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212202bf1d4303a974a9c365b5d1e50143197a6e985423861903be649efb0c9359bcd64736f6c634300081500330000000000000000000000004150ded32a6d3bfecae76e7558af48019034492700000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d7398
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c806301b3fab11461025757806301ffc9a71461025257806306fdde031461024d578063081812fc14610248578063095ea7b3146102435780630f4d14e91461023e5780631249c58b14610239578063150b7a02146102345780631b8d7cac1461022f57806323b872dd1461022a5780632440932f1461022557806336fa5e6e1461022057806342842e0e1461021b5780634ec028901461021657806357c8dbbf146102115780635882e1951461020c5780636352211e1461020757806370a08231146102025780638322fff2146101fd57806384437725146101f85780638736e13b146101f357806395d89b41146101ee578063a22cb465146101e9578063a72cefe2146101e4578063a7323f9d146101df578063b0facab3146101da578063b88d4fde146101d5578063bc197c81146101d0578063c20938e0146101cb578063c311d049146101c6578063c87b56dd146101c1578063e985e9c5146101bc578063ede41a90146101b7578063f23a6e61146101b2578063f63b9b38146101ad5763fcd3533c146101a857600080fd5b6117ea565b6117d3565b611779565b611711565b6116b9565b6114c4565b6114a8565b611480565b6113f1565b611316565b6111af565b611156565b611038565b610faf565b610ee4565b610e79565b610dec565b610dbd565b610d3b565b610d0b565b610c6a565b610bb0565b610b99565b610ab5565b61099a565b61094f565b610938565b610866565b610812565b6106d1565b61062c565b610562565b61052e565b610401565b6102cf565b610272565b6001600160a01b0381160361026d57565b600080fd5b3461026d57604036600319011261026d5760043561028f8161025c565b60018060a01b0316600052600860205260406000206024356000526020526020604060002054604051908152f35b6001600160e01b031981160361026d57565b3461026d57602036600319011261026d5760206004356102ee816102bd565b63ffffffff60e01b166301ffc9a760e01b811490811561032c575b811561031b575b506040519015158152f35b635b5e139f60e01b14905038610310565b6380ac58cd60e01b81149150610309565b600091031261026d57565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161037157604052565b610348565b604081019081106001600160401b0382111761037157604052565b90601f801991011681019081106001600160401b0382111761037157604052565b60005b8381106103c55750506000910152565b81810151838201526020016103b5565b604091602082526103f581518092816020860152602086860191016103b2565b601f01601f1916010190565b3461026d5760008060031936011261050857604051908080549060019180831c928082169283156104fe575b60209283861085146104ea5785885260208801949081156104c95750600114610471575b61046d8761046181890382610391565b604051918291826103d5565b0390f35b6000805294509192917f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8386106104b857505050910190506104618261046d3880610451565b80548587015294820194810161049c565b60ff191685525050505090151560051b0190506104618261046d3880610451565b634e487b7160e01b82526022600452602482fd5b93607f169361042d565b80fd5b6000526004602052604060002090565b6001600160a01b03909116815260200190565b3461026d57602036600319011261026d576004356000526004602052602060018060a01b0360406000205416604051908152f35b3461026d57604036600319011261026d5760043561057f8161025c565b60243560008181526002602052604081205490926001600160a01b0391821691903383148015610608575b6105b390611871565b6105df816105c08661050b565b80546001600160a01b0319166001600160a01b03909216919091179055565b16907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258480a480f35b5082855260056020526105b360ff61062333604089206116a2565b541690506105aa565b602036600319011261026d576004356106448161239d565b60008181527ea206b70d87cacff7a19f3d98e0957b781c25fb4ae954252c87bcf40626174260205260408120805491927f29e8ab3a5ee1054a4bad5627fd68b00e7cb87684fe0d98f8625af41385ff5afe9260609273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee916106ba903490611bba565b90556040519182526020820152346040820152a180f35b3461026d576000806003193601126105085760016006540190816006556106f93315156118ae565b818152600260205260408120546001600160a01b03166107625761071c33611654565b8054600101905561073b336105c0846000526002602052604060002090565b61046d8260405193849333906000805160206124078339815191528180a482526020820190565b60405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606490fd5b9181601f8401121561026d578235916001600160401b03831161026d576020838186019501011161026d57565b90608060031983011261026d576004356107de8161025c565b916024356107eb8161025c565b9160443591606435906001600160401b03821161026d5761080e91600401610798565b9091565b3461026d57610820366107c5565b50505050506020604051630a85bd0160e11b8152f35b9181601f8401121561026d578235916001600160401b03831161026d576020808501948460051b01011161026d57565b3461026d5760c036600319011261026d576001600160401b03600460243582811161026d576108989036908301610836565b60449291923584811161026d576108b29036908401610836565b60649291923586811161026d576108cc9036908601610836565b9160843588811161026d576108e49036908801610836565b95909460a435998a1161026d5761090161090a9a36908a01610836565b99909835611ad8565b005b606090600319011261026d576004356109248161025c565b906024356109318161025c565b9060443590565b3461026d5761090a6109493661090c565b916118ee565b3461026d57604036600319011261026d5760243561096c8161025c565b60018060a01b0316600052600960205260406000206004356000526020526020604060002054604051908152f35b3461026d57606036600319011261026d576004356024356109ba8161025c565b6044356001600160401b03811161026d576109d9903690600401610836565b926109e38161239d565b604051633af32abf60e01b815260208180610a01876004830161051b565b03817f00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d73986001600160a01b03165afa908115610ab057600091610a82575b5015610a705760005b848110610a5057005b80610a6a610a616001938887611aa8565b35868533611cae565b01610a47565b6040516378d31c7360e11b8152600490fd5b610aa3915060203d8111610aa9575b610a9b8183610391565b810190611ba5565b38610a3e565b503d610a91565b611a5d565b3461026d57610ac33661090c565b91610acf8383836118ee565b813b15918215610ae3575b61090a83611a69565b602091925060a460018060a01b03946000604051968794859382630a85bd0160e11b998a8752336004880152166024860152604485015260806064850152826084850152165af18015610ab05761090a92600091610b4f575b506001600160e01b031916143880610ada565b610b70915060203d8111610b76575b610b688183610391565b810190611a45565b38610b3c565b503d610b5e565b606090600319011261026d57600435906024356109318161025c565b3461026d5761090a610baa36610b7d565b916120b2565b3461026d57608036600319011261026d57600435602435610bd08161025c565b610bd98261239d565b604051633af32abf60e01b815260208180610bf7856004830161051b565b03817f00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d73986001600160a01b03165afa908115610ab057600091610c4c575b5015610a705761090a91606435916044359133611e34565b610c64915060203d8111610aa957610a9b8183610391565b38610c34565b3461026d57610c7836610b7d565b90610c828361239d565b604051633af32abf60e01b815260208180610ca0856004830161051b565b03817f00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d73986001600160a01b03165afa908115610ab057600091610ced575b5015610a705761090a9233611cae565b610d05915060203d8111610aa957610a9b8183610391565b38610cdd565b3461026d57602036600319011261026d576020610d2960043561184b565b6040516001600160a01b039091168152f35b3461026d57602036600319011261026d57600435610d588161025c565b6001600160a01b03168015610d8957600052600360205261046d604060002054604051918291829190602083019252565b60405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606490fd5b3461026d57600036600319011261026d57602060405173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8152f35b3461026d5760206040610dfe36610b7d565b6001600160a01b039091166000908152600a85528381209181529084528281209181529083522054604051908152f35b90606060031983011261026d57600435916001600160401b039160243583811161026d5782610e5f91600401610836565b9390939260443591821161026d5761080e91600401610836565b3461026d57610e8736610e2e565b91929390828403610ed25760005b848110610e9e57005b80610ecc610eaf600193888a611aa8565b35610eb98161025c565b610ec4838887611aa8565b3590866120b2565b01610e95565b604051637736a16d60e01b8152600490fd5b3461026d57600080600319360112610508576040519080600190815480831c92808216928315610f9b575b60209283861085146104ea5785885260208801949081156104c95750600114610f425761046d8761046181890382610391565b600160005294509192917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b838610610f8a57505050910190506104618261046d3880610451565b805485870152948201948101610f6e565b93607f1693610f0f565b8015150361026d57565b3461026d57604036600319011261026d57600435610fcc8161025c565b60243590610fd982610fa5565b336000526005602052610ff08160406000206116a2565b9115159160ff1981541660ff841617905560405191825260018060a01b0316907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b3461026d57608036600319011261026d576024356004356110588261025c565b6001600160401b039160443583811161026d57611079903690600401610836565b92909360643590811161026d57611094903690600401610836565b9261109e8361239d565b604051633af32abf60e01b8152602081806110bc856004830161051b565b03817f00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d73986001600160a01b03165afa908115610ab057600091611138575b5015610a705760005b85811061110b57005b8061113261111c600193898b611aa8565b35611128838988611aa8565b3590858833611e34565b01611102565b611150915060203d8111610aa957610a9b8183610391565b386110f9565b3461026d5761116436610e2e565b91929390828403610ed25760005b84811061117b57005b806111a961118c600193888a611aa8565b356111968161025c565b6111a1838887611aa8565b359086611eee565b01611172565b3461026d576111bd36610b7d565b916111c78161239d565b6001600160a01b038281169073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee82146113045760206040518092633af32abf60e01b8252818061120e896004830161051b565b03917f0000000000000000000000004150ded32a6d3bfecae76e7558af480190344927165afa908115610ab0576000916112e6575b50156112d4578361127c7f29e8ab3a5ee1054a4bad5627fd68b00e7cb87684fe0d98f8625af41385ff5afe956112cf9330903390611d55565b6001600160a01b03841660009081526009602052604090206112b69084600052602052604060002090565b90600052602052604060002090565b6112c1828254611bba565b905560405193849384611bdd565b0390a1005b60405163a212b5d360e01b8152600490fd5b6112fe915060203d8111610aa957610a9b8183610391565b38611243565b604051630130141160e61b8152600490fd5b3461026d57611324366107c5565b939192906113338483856118ee565b813b15938415611347575b61090a85611a69565b602093945090600086939260a460018060a01b0391604051998a978896879386630a85bd0160e11b9d8e8752336004880152166024860152604485015260806064850152816084850152848401378181018301859052601f01601f19168101030193165af18015610ab05761090a926000916113d3575b506001600160e01b031916143880808061133e565b6113eb915060203d8111610b7657610b688183610391565b386113be565b3461026d5760a036600319011261026d5761140d60043561025c565b61141860243561025c565b6001600160401b0360443581811161026d57611438903690600401610836565b505060643581811161026d57611452903690600401610836565b505060843590811161026d5761146c903690600401610798565b505060405163bc197c8160e01b8152602090f35b3461026d57604036600319011261026d5761090a6024356114a08161025c565b600435611fbe565b3461026d57602036600319011261026d5761090a60043561228c565b3461026d57602036600319011261026d576004356040516114e481610376565b601e81527f68747470733a2f2f676f6e64692e78797a2f757365725f7661756c74732f000060208201526000918072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8181811015611646575b506904ee2d6d415b85acef8160201b905080831015611637575b50662386f26fc1000080831015611628575b506305f5e10080831015611619575b506127108083101561160a575b5060648210156115fa575b600a809210156115f0575b6001908160216115a2828801611c5a565b96870101905b6115ba575b61046d6104618787611c19565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353049182156115eb579190826115a8565b6115ad565b9260010192611591565b9290606460029104910192611586565b6004919492049101923861157b565b6008919492049101923861156e565b6010919492049101923861155f565b6020919492049101923861154d565b604095500491503880611533565b6001600160a01b0316600090815260036020526040902090565b6001600160a01b0316600090815260086020526040902090565b6001600160a01b03166000908152600a6020526040902090565b9060018060a01b0316600052602052604060002090565b3461026d57604036600319011261026d57602060ff6117056004356116dd8161025c565b602435906116ea8261025c565b6001600160a01b0316600090815260058552604090206116a2565b54166040519015158152f35b3461026d57604036600319011261026d576004356024356001600160401b03811161026d57611744903690600401610836565b919060005b83811061175257005b806117736117636001938786611aa8565b3561176d8161025c565b85611fbe565b01611749565b3461026d5760a036600319011261026d5761179560043561025c565b6117a060243561025c565b6084356001600160401b03811161026d576117bf903690600401610798565b505060405163f23a6e6160e01b8152602090f35b3461026d5761090a6117e436610b7d565b91611eee565b3461026d57604036600319011261026d5761090a60243561180a8161025c565b60043561217a565b1561181957565b60405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606490fd5b6000908152600260205260409020546001600160a01b03169061186f821515611812565b565b1561187857565b60405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606490fd5b156118b557565b60405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606490fd5b9060018060a01b038061190b856000526002602052604060002090565b541691818416928303611a135761194c6119789282169461192d8615156118ae565b84331480156119de575b80156119a9575b61194790611871565b611654565b805460001901905561195d81611654565b805460010190556105c0856000526002602052604060002090565b6119946119848461050b565b80546001600160a01b0319169055565b600080516020612407833981519152600080a4565b506119476119d56119c96119bc8a61050b565b546001600160a01b031690565b6001600160a01b031690565b3314905061193e565b50611a0e611a0733611a028460018060a01b03166000526005602052604060002090565b6116a2565b5460ff1690565b611937565b60405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606490fd5b9081602091031261026d5751611a5a816102bd565b90565b6040513d6000823e3d90fd5b15611a7057565b60405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606490fd5b9190811015611ab85760051b0190565b634e487b7160e01b600052603260045260246000fd5b35611a5a8161025c565b999698979593909291611aeb338c61217a565b818103610ed25760005b818110611b7857505050505060005b818110611b585750505060005b818110611b2657505050505061186f9061228c565b80611b52611b3f611b3a600194868a611aa8565b611ace565b611b4a838789611aa8565b3590896120b2565b01611b11565b80611b72611b6c611b3a6001948688611aa8565b8a611fbe565b01611b04565b80611b9f8d611b8d611b3a600195878b611aa8565b611b9884888a611aa8565b3591611eee565b01611af5565b9081602091031261026d5751611a5a81610fa5565b91908201809211611bc757565b634e487b7160e01b600052601160045260246000fd5b9081526001600160a01b039091166020820152604081019190915260600190565b6001600160401b03811161037157601f01601f191660200190565b602061186f919392936040519481611c3a87935180928680870191016103b2565b8201611c4e825180938680850191016103b2565b01038085520183610391565b90611c6482611bfe565b611c716040519182610391565b8281528092611c82601f1991611bfe565b0190602036910137565b6001600160a01b03918216815291166020820152604081019190915260600190565b926001600160a01b038316803b1561026d5781600091611ce796836040518099819582946323b872dd60e01b8452309060048501611c8c565b03925af1908115610ab0577f4e92356bc3e014711be5e60ba880885e904c8baded8441e59854b2cf1f89f8b094611d4192611d46575b50611d278461166e565b816000526020528260406000205560405193849384611bdd565b0390a1565b611d4f9061035e565b38611d1d565b9160008093602095606494604051946323b872dd60e01b865260018060a01b03809216600487015216602485015260448401525af13d15601f3d1160016000511416171615611da057565b60405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606490fd5b929060c0949260018060a01b0380921685521660208401526040830152606082015260a06080820152600060a08201520190565b909493926060926080830196835260018060a01b0316602083015260408201520152565b919290916001600160a01b03841691823b1561026d5780869260405194858092637921219560e11b825281611e7460009c8d978894309060048601611ddc565b03925af18015610ab0577f591c45c6cd9259632b4e9a5cfa0dd0a5ad5dd72470c757c25c184309f44d9da396611d4194604092611edf575b50611eb687611688565b83825260205281812086825260205220611ed1838254611bba565b905560405194859485611e10565b611ee89061035e565b38611eac565b611ef7816123cd565b80611f05846112a78561166e565b5403611fac576001600160a01b03821692833b1561026d57600060405180956323b872dd60e01b8252818381611f4087333060048501611c8c565b03925af1908115610ab0577f20289891ea20aca7d12a5b330123469398894b00725c9e8564c7981114abdc0f94611d4192611f93575b506000611f86826112a78761166e565b5560405193849384611bdd565b80611fa0611fa69261035e565b8061033d565b38611f76565b6040516349e11b0360e01b8152600490fd5b9190611fc9836123cd565b6001600160a01b038116600081815260096020908152604080832087845282528083205490969390929083156120a8578160448285938352600984528a83208884528452828b812055828b519163a9059cbb60e01b83523360048401528860248401525af19051600114601f3d11163d151716156120735750611d41907f893699b7a610f8ef1d97bd0dcc4cc672bc257f1b1ddd063cf2e218153eaf0a8a94955193849384611bdd565b60649086519062461bcd60e51b82526004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152fd5b5050505050509050565b6120bb816123cd565b6120cc816112a7856112a786611688565b549283156121745760006120e7836112a7846112a788611688565b556001600160a01b03831693843b1561026d5760006040518096637921219560e11b825281838161211e8789333060048601611ddc565b03925af1918215610ab0577fabe6b5b858802d850f86c44c35989762d5c479134363a0d7a57c5ef51789ec3095611d4193612161575b5060405194859485611e10565b80611fa061216e9261035e565b38612154565b50505050565b91906001600160a01b038061218e8561184b565b1633141580612260575b8061224b575b612232578361186f93946105c09260009082825260026020526040822054166121c8811515611812565b80825260036020526040822060001981540190556121f0836000526002602052604060002090565b80546001600160a01b031990811690915561220a8461050b565b9081541690556000805160206124078339815191528280a46000526007602052604060002090565b604051633f7d787960e11b815260048101859052602490fd5b5033816122578661050b565b5416141561219e565b508061226b8561184b565b16600052600560205260ff6122843360406000206116a2565b541615612198565b90612296826123cd565b60008281527ea206b70d87cacff7a19f3d98e0957b781c25fb4ae954252c87bcf4062617426020526040808220549093909173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8315612395578152600960205284812082825260205280858120558080808086335af1903d1561238f573d9061231282611bfe565b9161231f88519384610391565b825260203d92013e5b1561237e57925192835273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60208401526040830152907f893699b7a610f8ef1d97bd0dcc4cc672bc257f1b1ddd063cf2e218153eaf0a8a908060608101611d41565b835163439e708560e11b8152600490fd5b50612328565b505050509050565b6000908152600260205260409020546001600160a01b0316156123bc57565b63be7238f360e01b60005260046000fd5b6000818152600760205260409020546001600160a01b031633036123ee5750565b60249060405190633f7d787960e11b82526004820152fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212202bf1d4303a974a9c365b5d1e50143197a6e985423861903be649efb0c9359bcd64736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004150ded32a6d3bfecae76e7558af48019034492700000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d7398
-----Decoded View---------------
Arg [0] : currencyManager (address): 0x4150deD32A6D3bfecAE76e7558Af480190344927
Arg [1] : collectionManager (address): 0x52Ac424eF7B283aA5bADB8c6254832E3280d7398
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004150ded32a6d3bfecae76e7558af480190344927
Arg [1] : 00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d7398
Deployed Bytecode Sourcemap
658:14361:15:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;;:::o;:::-;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;658:14361:15;4891:13;658:14361;;;-1:-1:-1;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;-1:-1:-1;658:14361:15;;;;;;;;;-1:-1:-1;;;;;;658:14361:15;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;:::i;:::-;;;;;;;;4825:25:8;;:100;;;;;658:14361:15;4825:175:8;;;;658:14361:15;;;;;;;;;;4825:175:8;-1:-1:-1;;;4975:25:8;;-1:-1:-1;4825:175:8;;;:100;-1:-1:-1;;;4900:25:8;;;-1:-1:-1;4825:100:8;;658:14361:15;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;:::o;:::-;;:::i;:::-;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;:::o;:::-;;;;;;;;-1:-1:-1;;658:14361:15;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;658:14361:15;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;658:14361:15;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;-1:-1:-1;;;;658:14361:15;;;;;;;-1:-1:-1;658:14361:15;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;-1:-1:-1;658:14361:15;;;;;;;;;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;-1:-1:-1;658:14361:15;;;2540:8:8;658:14361:15;;;;;;-1:-1:-1;;;;;;;658:14361:15;;;;;2571:10:8;:19;;:58;;;;658:14361:15;2563:85:8;;;:::i;:::-;2659:25;:15;;;;:::i;:::-;658:14361:15;;-1:-1:-1;;;;;;658:14361:15;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;2659:25:8;658:14361:15;2700:28:8;;;;;658:14361:15;;2571:58:8;658:14361:15;;;;2594:16:8;658:14361:15;;2563:85:8;658:14361:15;2594:35:8;2571:10;658:14361:15;;;2594:35:8;:::i;:::-;658:14361:15;;2571:58:8;;;;658:14361:15;;;-1:-1:-1;;658:14361:15;;;;;;8036:8;;;:::i;:::-;-1:-1:-1;658:14361:15;;;;;;;;;;;-1:-1:-1;;8112:40:15;;658:14361;;956:42;;8056:40;;8087:9;;8056:40;:::i;:::-;658:14361;;;;;;;;;;;8087:9;658:14361;;;;8112:40;658:14361;;;;;;;;;;;;;;;;3288:9;658:14361;;;;3288:9;658:14361;5309:46:8;3323:10:15;5317:16:8;;5309:46;:::i;:::-;658:14361:15;;;5374:8:8;658:14361:15;;;;;;-1:-1:-1;;;;;658:14361:15;;;5509:14:8;3323:10:15;5509:14:8;:::i;:::-;658:14361:15;;;;;;5546:17:8;3323:10:15;5546:12:8;;658:14361:15;;5374:8:8;658:14361:15;;;;;;;5546:17:8;658:14361:15;;;;3323:10;;;;5579:28:8;-1:-1:-1;;;;;;;;;;;5579:28:8;;;658:14361:15;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;658:14361:15;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;7310:45:8;;;658:14361:15;;;;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;658:14361:15;5069:12;658:14361;;;-1:-1:-1;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;:::i;:::-;5934:8;;;;:::i;:::-;658:14361;;-1:-1:-1;;;5958:45:15;;658:14361;;;5958:45;;658:14361;5958:45;;;:::i;:::-;;658:14361;5958:18;-1:-1:-1;;;;;658:14361:15;5958:45;;;;;;;-1:-1:-1;5958:45:15;;;658:14361;5957:46;;5953:115;;-1:-1:-1;6145:15:15;;;;;;658:14361;6130:13;6228:12;;;658:14361;6228:12;;;;:::i;:::-;658:14361;6193:10;;;6228:12;:::i;:::-;658:14361;6130:13;;5953:115;658:14361;;-1:-1:-1;;;6026:31:15;;658:14361;;6026:31;5958:45;;;;658:14361;5958:45;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;:::i;658:14361::-;;;;;;;:::i;:::-;3839:2:8;;;;;;:::i;:::-;3874:14;;:19;:170;;;;;658:14361:15;3853:233:8;;;:::i;3874:170::-;3913:66;658:14361:15;;;;;;;;;;3892:1:8;658:14361:15;;7310:45:8;;;;;;;;;3913:66;;;;3954:10;658:14361:15;3913:66:8;;658:14361:15;;;;;;;;;;;;;;;;;;;;;3913:66:8;;;;;;3853:233;3913:66;3892:1;3913:66;;;3874:170;-1:-1:-1;;;;;;;658:14361:15;3913:131:8;3874:170;;;;3913:66;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;658:14361:15;;;;;;;;;;;;;;;;;:::i;:::-;;;;9592:8;658:14361;;;:::i;:::-;9592:8;;:::i;658:14361::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;;:::i;:::-;6917:8;;;:::i;:::-;658:14361;;-1:-1:-1;;;6942:40:15;;658:14361;;;6942:40;;658:14361;6942:40;;;:::i;:::-;;658:14361;6942:18;-1:-1:-1;;;;;658:14361:15;6942:40;;;;;;;-1:-1:-1;6942:40:15;;;658:14361;6941:41;;6937:110;;7113:7;658:14361;;;;;;7073:10;;7113:7;:::i;6942:40::-;;;;658:14361;6942:40;;;;;;;;;:::i;:::-;;;;658:14361;;;;;;;:::i;:::-;5497:8;;;;:::i;:::-;658:14361;;-1:-1:-1;;;5522:45:15;;;658:14361;;5522:45;;658:14361;5522:45;;;:::i;:::-;;658:14361;5522:18;-1:-1:-1;;;;;658:14361:15;5522:45;;;;;;;-1:-1:-1;5522:45:15;;;658:14361;5521:46;;5517:115;;5691:8;5656:10;;5691:8;:::i;5522:45::-;;;;;;;;;;;;;;:::i;:::-;;;;658:14361;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;1572:19:8;;658:14361:15;;-1:-1:-1;658:14361:15;1626:10:8;658:14361:15;;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;956:42;658:14361;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;-1:-1:-1;658:14361:15;;;5269:14;658:14361;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;9800:34;;;;;;;9796:93;;9966:1;9969:20;;;;;;658:14361;9954:13;10034:10;10046:12;10034:10;658:14361;10034:10;;;;:::i;:::-;658:14361;;;;:::i;:::-;10046:12;;;;;:::i;:::-;658:14361;10046:12;;;:::i;:::-;658:14361;9954:13;;9796:93;658:14361;;-1:-1:-1;;;9857:21:15;;658:14361;;9857:21;658:14361;;;;;;;;;;;;;;;;;924:20:8;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;924:20:8;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;2843:10:8;-1:-1:-1;658:14361:15;2826:16:8;658:14361:15;;2826:38:8;658:14361:15;;-1:-1:-1;658:14361:15;2826:38:8;:::i;:::-;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;2843:10:8;2891:46;658:14361:15;2843:10:8;2891:46;;658:14361:15;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;7395:8;;;;:::i;:::-;658:14361;;-1:-1:-1;;;7419:45:15;;658:14361;;;7419:45;;658:14361;7419:45;;;:::i;:::-;;658:14361;7419:18;-1:-1:-1;;;;;658:14361:15;7419:45;;;;;;;-1:-1:-1;7419:45:15;;;658:14361;7418:46;;7414:115;;-1:-1:-1;7606:15:15;;;;;;658:14361;7591:13;7755:12;7785:11;7755:12;658:14361;7755:12;;;;:::i;:::-;658:14361;7785:11;;;;;:::i;:::-;658:14361;7672:10;;;;7785:11;:::i;:::-;658:14361;7591:13;;7419:45;;;;658:14361;7419:45;;;;;;;;;:::i;:::-;;;;658:14361;;;;;;;:::i;:::-;8577:39;;;;;;;8573:98;;8753:1;8756:20;;;;;;658:14361;8741:13;8820:15;8837:12;8820:15;658:14361;8820:15;;;;:::i;:::-;658:14361;;;;:::i;:::-;8837:12;;;;;:::i;:::-;658:14361;8837:12;;;:::i;:::-;658:14361;8741:13;;658:14361;;;;;;;:::i;:::-;6524:8;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;956:42;6548:13;;6544:69;;10985:38;658:14361;;;;;;;10985:38;;;;;;658:14361;10985:38;;;:::i;:::-;;:16;;658:14361;10985:38;;;;;;;-1:-1:-1;10985:38:15;;;658:14361;10984:39;;10980:106;;11146:4;11153:7;11228:41;11146:4;11228:41;11146:4;;6636:10;;11153:7;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;11172:12;658:14361;;;;;11172:30;;:20;658:14361;;;;;;;;;11172:20;658:14361;;;;;;;;;;11172:30;:41;658:14361;;;11172:41;:::i;:::-;658:14361;;;;11228:41;;;;;:::i;:::-;;;;658:14361;10980:106;658:14361;;-1:-1:-1;;;11046:29:15;;658:14361;;11046:29;10985:38;;;;;;;;;;;;;;:::i;:::-;;;;6544:69;658:14361;;-1:-1:-1;;;6584:18:15;;658:14361;;6584:18;658:14361;;;;;;;:::i;:::-;4270:2:8;;;;;;;;;:::i;:::-;4305:14;;:19;:172;;;;;658:14361:15;4284:235:8;;;:::i;4305:172::-;4344:68;658:14361:15;;;;4323:1:8;658:14361:15;;;;;;;;;;;;7310:45:8;;;;;;;;;;;4344:68;;;;4385:10;658:14361:15;4344:68:8;;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;4344:68:8;;;658:14361:15;4344:68:8;;;;;;4284:235;4344:68;4323:1;4344:68;;;4305:172;-1:-1:-1;;;;;;;658:14361:15;4344:133:8;4305:172;;;;;;4344:68;;;;;;;;;;;;;;:::i;:::-;;;;658:14361:15;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;:::i;:::-;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;658:14361:15;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;9064:6;658:14361;;;;;:::i;:::-;;;9064:6;:::i;658:14361::-;;;;;;-1:-1:-1;;658:14361:15;;;;10243:8;658:14361;;10243:8;:::i;658:14361::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;10429:26:15;-1:-1:-1;;;10429:26:15;24801:17:2;;;;24797:103;;658:14361:15;-1:-1:-1;;;;24926:8:2;-1:-1:-1;24917:17:2;;;;24913:103;;658:14361:15;25042:8:2;;25033:17;;;;25029:103;;658:14361:15;25158:7:2;;25149:16;;;;25145:100;;658:14361:15;25271:7:2;;25262:16;;;;25258:100;;658:14361:15;25375:16:2;25384:7;25375:16;;;25371:100;;658:14361:15;25497:7:2;25488:16;;;;25484:66;;658:14361:15;779:1:1;658:14361:15;;921:76:1;817:18;658:14361:15;;;817:18:1;:::i;:::-;849:11;921:76;;;1010:282;779:1;;;1010:282;658:14361:15;10404:52;;;;:::i;1010:282:1:-;-1:-1:-1;;658:14361:15;;;;-1:-1:-1;;;1115:95:1;;;;658:14361:15;1115:95:1;658:14361:15;1227:11:1;;1260:10;1256:21;;1010:282;;;;;1256:21;1272:5;;25484:66:2;658:14361:15;25534:1:2;658:14361:15;25484:66:2;;;25371:100;658:14361:15;;25384:7:2;25455:1;658:14361:15;;;;25371:100:2;;;25258;658:14361:15;;;;;;;25258:100:2;;;;25145;25229:1;658:14361:15;;;;;;25145:100:2;;;;25029:103;25115:2;658:14361:15;;;;;;25029:103:2;;;;24913;658:14361:15;;;;;;;24913:103:2;;;;24797;658:14361:15;;-1:-1:-1;658:14361:15;;-1:-1:-1;24797:103:2;;;;658:14361:15;-1:-1:-1;;;;;658:14361:15;;;;;5509:10:8;658:14361:15;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;10706:13;658:14361;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;11623:14;658:14361;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;1897:68:8;658:14361:15;;;;;:::i;:::-;;;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;-1:-1:-1;658:14361:15;;;1897:68:8;658:14361:15;;;;;1897:68:8;:::i;:::-;658:14361:15;;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;:::i;:::-;9231:13;;-1:-1:-1;9246:18:15;;;;;;658:14361;9231:13;9307:10;;;658:14361;9307:10;;;;:::i;:::-;658:14361;;;;:::i;:::-;9307:10;;:::i;:::-;658:14361;9231:13;;658:14361;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;:::i;:::-;-1:-1:-1;;658:14361:15;;-1:-1:-1;;;658:14361:15;;;;;;;;;8365:8;658:14361;;;:::i;:::-;8365:8;;:::i;658:14361::-;;;;;;-1:-1:-1;;658:14361:15;;;;3509:15;658:14361;;;;;:::i;:::-;;;3509:15;:::i;658:14361::-;;;;:::o;:::-;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;1327:149:8;-1:-1:-1;658:14361:15;;;1427:8:8;658:14361:15;;;;;;-1:-1:-1;;;;;658:14361:15;;1410:59:8;1418:36;;;1410:59;:::i;:::-;1327:149::o;658:14361:15:-;;;;:::o;:::-;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;2950:741:8;;658:14361:15;;;;;3081:12:8;;;658:14361:15;;5374:8:8;658:14361:15;;;;;;;3081:12:8;658:14361:15;;;;;;3073:20:8;;;658:14361:15;;3526:16:8;3596:17;658:14361:15;;;3127:16:8;3119:46;3127:16;;;3119:46;:::i;:::-;3197:10;;:18;:56;;;;2950:741;3197:89;;;;2950:741;3176:150;;;:::i;:::-;3526:16;:::i;:::-;658:14361:15;;-1:-1:-1;;658:14361:15;;;3559:14:8;;;:::i;:::-;658:14361:15;;;;;;3596:12:8;;658:14361:15;;5374:8:8;658:14361:15;;;;;;;3596:17:8;658:14361:15;3631:15:8;;;:::i;:::-;658:14361:15;;-1:-1:-1;;;;;;658:14361:15;;;;;-1:-1:-1;;;;;;;;;;;;3662:22:8;;2950:741::o;3197:89::-;3271:15;3176:150;3257:29;3271:15;;;;:::i;:::-;658:14361:15;-1:-1:-1;;;;;658:14361:15;;;3271:15:8;-1:-1:-1;;;;;658:14361:15;;;3257:29:8;3197:10;3257:29;3197:89;;;;:56;:10;3219:34;;3197:10;3219:22;;658:14361:15;;;;;;;;3219:16:8;658:14361:15;;;;;;;3219:22:8;:34;:::i;:::-;658:14361:15;;;;;3219:34:8;3197:56;;658:14361:15;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;3569:1183::-;;;;;;;;;;3869:10;;;;:::i;:::-;3950:36;;;3946:95;;4067:1;4070:20;;;;;;4294:13;;;;;4067:1;4309:15;;;;;;4522:13;;;4067:1;4537:22;;;;;;4736:8;;;;;;;;:::i;4522:13::-;4604:17;4623:20;4604:17;;658:14361;4604:17;;;;:::i;:::-;;:::i;:::-;4623:20;;;;;:::i;:::-;658:14361;4623:20;;;:::i;:::-;658:14361;4522:13;;4294;4367:10;;;;658:14361;4367:10;;;;:::i;:::-;;;:::i;:::-;658:14361;4294:13;;4055;4134:15;4151:12;4134:15;;;658:14361;4134:15;;;;:::i;:::-;4151:12;;;;;:::i;:::-;658:14361;4151:12;;:::i;:::-;658:14361;4055:13;;658:14361;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;-1:-1:-1;;658:14361:15;;;;:::o;838:32::-;;;;;;;658:14361;;;;838:32;658:14361;;;838:32;;;;;;;;;:::i;:::-;;;;658:14361;;838:32;;;;;;;;;:::i;:::-;;;;;;;;;:::i;658:14361::-;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;;;;;;;:::o;10469:355::-;;-1:-1:-1;;;;;658:14361:15;;10626:69;;;;;658:14361;10626:69;658:14361;10626:69;658:14361;;;;;;;;;;;;;10626:69;;10679:4;10626:69;;;;;:::i;:::-;;;;;;;;;;10769:48;10626:69;10769:48;10626:69;;;10469:355;10706:26;;;;:::i;:::-;658:14361;10626:69;658:14361;;;;;10626:69;658:14361;;;;10769:48;;;;;:::i;:::-;;;;10469:355::o;10626:69::-;;;;:::i;:::-;;;;1328:1782:10;;-1:-1:-1;1328:1782:10;;1532:1521;1328:1782;1532:1521;1328:1782;1532:1521;;658:14361:15;;;;1532:1521:10;;658:14361:15;;;;;1532:1521:10;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1532:1521:10;;;;;658:14361:15;;;1328:1782:10:o;658:14361:15:-;1532:1521:10;658:14361:15;-1:-1:-1;;;658:14361:15;;1532:1521:10;;658:14361:15;;;;1532:1521:10;658:14361:15;;;-1:-1:-1;;;1532:1521:10;658:14361:15;;;1532:1521:10;;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;11282:469::-;;;;;-1:-1:-1;;;;;658:14361:15;;;11460:152;;;;;658:14361;;;;;;;;;;;;11460:152;;;;;11538:4;;;;;;11460:152;;;;;:::i;:::-;;;;;;;;;11691:53;11460:152;11691:53;11460:152;658:14361;11460:152;;;11282:469;11623:22;;;;:::i;:::-;658:14361;;;;;;;;;;;;;;11623:53;658:14361;;;11623:53;:::i;:::-;658:14361;;;;11691:53;;;;;:::i;11460:152::-;;;;:::i;:::-;;;;12069:483;12223:8;;;:::i;:::-;12247:26;:36;:26;;;;:::i;:36::-;658:14361;12247:48;12243:106;;-1:-1:-1;;;;;658:14361:15;;;12358:69;;;;;-1:-1:-1;658:14361:15;;;;;;;12358:69;;12406:10;;;12358:69;12406:10;;12399:4;12358:69;;;;:::i;:::-;;;;;;;;;;12497:48;12358:69;12497:48;12358:69;;;12069:483;12445:26;-1:-1:-1;12445:36:15;:26;;;;:::i;:36::-;658:14361;;;12497:48;;;;;:::i;12358:69::-;;;;;;:::i;:::-;;;:::i;:::-;;;;12243:106;658:14361;;-1:-1:-1;;;12318:20:15;;;;;12558:391;;;12658:8;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;-1:-1:-1;658:14361:15;;;12695:12;658:14361;;;;;;;;;;;;;;;;;;;-1:-1:-1;658:14361:15;;-1:-1:-1;12739:11:15;;12735:48;;658:14361;3294:1377:10;658:14361:15;;;;;12695:12;658:14361;;;;;;;;;;;;;;;3294:1377:10;;;;;;;;;12867:10:15;3294:1377:10;;;;;;;;;;;;;;;;;;;;;;;658:14361:15;;;;12902:40;658:14361;12902:40;658:14361;;;12902:40;;;;;:::i;658:14361::-;;;;;;;;;;;3294:1377:10;658:14361:15;;;;3294:1377:10;658:14361:15;;;-1:-1:-1;;;3294:1377:10;658:14361:15;;;;12735:48;12766:7;;;;;;;;:::o;12955:582::-;13105:8;;;:::i;:::-;13142:42;:22;:32;:22;;;;:::i;:42::-;658:14361;13198:11;;;13194:48;;12358:69;13258:42;:22;:32;:22;;;;:::i;:42::-;658:14361;-1:-1:-1;;;;;658:14361:15;;;13311:151;;;;;12358:69;658:14361;;;;;;;13311:151;;13384:10;;;13311:151;13384:10;;;13365:4;13311:151;;;;:::i;:::-;;;;;;;;;;13478:52;13311:151;13478:52;13311:151;;;12955:582;658:14361;;;13478:52;;;;;:::i;13311:151::-;;;;;;:::i;:::-;;;;13194:48;13225:7;;;;:::o;13543:193::-;;;-1:-1:-1;;;;;658:14361:15;14617:17;13543:193;14617:17;:::i;:::-;658:14361;14603:10;:31;;:95;;;13543:193;14603:146;;;13543:193;14586:232;;-1:-1:-1;13682:47:15;-1:-1:-1;;13682:29:15;-1:-1:-1;;658:14361:15;;;;5690:8:8;658:14361:15;;;;;;;5713:42:8;5721:19;;;5713:42;:::i;:::-;658:14361:15;;;5845:10:8;658:14361:15;;;;;;;;;;;;5892:12:8;;658:14361:15;;5374:8:8;658:14361:15;;;;;;;5892:12:8;658:14361:15;;-1:-1:-1;;;;;;658:14361:15;;;;;;5922:15:8;;;:::i;:::-;658:14361:15;;;;;;-1:-1:-1;;;;;;;;;;;5953:31:8;;;658:14361:15;;13682:19;658:14361;;;;;;;14586:232;658:14361;;-1:-1:-1;;;14781:26:15;;;;;658:14361;;;;;14781:26;14603:146;:10;;14714:21;;;;:::i;:::-;658:14361;;14714:35;;14603:146;;:95;14668:17;;;;;:::i;:::-;658:14361;-1:-1:-1;658:14361:15;14651:16;658:14361;;;14651:47;14603:10;658:14361;-1:-1:-1;658:14361:15;14651:47;:::i;:::-;658:14361;;14650:48;14603:95;;13742:450;;13824:8;;;:::i;:::-;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;956:42;13902:11;;13898:48;;658:14361;;13861:12;658:14361;;;;;;;;;;;;;;;14024:10;;;;;;14016:43;;658:14361;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;14073:5;14069:64;;658:14361;;;;;956:42;658:14361;;;;;;;;;14148:37;;658:14361;;;;14148:37;658:14361;14069:64;658:14361;;-1:-1:-1;;;14101:21:15;;;;;658:14361;;;;13898:48;13929:7;;;;;;:::o;14198:318::-;-1:-1:-1;658:14361:15;;;14338:8;658:14361;;;;;;-1:-1:-1;;;;;658:14361:15;14366:144;;;14198:318::o;14366:144::-;14284:28;;;-1:-1:-1;14366:144:15;;-1:-1:-1;14366:144:15;14830:187;-1:-1:-1;658:14361:15;;;14908:19;658:14361;;;;;;-1:-1:-1;;;;;658:14361:15;14941:10;14908:43;14904:107;;14830:187;:::o;14904:107::-;658:14361;;;;14781:26;;;;14974;;;;;658:14361;14974:26
Swarm Source
ipfs://2bf1d4303a974a9c365b5d1e50143197a6e985423861903be649efb0c9359bcd
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.