More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 477,386 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Cancel Multiple ... | 19170936 | 12 mins ago | IN | 0 CRO | 0.18351212 | ||||
0x3b6d032e | 19170380 | 1 hr ago | IN | 0 CRO | 1.56104274 | ||||
Cancel Multiple ... | 19169576 | 2 hrs ago | IN | 0 CRO | 0.18527313 | ||||
0x3b6d032e | 19169568 | 2 hrs ago | IN | 0 CRO | 0.92870257 | ||||
0x38e29209 | 19169183 | 2 hrs ago | IN | 0 CRO | 1.54641352 | ||||
0xb4e4b296 | 19168881 | 3 hrs ago | IN | 9 CRO | 1.54826561 | ||||
0xb4e4b296 | 19168871 | 3 hrs ago | IN | 12 CRO | 1.489851 | ||||
0xb4e4b296 | 19168827 | 3 hrs ago | IN | 5.5 CRO | 1.48928287 | ||||
0xb4e4b296 | 19168804 | 3 hrs ago | IN | 5.5 CRO | 1.47317085 | ||||
0x3b6d032e | 19168172 | 4 hrs ago | IN | 0 CRO | 1.22270726 | ||||
0x3b6d032e | 19168102 | 4 hrs ago | IN | 0 CRO | 0.89772679 | ||||
0x3b6d032e | 19168092 | 4 hrs ago | IN | 0 CRO | 0.9993944 | ||||
0xb4e4b296 | 19168051 | 4 hrs ago | IN | 50 CRO | 1.06180935 | ||||
Cancel Multiple ... | 19167433 | 5 hrs ago | IN | 0 CRO | 0.18522768 | ||||
0xb4e4b296 | 19166711 | 6 hrs ago | IN | 499.9 CRO | 1.0918178 | ||||
Cancel Multiple ... | 19166711 | 6 hrs ago | IN | 0 CRO | 0.18522768 | ||||
0xb4e4b296 | 19165857 | 8 hrs ago | IN | 160.5 CRO | 1.06074618 | ||||
Cancel Multiple ... | 19165623 | 8 hrs ago | IN | 0 CRO | 0.18517266 | ||||
0x3b6d032e | 19164449 | 10 hrs ago | IN | 0 CRO | 0.96149853 | ||||
Cancel Multiple ... | 19163360 | 12 hrs ago | IN | 0 CRO | 0.27784153 | ||||
Cancel Multiple ... | 19162342 | 13 hrs ago | IN | 0 CRO | 0.27784153 | ||||
Cancel Multiple ... | 19161813 | 14 hrs ago | IN | 0 CRO | 0.18527313 | ||||
0x3b6d032e | 19159067 | 18 hrs ago | IN | 0 CRO | 0.95018906 | ||||
Cancel Multiple ... | 19159043 | 18 hrs ago | IN | 0 CRO | 0.1851193 | ||||
0x38e29209 | 19158688 | 19 hrs ago | IN | 0 CRO | 0.7861941 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
19168881 | 3 hrs ago | 9 CRO | ||||
19168871 | 3 hrs ago | 12 CRO | ||||
19168827 | 3 hrs ago | 5.5 CRO | ||||
19168804 | 3 hrs ago | 5.5 CRO | ||||
19168051 | 4 hrs ago | 50 CRO | ||||
19166711 | 6 hrs ago | 499.9 CRO | ||||
19165857 | 8 hrs ago | 160.5 CRO | ||||
19158110 | 20 hrs ago | 29 CRO | ||||
19158098 | 20 hrs ago | 25 CRO | ||||
19158090 | 20 hrs ago | 24 CRO | ||||
19158074 | 20 hrs ago | 20 CRO | ||||
19158068 | 20 hrs ago | 19 CRO | ||||
19158043 | 20 hrs ago | 25 CRO | ||||
19149521 | 33 hrs ago | 14.46415528 CRO | ||||
19149521 | 33 hrs ago | 14.46415528 CRO | ||||
19149521 | 33 hrs ago | 15 CRO | ||||
19149521 | 33 hrs ago | 15 CRO | ||||
19149521 | 33 hrs ago | 15 CRO | ||||
19149521 | 33 hrs ago | 15 CRO | ||||
19149521 | 33 hrs ago | 15 CRO | ||||
19149521 | 33 hrs ago | 15 CRO | ||||
19149081 | 34 hrs ago | 99 CRO | ||||
19146807 | 38 hrs ago | 499 CRO | ||||
19146174 | 39 hrs ago | 499 CRO | ||||
19146168 | 39 hrs ago | 470.73090805 CRO |
Loading...
Loading
Contract Name:
MintedExchange
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
/** .... .... .... #@@@? ^@@@@ :@@@@ P&&&! :@@@@ :@@@@ .... .... .... ..................... .... ............ ...!@@@@:... ............ ........!@@@@ !@@@& @@@@: G@@@Y .@@@@@@@@@@@@@@@@@@@@@. #@@@? !@@@@@@@@@@@@~ J@@@@@@@@@@@@^ P@@@@@@@@@@@@. B@@@@@@@@@@@@ !@@@& @@@@: G@@@5 .@@@@&&&&@@@@@&&&&@@@@. #@@@? !@@@@&&&&@@@@~ 7&&&&@@@@&&&&: P@@@@#&&&@@@@. B@@@@&&&&@@@@ ~&&&G #&&&. G@@@5 .@@@@. G@@@5 .@@@@. #@@@? !@@@& &@@@~ ^@@@@ P@@@G...~@@@@. B@@@Y ^@@@@ G@@@5 .@@@@. G@@@5 .@@@@. #@@@? !@@@& &@@@~ ^@@@@ P@@@@@@@@@@@@. B@@@J :@@@@ G@@@5 .@@@@. G@@@5 .@@@@. #@@@? !@@@& &@@@~ ^@@@@ P@@@@#&&&##&#. B@@@J :@@@@ ............B@@@5 .@@@@. G@@@5 .@@@@. #@@@? !@@@& &@@@~ ^@@@@ P@@@G........ B@@@5...!@@@@ !@@@@@@@@@@@@@@@@5 .@@@@. G@@@5 .@@@@. #@@@? 7@@@& &@@@~ ^@@@@ P@@@@@@@@@@@@. B@@@@@@@@@@@@ ~&&&&&&&&&&&&&&&&? .&&&# Y&&&? .&&&#. P&&&! ~&&&G B&&&^ :&&&# J&&&&&&&&&&&&. 5&&&&&&&&&&&# */ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // OpenZeppelin contracts import {AccessControlEnumerable} from "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; // Minted interfaces import {ICurrencyManager} from "./interfaces/ICurrencyManager.sol"; import {IExecutionManager} from "./interfaces/IExecutionManager.sol"; import {IExecutionStrategy} from "./interfaces/IExecutionStrategy.sol"; import {IRoyaltyFeeManager} from "./interfaces/IRoyaltyFeeManager.sol"; import {IMintedExchange} from "./interfaces/IMintedExchange.sol"; import {ITransferManagerNFT} from "./interfaces/ITransferManagerNFT.sol"; import {ITransferSelectorNFT} from "./interfaces/ITransferSelectorNFT.sol"; import {IWETH} from "./interfaces/IWETH.sol"; // Minted libraries import {OrderTypes} from "./libraries/OrderTypes.sol"; import {SignatureChecker} from "./libraries/SignatureChecker.sol"; /** * @title Minted * @notice It is the core contract of the Minted exchange. */ contract MintedExchange is IMintedExchange, ReentrancyGuard, Pausable, AccessControlEnumerable { using SafeERC20 for IERC20; using OrderTypes for OrderTypes.MakerOrder; using OrderTypes for OrderTypes.TakerOrder; bytes32 public constant MATCH_MAKER_ORDERS_ROLE = keccak256("MATCH_MAKER_ORDERS_ROLE"); bool public isMatchMakerOrderBeta = true; address public immutable WETH; bytes32 public immutable DOMAIN_SEPARATOR; address public protocolFeeRecipient; ICurrencyManager public currencyManager; IExecutionManager public executionManager; IRoyaltyFeeManager public royaltyFeeManager; ITransferSelectorNFT public transferSelectorNFT; mapping(address => uint256) public userMinOrderNonce; mapping(address => mapping(uint256 => bool)) private _isUserOrderNonceExecutedOrCancelled; event CancelAllOrders(address indexed user, uint256 newMinNonce); event CancelMultipleOrders(address indexed user, uint256[] orderNonces); event NewCurrencyManager(address indexed currencyManager); event NewExecutionManager(address indexed executionManager); event NewProtocolFeeRecipient(address indexed protocolFeeRecipient); event NewRoyaltyFeeManager(address indexed royaltyFeeManager); event NewTransferSelectorNFT(address indexed transferSelectorNFT); event RoyaltyPayment( address indexed collection, uint256 indexed tokenId, address indexed royaltyRecipient, address currency, uint256 amount ); event TakerAsk( bytes32 orderHash, // bid hash of the maker order uint256 orderNonce, // user order nonce address indexed taker, // sender address for the taker ask order address indexed maker, // maker address of the initial bid order address indexed strategy, // strategy that defines the execution address currency, // currency address address collection, // collection address uint256 tokenId, // tokenId transferred uint256 amount, // amount of tokens transferred uint256 price // final transacted price ); event TakerBid( bytes32 orderHash, // ask hash of the maker order uint256 orderNonce, // user order nonce address indexed taker, // sender address for the taker bid order address indexed maker, // maker address of the initial ask order address indexed strategy, // strategy that defines the execution address currency, // currency address address collection, // collection address uint256 tokenId, // tokenId transferred uint256 amount, // amount of tokens transferred uint256 price // final transacted price ); event MakerMatch( bytes32 orderHash, //ask hash of the maker order uint256 bidOrderNonce, // user bid order nonce uint256 askOrderNonce, // user ask order nonce address indexed taker, // address for the bid order address indexed maker, // address of the ask order address indexed strategy, // strategy that defines the execution address currency, // currency address address collection, // collection address uint256 tokenId, // tokenId transferred uint256 amount, // amount of tokens transferred uint256 price // final transacted price ); modifier onlyMatchMakerRoleOrNotBeta() { require( !isMatchMakerOrderBeta || hasRole(MATCH_MAKER_ORDERS_ROLE, msg.sender), "MintedExchange: no permission to call match maker order" ); _; } /** * @notice Constructor * @param _currencyManager currency manager address * @param _executionManager execution manager address * @param _royaltyFeeManager royalty fee manager address * @param _WETH wrapped ether address (for other chains, use wrapped native asset) * @param _protocolFeeRecipient protocol fee recipient */ constructor( address _currencyManager, address _executionManager, address _royaltyFeeManager, address _WETH, address _protocolFeeRecipient ) { require(_currencyManager != address(0), "_currencyManager is address(0)"); require(_executionManager != address(0), "_executionManager is address(0)"); require(_royaltyFeeManager != address(0), "_royaltyFeeManager is address(0)"); require(_WETH != address(0), "_WETH is address(0)"); // Calculate the domain separator DOMAIN_SEPARATOR = keccak256( abi.encode( 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f, // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") 0xbc11948365c354ad12f7242cbad9cd271ba4e4834d635121cd5c915109927d7b, // keccak256("MintedExchange") 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6, // keccak256(bytes("1")) for versionId = 1 block.chainid, address(this) ) ); currencyManager = ICurrencyManager(_currencyManager); executionManager = IExecutionManager(_executionManager); royaltyFeeManager = IRoyaltyFeeManager(_royaltyFeeManager); WETH = _WETH; protocolFeeRecipient = _protocolFeeRecipient; // contract owner will be able to grant role to other _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); } /** * @notice Cancel all pending orders for a sender * @param minNonce minimum user nonce */ function cancelAllOrdersForSender(uint256 minNonce) external { require(minNonce > userMinOrderNonce[msg.sender], "Cancel: Order nonce lower than current"); require(minNonce < userMinOrderNonce[msg.sender] + 500000, "Cancel: Cannot cancel more orders"); userMinOrderNonce[msg.sender] = minNonce; emit CancelAllOrders(msg.sender, minNonce); } /** * @notice Cancel maker orders * @param orderNonces array of order nonces */ function cancelMultipleMakerOrders(uint256[] calldata orderNonces) external { require(orderNonces.length > 0, "Cancel: Cannot be empty"); for (uint256 i = 0; i < orderNonces.length; i++) { require( orderNonces[i] >= userMinOrderNonce[msg.sender], "Cancel: Order nonce lower than current" ); _isUserOrderNonceExecutedOrCancelled[msg.sender][orderNonces[i]] = true; } emit CancelMultipleOrders(msg.sender, orderNonces); } /** * @notice Match ask with a taker bid order using ETH * @param takerBid taker bid order * @param makerAsk maker ask order */ function matchAskWithTakerBidUsingETHAndWETH( OrderTypes.TakerOrder calldata takerBid, OrderTypes.MakerOrder calldata makerAsk ) external payable override nonReentrant { require((makerAsk.isOrderAsk) && (!takerBid.isOrderAsk), "Order: Wrong sides"); require(makerAsk.currency == WETH, "Order: Currency must be WETH"); require(msg.sender == takerBid.taker, "Order: Taker must be the sender"); // If not enough ETH to cover the price, use WETH if (takerBid.price > msg.value) { IERC20(WETH).safeTransferFrom(msg.sender, address(this), (takerBid.price - msg.value)); } else { require(takerBid.price == msg.value, "Order: Msg.value too high"); } // Wrap ETH sent to this contract IWETH(WETH).deposit{value: msg.value}(); // Check the maker ask order bytes32 askHash = makerAsk.hash(); _validateOrder(makerAsk, askHash); // Retrieve execution parameters (bool isExecutionValid, uint256 tokenId, uint256 amount) = IExecutionStrategy(makerAsk.strategy) .canExecuteTakerBid(takerBid, makerAsk); require(isExecutionValid, "Strategy: Execution invalid"); // Update maker ask order status to true (prevents replay) _isUserOrderNonceExecutedOrCancelled[makerAsk.signer][makerAsk.nonce] = true; // Execution part 1/2 _transferFeesAndFundsWithWETH( makerAsk.strategy, makerAsk.collection, tokenId, makerAsk.signer, takerBid.price, makerAsk.minPercentageToAsk ); // Execution part 2/2 _transferNonFungibleToken(makerAsk.collection, makerAsk.signer, takerBid.taker, tokenId, amount); emit TakerBid( askHash, makerAsk.nonce, takerBid.taker, makerAsk.signer, makerAsk.strategy, makerAsk.currency, makerAsk.collection, tokenId, amount, takerBid.price ); } /** * @notice Match a takerBid with a matchAsk * @param takerBid taker bid order * @param makerAsk maker ask order */ function matchAskWithTakerBid( OrderTypes.TakerOrder calldata takerBid, OrderTypes.MakerOrder calldata makerAsk ) external override nonReentrant { require((makerAsk.isOrderAsk) && (!takerBid.isOrderAsk), "Order: Wrong sides"); require(msg.sender == takerBid.taker, "Order: Taker must be the sender"); // Check the maker ask order bytes32 askHash = makerAsk.hash(); _validateOrder(makerAsk, askHash); (bool isExecutionValid, uint256 tokenId, uint256 amount) = IExecutionStrategy(makerAsk.strategy) .canExecuteTakerBid(takerBid, makerAsk); require(isExecutionValid, "Strategy: Execution invalid"); // Update maker ask order status to true (prevents replay) _isUserOrderNonceExecutedOrCancelled[makerAsk.signer][makerAsk.nonce] = true; // Execution part 1/2 _transferFeesAndFunds( makerAsk.strategy, makerAsk.collection, tokenId, makerAsk.currency, msg.sender, makerAsk.signer, takerBid.price, makerAsk.minPercentageToAsk ); // Execution part 2/2 _transferNonFungibleToken(makerAsk.collection, makerAsk.signer, takerBid.taker, tokenId, amount); emit TakerBid( askHash, makerAsk.nonce, takerBid.taker, makerAsk.signer, makerAsk.strategy, makerAsk.currency, makerAsk.collection, tokenId, amount, takerBid.price ); } /** * @notice Match a takerAsk with a makerBid * @param takerAsk taker ask order * @param makerBid maker bid order */ function matchBidWithTakerAsk( OrderTypes.TakerOrder calldata takerAsk, OrderTypes.MakerOrder calldata makerBid ) external override nonReentrant { require((!makerBid.isOrderAsk) && (takerAsk.isOrderAsk), "Order: Wrong sides"); require(msg.sender == takerAsk.taker, "Order: Taker must be the sender"); // Check the maker bid order bytes32 bidHash = makerBid.hash(); _validateOrder(makerBid, bidHash); (bool isExecutionValid, uint256 tokenId, uint256 amount) = IExecutionStrategy(makerBid.strategy) .canExecuteTakerAsk(takerAsk, makerBid); require(isExecutionValid, "Strategy: Execution invalid"); // Update maker bid order status to true (prevents replay) _isUserOrderNonceExecutedOrCancelled[makerBid.signer][makerBid.nonce] = true; // Execution part 1/2 _transferNonFungibleToken(makerBid.collection, msg.sender, makerBid.signer, tokenId, amount); // Execution part 2/2 _transferFeesAndFunds( makerBid.strategy, makerBid.collection, tokenId, makerBid.currency, makerBid.signer, takerAsk.taker, takerAsk.price, takerAsk.minPercentageToAsk ); emit TakerAsk( bidHash, makerBid.nonce, takerAsk.taker, makerBid.signer, makerBid.strategy, makerBid.currency, makerBid.collection, tokenId, amount, takerAsk.price ); } /** * @notice match a MakerBid with MakerAsk order * @dev only callable by whitelisted address * @param makerBid maker bid order * @param makerAsk maker ask order */ function matchMakerOrders( OrderTypes.MakerOrder calldata makerBid, OrderTypes.MakerOrder calldata makerAsk ) external override nonReentrant whenNotPaused onlyMatchMakerRoleOrNotBeta { require((!makerBid.isOrderAsk) && (makerAsk.isOrderAsk), "Order: Wrong sides"); // Check the maker bid and ask order _validateOrder(makerBid, makerBid.hash()); _validateOrder(makerAsk, makerAsk.hash()); // For this case both order must point to the same strategy require(makerBid.strategy == makerAsk.strategy, "Order: Both strategy must be same"); (bool isExecutionValid, uint256 tokenId, uint256 amount) = IExecutionStrategy(makerAsk.strategy) .canExecuteMakerOrder(makerBid, makerAsk); require(isExecutionValid, "Strategy: Execution invalid"); // Update maker order status to true (prevents replay) _isUserOrderNonceExecutedOrCancelled[makerAsk.signer][makerAsk.nonce] = true; _isUserOrderNonceExecutedOrCancelled[makerBid.signer][makerBid.nonce] = true; // Execution part 1/2 _transferFeesAndFunds( makerAsk.strategy, makerAsk.collection, tokenId, makerAsk.currency, makerBid.signer, makerAsk.signer, makerBid.price, makerAsk.minPercentageToAsk ); // Execution part 2/2 _transferNonFungibleToken(makerAsk.collection, makerAsk.signer, makerBid.signer, tokenId, amount); emit MakerMatch( makerAsk.hash(), makerBid.nonce, makerAsk.nonce, makerBid.signer, makerAsk.signer, makerAsk.strategy, makerAsk.currency, makerAsk.collection, tokenId, amount, makerBid.price ); } /** * @notice Update currency manager * @param _currencyManager new currency manager address */ function updateCurrencyManager(address _currencyManager) external onlyRole(DEFAULT_ADMIN_ROLE) { require(_currencyManager != address(0), "Owner: Cannot be null address"); currencyManager = ICurrencyManager(_currencyManager); emit NewCurrencyManager(_currencyManager); } /** * @notice Update execution manager * @param _executionManager new execution manager address */ function updateExecutionManager(address _executionManager) external onlyRole(DEFAULT_ADMIN_ROLE) { require(_executionManager != address(0), "Owner: Cannot be null address"); executionManager = IExecutionManager(_executionManager); emit NewExecutionManager(_executionManager); } /** * @notice Update protocol fee and recipient * @param _protocolFeeRecipient new recipient for protocol fees */ function updateProtocolFeeRecipient(address _protocolFeeRecipient) external onlyRole(DEFAULT_ADMIN_ROLE) { protocolFeeRecipient = _protocolFeeRecipient; emit NewProtocolFeeRecipient(_protocolFeeRecipient); } /** * @notice Update royalty fee manager * @param _royaltyFeeManager new fee manager address */ function updateRoyaltyFeeManager(address _royaltyFeeManager) external onlyRole(DEFAULT_ADMIN_ROLE) { require(_royaltyFeeManager != address(0), "Owner: Cannot be null address"); royaltyFeeManager = IRoyaltyFeeManager(_royaltyFeeManager); emit NewRoyaltyFeeManager(_royaltyFeeManager); } /** * @notice Update transfer selector NFT * @param _transferSelectorNFT new transfer selector address */ function updateTransferSelectorNFT(address _transferSelectorNFT) external onlyRole(DEFAULT_ADMIN_ROLE) { require(_transferSelectorNFT != address(0), "Owner: Cannot be null address"); transferSelectorNFT = ITransferSelectorNFT(_transferSelectorNFT); emit NewTransferSelectorNFT(_transferSelectorNFT); } /** * @notice Pause the contract. Revert if already paused. */ function pause() external onlyRole(DEFAULT_ADMIN_ROLE) { _pause(); } /** * @notice Unpause the contract. Revert if already unpaused. */ function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); } /** * @notice toggle beta mode. If beta is false, it will allow all address to call matchMakerOrders */ function toggleMatchMakerOrderBeta() external onlyRole(DEFAULT_ADMIN_ROLE) { isMatchMakerOrderBeta = !isMatchMakerOrderBeta; } /** * @notice Check whether user order nonce is executed or cancelled * @param user address of user * @param orderNonce nonce of the order */ function isUserOrderNonceExecutedOrCancelled(address user, uint256 orderNonce) external view returns (bool) { return _isUserOrderNonceExecutedOrCancelled[user][orderNonce]; } /** * @notice Transfer fees and funds to royalty recipient, protocol, and seller * @param strategy address of the execution strategy * @param collection non fungible token address for the transfer * @param tokenId tokenId * @param currency currency being used for the purchase (e.g., WETH/USDC) * @param from sender of the funds * @param to seller's recipient * @param amount amount being transferred (in currency) * @param minPercentageToAsk minimum percentage of the gross amount that goes to ask */ function _transferFeesAndFunds( address strategy, address collection, uint256 tokenId, address currency, address from, address to, uint256 amount, uint256 minPercentageToAsk ) internal { // Initialize the final amount that is transferred to seller uint256 finalSellerAmount = amount; // 1. Protocol fee { uint256 protocolFeeAmount = _calculateProtocolFee(strategy, amount); // Check if the protocol fee is different than 0 for this strategy if ((protocolFeeRecipient != address(0)) && (protocolFeeAmount != 0)) { IERC20(currency).safeTransferFrom(from, protocolFeeRecipient, protocolFeeAmount); finalSellerAmount -= protocolFeeAmount; } } // 2. Royalty fee { (address royaltyFeeRecipient, uint256 royaltyFeeAmount) = royaltyFeeManager .calculateRoyaltyFeeAndGetRecipient(collection, tokenId, amount); // Check if there is a royalty fee and that it is different to 0 if ((royaltyFeeRecipient != address(0)) && (royaltyFeeAmount != 0)) { IERC20(currency).safeTransferFrom(from, royaltyFeeRecipient, royaltyFeeAmount); finalSellerAmount -= royaltyFeeAmount; emit RoyaltyPayment(collection, tokenId, royaltyFeeRecipient, currency, royaltyFeeAmount); } } require((finalSellerAmount * 10000) >= (minPercentageToAsk * amount), "Fees: Higher than expected"); // 3. Transfer final amount (post-fees) to seller { IERC20(currency).safeTransferFrom(from, to, finalSellerAmount); } } /** * @notice Transfer fees and funds to royalty recipient, protocol, and seller * @param strategy address of the execution strategy * @param collection non fungible token address for the transfer * @param tokenId tokenId * @param to seller's recipient * @param amount amount being transferred (in currency) * @param minPercentageToAsk minimum percentage of the gross amount that goes to ask */ function _transferFeesAndFundsWithWETH( address strategy, address collection, uint256 tokenId, address to, uint256 amount, uint256 minPercentageToAsk ) internal { // Initialize the final amount that is transferred to seller uint256 finalSellerAmount = amount; // 1. Protocol fee { uint256 protocolFeeAmount = _calculateProtocolFee(strategy, amount); // Check if the protocol fee is different than 0 for this strategy if ((protocolFeeRecipient != address(0)) && (protocolFeeAmount != 0)) { IERC20(WETH).safeTransfer(protocolFeeRecipient, protocolFeeAmount); finalSellerAmount -= protocolFeeAmount; } } // 2. Royalty fee { (address royaltyFeeRecipient, uint256 royaltyFeeAmount) = royaltyFeeManager .calculateRoyaltyFeeAndGetRecipient(collection, tokenId, amount); // Check if there is a royalty fee and that it is different to 0 if ((royaltyFeeRecipient != address(0)) && (royaltyFeeAmount != 0)) { IERC20(WETH).safeTransfer(royaltyFeeRecipient, royaltyFeeAmount); finalSellerAmount -= royaltyFeeAmount; emit RoyaltyPayment( collection, tokenId, royaltyFeeRecipient, address(WETH), royaltyFeeAmount ); } } require((finalSellerAmount * 10000) >= (minPercentageToAsk * amount), "Fees: Higher than expected"); // 3. Transfer final amount (post-fees) to seller { IERC20(WETH).safeTransfer(to, finalSellerAmount); } } /** * @notice Transfer NFT * @param collection address of the token collection * @param from address of the sender * @param to address of the recipient * @param tokenId tokenId * @param amount amount of tokens (1 for ERC721, 1+ for ERC1155) * @dev For ERC721, amount is not used */ function _transferNonFungibleToken( address collection, address from, address to, uint256 tokenId, uint256 amount ) internal { // Retrieve the transfer manager address address transferManager = transferSelectorNFT.checkTransferManagerForToken(collection); // If no transfer manager found, it returns address(0) require(transferManager != address(0), "Transfer: No NFT transfer manager available"); // If one is found, transfer the token ITransferManagerNFT(transferManager).transferNonFungibleToken(collection, from, to, tokenId, amount); } /** * @notice Calculate protocol fee for an execution strategy * @param executionStrategy strategy * @param amount amount to transfer */ function _calculateProtocolFee(address executionStrategy, uint256 amount) internal view returns (uint256) { uint256 protocolFee = IExecutionStrategy(executionStrategy).viewProtocolFee(); return (protocolFee * amount) / 10000; } /** * @notice Verify the validity of the maker order * @param makerOrder maker order * @param orderHash computed hash for the order */ function _validateOrder(OrderTypes.MakerOrder calldata makerOrder, bytes32 orderHash) internal view { // Verify whether order nonce has expired require( (!_isUserOrderNonceExecutedOrCancelled[makerOrder.signer][makerOrder.nonce]) && (makerOrder.nonce >= userMinOrderNonce[makerOrder.signer]), "Order: Matching order expired" ); // Verify the signer is not address(0) require(makerOrder.signer != address(0), "Order: Invalid signer"); // Verify the amount is not 0 require(makerOrder.amount > 0, "Order: Amount cannot be 0"); // Verify the validity of the signature require( SignatureChecker.verify( orderHash, makerOrder.signer, makerOrder.v, makerOrder.r, makerOrder.s, DOMAIN_SEPARATOR ), "Signature: Invalid" ); // Verify whether the currency is whitelisted require(currencyManager.isCurrencyWhitelisted(makerOrder.currency), "Currency: Not whitelisted"); // Verify whether strategy can be executed require(executionManager.isStrategyWhitelisted(makerOrder.strategy), "Strategy: Not whitelisted"); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControlEnumerable.sol"; import "./AccessControl.sol"; import "../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ICurrencyManager { function addCurrency(address currency) external; function removeCurrency(address currency) external; function isCurrencyWhitelisted(address currency) external view returns (bool); function viewWhitelistedCurrencies(uint256 cursor, uint256 size) external view returns (address[] memory, uint256); function viewCountWhitelistedCurrencies() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IExecutionManager { function addStrategy(address strategy) external; function removeStrategy(address strategy) external; function isStrategyWhitelisted(address strategy) external view returns (bool); function viewWhitelistedStrategies(uint256 cursor, uint256 size) external view returns (address[] memory, uint256); function viewCountWhitelistedStrategies() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {OrderTypes} from "../libraries/OrderTypes.sol"; interface IExecutionStrategy { function canExecuteTakerAsk( OrderTypes.TakerOrder calldata takerAsk, OrderTypes.MakerOrder calldata makerBid ) external view returns ( bool, uint256, uint256 ); function canExecuteTakerBid( OrderTypes.TakerOrder calldata takerBid, OrderTypes.MakerOrder calldata makerAsk ) external view returns ( bool, uint256, uint256 ); function canExecuteMakerOrder( OrderTypes.MakerOrder calldata makerBid, OrderTypes.MakerOrder calldata makerAsk ) external view returns ( bool, uint256, uint256 ); function viewProtocolFee() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IRoyaltyFeeManager { function calculateRoyaltyFeeAndGetRecipient( address collection, uint256 tokenId, uint256 amount ) external view returns (address, uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {OrderTypes} from "../libraries/OrderTypes.sol"; interface IMintedExchange { function matchAskWithTakerBidUsingETHAndWETH( OrderTypes.TakerOrder calldata takerBid, OrderTypes.MakerOrder calldata makerAsk ) external payable; function matchAskWithTakerBid( OrderTypes.TakerOrder calldata takerBid, OrderTypes.MakerOrder calldata makerAsk ) external; function matchBidWithTakerAsk( OrderTypes.TakerOrder calldata takerAsk, OrderTypes.MakerOrder calldata makerBid ) external; function matchMakerOrders( OrderTypes.MakerOrder calldata makerBid, OrderTypes.MakerOrder calldata makerAsk ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ITransferManagerNFT { function transferNonFungibleToken( address collection, address from, address to, uint256 tokenId, uint256 amount ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ITransferSelectorNFT { function checkTransferManagerForToken(address collection) external view returns (address); }
// SPDX-License-Identifier: GNU pragma solidity >=0.5.0; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title OrderTypes * @notice This library contains order types for the Minted exchange. */ library OrderTypes { // keccak256("MakerOrder(bool isOrderAsk,address signer,address collection,uint256 price,uint256 tokenId,uint256 amount,address strategy,address currency,uint256 nonce,uint256 startTime,uint256 endTime,uint256 minPercentageToAsk,bytes params)") bytes32 internal constant MAKER_ORDER_HASH = 0x40261ade532fa1d2c7293df30aaadb9b3c616fae525a0b56d3d411c841a85028; struct MakerOrder { bool isOrderAsk; // true --> ask / false --> bid address signer; // signer of the maker order address collection; // collection address uint256 price; // price (used as ) uint256 tokenId; // id of the token uint256 amount; // amount of tokens to sell/purchase (must be 1 for ERC721, 1+ for ERC1155) address strategy; // strategy for trade execution (e.g., DutchAuction, StandardSaleForFixedPrice) address currency; // currency (e.g., WETH) uint256 nonce; // order nonce (must be unique unless new maker order is meant to override existing one e.g., lower ask price) uint256 startTime; // startTime in timestamp uint256 endTime; // endTime in timestamp uint256 minPercentageToAsk; // slippage protection (9000 --> 90% of the final price must return to ask) bytes params; // additional parameters uint8 v; // v: parameter (27 or 28) bytes32 r; // r: parameter bytes32 s; // s: parameter } struct TakerOrder { bool isOrderAsk; // true --> ask / false --> bid address taker; // msg.sender uint256 price; // final price for the purchase uint256 tokenId; uint256 minPercentageToAsk; // // slippage protection (9000 --> 90% of the final price must return to ask) bytes params; // other params (e.g., tokenId) } function hash(MakerOrder memory makerOrder) internal pure returns (bytes32) { return keccak256( abi.encode( MAKER_ORDER_HASH, makerOrder.isOrderAsk, makerOrder.signer, makerOrder.collection, makerOrder.price, makerOrder.tokenId, makerOrder.amount, makerOrder.strategy, makerOrder.currency, makerOrder.nonce, makerOrder.startTime, makerOrder.endTime, makerOrder.minPercentageToAsk, keccak256(makerOrder.params) ) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; /** * @title SignatureChecker * @notice This library allows verification of signatures for both EOAs and contracts. */ library SignatureChecker { /** * @notice Recovers the signer of a signature (for EOA) * @param hash the hash containing the signed mesage * @param v parameter (27 or 28). This prevents maleability since the public key recovery equation has two possible solutions. * @param r parameter * @param s parameter */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { // https://ethereum.stackexchange.com/questions/83174/is-it-best-practice-to-check-signature-malleability-in-ecrecover // https://crypto.iacr.org/2019/affevents/wac/medias/Heninger-BiasedNonceSense.pdf require( uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "Signature: Invalid s parameter" ); require(v == 27 || v == 28, "Signature: Invalid v parameter"); // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); require(signer != address(0), "Signature: Invalid signer"); return signer; } /** * @notice Returns whether the signer matches the signed message * @param hash the hash containing the signed mesage * @param signer the signer address to confirm message validity * @param v parameter (27 or 28) * @param r parameter * @param s parameter * @param domainSeparator paramer to prevent signature being executed in other chains and environments * @return true --> if valid // false --> if invalid */ function verify( bytes32 hash, address signer, uint8 v, bytes32 r, bytes32 s, bytes32 domainSeparator ) internal view returns (bool) { // \x19\x01 is the standardized encoding prefix // https://eips.ethereum.org/EIPS/eip-712#specification bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, hash)); if (Address.isContract(signer)) { // 0x1626ba7e is the interfaceId for signature contracts (see IERC1271) return IERC1271(signer).isValidSignature(digest, abi.encodePacked(r, s, v)) == 0x1626ba7e; } else { return recover(digest, v, r, s) == signer; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_currencyManager","type":"address"},{"internalType":"address","name":"_executionManager","type":"address"},{"internalType":"address","name":"_royaltyFeeManager","type":"address"},{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"_protocolFeeRecipient","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newMinNonce","type":"uint256"}],"name":"CancelAllOrders","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"orderNonces","type":"uint256[]"}],"name":"CancelMultipleOrders","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"bidOrderNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"askOrderNonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"taker","type":"address"},{"indexed":true,"internalType":"address","name":"maker","type":"address"},{"indexed":true,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"MakerMatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"currencyManager","type":"address"}],"name":"NewCurrencyManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executionManager","type":"address"}],"name":"NewExecutionManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"protocolFeeRecipient","type":"address"}],"name":"NewProtocolFeeRecipient","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"royaltyFeeManager","type":"address"}],"name":"NewRoyaltyFeeManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transferSelectorNFT","type":"address"}],"name":"NewTransferSelectorNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"royaltyRecipient","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RoyaltyPayment","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"orderNonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"taker","type":"address"},{"indexed":true,"internalType":"address","name":"maker","type":"address"},{"indexed":true,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"TakerAsk","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"orderNonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"taker","type":"address"},{"indexed":true,"internalType":"address","name":"maker","type":"address"},{"indexed":true,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"TakerBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MATCH_MAKER_ORDERS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minNonce","type":"uint256"}],"name":"cancelAllOrdersForSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"orderNonces","type":"uint256[]"}],"name":"cancelMultipleMakerOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currencyManager","outputs":[{"internalType":"contract ICurrencyManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executionManager","outputs":[{"internalType":"contract IExecutionManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMatchMakerOrderBeta","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"orderNonce","type":"uint256"}],"name":"isUserOrderNonceExecutedOrCancelled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isOrderAsk","type":"bool"},{"internalType":"address","name":"taker","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"minPercentageToAsk","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"internalType":"struct OrderTypes.TakerOrder","name":"takerBid","type":"tuple"},{"components":[{"internalType":"bool","name":"isOrderAsk","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"minPercentageToAsk","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerAsk","type":"tuple"}],"name":"matchAskWithTakerBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isOrderAsk","type":"bool"},{"internalType":"address","name":"taker","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"minPercentageToAsk","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"internalType":"struct OrderTypes.TakerOrder","name":"takerBid","type":"tuple"},{"components":[{"internalType":"bool","name":"isOrderAsk","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"minPercentageToAsk","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerAsk","type":"tuple"}],"name":"matchAskWithTakerBidUsingETHAndWETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isOrderAsk","type":"bool"},{"internalType":"address","name":"taker","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"minPercentageToAsk","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"internalType":"struct OrderTypes.TakerOrder","name":"takerAsk","type":"tuple"},{"components":[{"internalType":"bool","name":"isOrderAsk","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"minPercentageToAsk","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerBid","type":"tuple"}],"name":"matchBidWithTakerAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isOrderAsk","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"minPercentageToAsk","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerBid","type":"tuple"},{"components":[{"internalType":"bool","name":"isOrderAsk","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"minPercentageToAsk","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerAsk","type":"tuple"}],"name":"matchMakerOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyFeeManager","outputs":[{"internalType":"contract IRoyaltyFeeManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleMatchMakerOrderBeta","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferSelectorNFT","outputs":[{"internalType":"contract ITransferSelectorNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_currencyManager","type":"address"}],"name":"updateCurrencyManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_executionManager","type":"address"}],"name":"updateExecutionManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_protocolFeeRecipient","type":"address"}],"name":"updateProtocolFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_royaltyFeeManager","type":"address"}],"name":"updateRoyaltyFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_transferSelectorNFT","type":"address"}],"name":"updateTransferSelectorNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMinOrderNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040526004805460ff191660011790553480156200001e57600080fd5b50604051620044183803806200441883398101604081905262000041916200045f565b60016000819055805460ff191690556001600160a01b038516620000ac5760405162461bcd60e51b815260206004820152601e60248201527f5f63757272656e63794d616e616765722069732061646472657373283029000060448201526064015b60405180910390fd5b6001600160a01b038416620001045760405162461bcd60e51b815260206004820152601f60248201527f5f657865637574696f6e4d616e616765722069732061646472657373283029006044820152606401620000a3565b6001600160a01b0383166200015c5760405162461bcd60e51b815260206004820181905260248201527f5f726f79616c74794665654d616e6167657220697320616464726573732830296044820152606401620000a3565b6001600160a01b038216620001b45760405162461bcd60e51b815260206004820152601360248201527f5f574554482069732061646472657373283029000000000000000000000000006044820152606401620000a3565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527fbc11948365c354ad12f7242cbad9cd271ba4e4834d635121cd5c915109927d7b918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152919052805160209091012060a052600580546001600160a01b038088166001600160a01b031992831617909255600680548784169083161790556007805486841692169190911790556001600160601b0319606084901b166080526004805491831661010002610100600160a81b0319909216919091179055620002ce600033620002d9565b5050505050620004ce565b620002e58282620002e9565b5050565b6200030082826200032c60201b62001bf41760201c565b60008281526003602090815260409091206200032791839062001c7a620003d0821b17901c565b505050565b60008281526002602090815260408083206001600160a01b038516845290915290205460ff16620002e55760008281526002602090815260408083206001600160a01b03851684529091529020805460ff191660011790556200038c3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000620003e7836001600160a01b038416620003f0565b90505b92915050565b60008181526001830160205260408120546200043957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003ea565b506000620003ea565b80516001600160a01b03811681146200045a57600080fd5b919050565b600080600080600060a0868803121562000477578081fd5b620004828662000442565b9450620004926020870162000442565b9350620004a26040870162000442565b9250620004b26060870162000442565b9150620004c26080870162000442565b90509295509295909350565b60805160601c60a051613ee96200052f600039600081816103680152611fd10152600081816105ba01528181611607015281816116f701528181611779015281816127540152818161284c015281816128b701526129760152613ee96000f3fe6080604052600436106102045760003560e01c80635e14f68e11610118578063ad5c4648116100a0578063ca15c8731161006f578063ca15c87314610643578063cbd2ec6514610663578063d4ff41dc14610683578063d547741f146106a3578063f75ff53f146106c357600080fd5b8063ad5c4648146105a8578063b4e4b296146105dc578063c5498769146105ef578063c808367f1461060f57600080fd5b80639010d07c116100e75780639010d07c1461051e57806391d148541461053e578063978cb4ad1461055e5780639e53a69a14610573578063a217fddf1461059357600080fd5b80635e14f68e146104a457806364df049e146104c45780638456cb59146104e957806387e4401f146104fe57600080fd5b806336568abe1161019b5780634266581e1161016a5780634266581e146103ff578063483abb9f1461042c578063503b65f11461044c5780635c975abb1461046c5780635ce052d71461048457600080fd5b806336568abe1461038a57806338e29209146103aa5780633b6d032e146103ca5780633f4ba83a146103ea57600080fd5b8063248a9ca3116101d7578063248a9ca3146102b25780632f2ff15d146102f057806331e27e27146103105780633644e5151461035657600080fd5b806301ffc9a7146102095780630f747d741461023e578063115523ad146102765780631df47f8014610290575b600080fd5b34801561021557600080fd5b506102296102243660046135df565b6106e3565b60405190151581526020015b60405180910390f35b34801561024a57600080fd5b5060055461025e906001600160a01b031681565b6040516001600160a01b039091168152602001610235565b34801561028257600080fd5b506004546102299060ff1681565b34801561029c57600080fd5b506102b06102ab366004613409565b61070e565b005b3480156102be57600080fd5b506102e26102cd366004613577565b60009081526002602052604090206001015490565b604051908152602001610235565b3480156102fc57600080fd5b506102b061030b36600461358f565b61076d565b34801561031c57600080fd5b5061022961032b366004613441565b6001600160a01b03919091166000908152600a60209081526040808320938352929052205460ff1690565b34801561036257600080fd5b506102e27f000000000000000000000000000000000000000000000000000000000000000081565b34801561039657600080fd5b506102b06103a536600461358f565b610798565b3480156103b657600080fd5b506102b06103c5366004613678565b61081b565b3480156103d657600080fd5b506102b06103e5366004613678565b610b59565b3480156103f657600080fd5b506102b0610e2b565b34801561040b57600080fd5b506102e261041a366004613409565b60096020526000908152604090205481565b34801561043857600080fd5b5060065461025e906001600160a01b031681565b34801561045857600080fd5b506102b0610467366004613617565b610e42565b34801561047857600080fd5b5060015460ff16610229565b34801561049057600080fd5b506102b061049f366004613409565b611334565b3480156104b057600080fd5b5060085461025e906001600160a01b031681565b3480156104d057600080fd5b5060045461025e9061010090046001600160a01b031681565b3480156104f557600080fd5b506102b06113b1565b34801561050a57600080fd5b5060075461025e906001600160a01b031681565b34801561052a57600080fd5b5061025e6105393660046135be565b6113c5565b34801561054a57600080fd5b5061022961055936600461358f565b6113e4565b34801561056a57600080fd5b506102b061140f565b34801561057f57600080fd5b506102b061058e366004613499565b611430565b34801561059f57600080fd5b506102e2600081565b3480156105b457600080fd5b5061025e7f000000000000000000000000000000000000000000000000000000000000000081565b6102b06105ea366004613678565b611596565b3480156105fb57600080fd5b506102b061060a366004613409565b61194e565b34801561061b57600080fd5b506102e27f1e2c5569f098f7e49e870b02a4d692e6052286f838402c5bec0c17dc6339954681565b34801561064f57600080fd5b506102e261065e366004613577565b6119cb565b34801561066f57600080fd5b506102b061067e366004613577565b6119e2565b34801561068f57600080fd5b506102b061069e366004613409565b611ad4565b3480156106af57600080fd5b506102b06106be36600461358f565b611b51565b3480156106cf57600080fd5b506102b06106de366004613409565b611b77565b60006001600160e01b03198216635a05180f60e01b1480610708575061070882611c8f565b92915050565b600061071a8133611cc4565b60048054610100600160a81b0319166101006001600160a01b038516908102919091179091556040517f8cffb07faa2874440346743bdc0a86b06c3335cc47dc49b327d10e77b73ceb1090600090a25050565b6000828152600260205260409020600101546107898133611cc4565b6107938383611d28565b505050565b6001600160a01b038116331461080d5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6108178282611d4a565b5050565b6002600054141561083e5760405162461bcd60e51b815260040161080490613a99565b60026000556108506020820182613509565b801561086657506108646020830183613509565b155b6108825760405162461bcd60e51b8152600401610804906139ff565b6108926040830160208401613409565b6001600160a01b0316336001600160a01b0316146108c25760405162461bcd60e51b815260040161080490613ad0565b60006108d56108d083613ce1565b611d6c565b90506108e18282611e13565b600080806108f560e0860160c08701613409565b6001600160a01b031663865781ca87876040518363ffffffff1660e01b8152600401610922929190613b72565b60606040518083038186803b15801561093a57600080fd5b505afa15801561094e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109729190613541565b925092509250826109955760405162461bcd60e51b815260040161080490613a62565b6001600a60006109ab6040890160208a01613409565b6001600160a01b03168152602080820192909252604090810160009081206101008a013582529092529020805460ff1916911515919091179055610a3b6109f860e0870160c08801613409565b610a086060880160408901613409565b84610a1a6101008a0160e08b01613409565b33610a2b60408c0160208d01613409565b8c604001358c61016001356121ff565b610a75610a4e6060870160408801613409565b610a5e6040880160208901613409565b610a6e60408a0160208b01613409565b858561241c565b610a8560e0860160c08701613409565b6001600160a01b0316610a9e6040870160208801613409565b6001600160a01b0316610ab76040890160208a01613409565b6001600160a01b03167f95fb6205e23ff6bda16a2d1dba56b9ad7c783f67c96fa149785052f47696f2be876101008a01803590610af79060e08d01613409565b610b0760608d0160408e01613409565b6040805194855260208501939093526001600160a01b03918216848401521660608301526080820188905260a082018790528b013560c082015260e00160405180910390a45050600160005550505050565b60026000541415610b7c5760405162461bcd60e51b815260040161080490613a99565b6002600055610b8e6020820182613509565b158015610ba35750610ba36020830183613509565b610bbf5760405162461bcd60e51b8152600401610804906139ff565b610bcf6040830160208401613409565b6001600160a01b0316336001600160a01b031614610bff5760405162461bcd60e51b815260040161080490613ad0565b6000610c0d6108d083613ce1565b9050610c198282611e13565b60008080610c2d60e0860160c08701613409565b6001600160a01b031663ad2390ac87876040518363ffffffff1660e01b8152600401610c5a929190613b72565b60606040518083038186803b158015610c7257600080fd5b505afa158015610c86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610caa9190613541565b92509250925082610ccd5760405162461bcd60e51b815260040161080490613a62565b6001600a6000610ce36040890160208a01613409565b6001600160a01b03168152602080820192909252604090810160009081206101008a0135825290925290819020805460ff191692151592909217909155610d4590610d349060608801908801613409565b33610a6e6040890160208a01613409565b610da9610d5860e0870160c08801613409565b610d686060880160408901613409565b84610d7a6101008a0160e08b01613409565b610d8a60408b0160208c01613409565b610d9a60408d0160208e01613409565b8c604001358d608001356121ff565b610db960e0860160c08701613409565b6001600160a01b0316610dd26040870160208801613409565b6001600160a01b0316610deb6040890160208a01613409565b6001600160a01b03167f68cd251d4d267c6e2034ff0088b990352b97b2002c0476587d0c4da889c11330876101008a01803590610af79060e08d01613409565b6000610e378133611cc4565b610e3f612587565b50565b60026000541415610e655760405162461bcd60e51b815260040161080490613a99565b600260005560015460ff1615610eb05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610804565b60045460ff161580610ee75750610ee77f1e2c5569f098f7e49e870b02a4d692e6052286f838402c5bec0c17dc63399546336113e4565b610f595760405162461bcd60e51b815260206004820152603760248201527f4d696e74656445786368616e67653a206e6f207065726d697373696f6e20746f60448201527f2063616c6c206d61746368206d616b6572206f726465720000000000000000006064820152608401610804565b610f666020830183613509565b158015610f7b5750610f7b6020820182613509565b610f975760405162461bcd60e51b8152600401610804906139ff565b610fac82610fa76108d082613ce1565b611e13565b610fbc81610fa76108d082613ce1565b610fcc60e0820160c08301613409565b6001600160a01b0316610fe560e0840160c08501613409565b6001600160a01b0316146110455760405162461bcd60e51b815260206004820152602160248201527f4f726465723a20426f7468207374726174656779206d7573742062652073616d6044820152606560f81b6064820152608401610804565b6000808061105960e0850160c08601613409565b6001600160a01b031663fb9c39ec86866040518363ffffffff1660e01b8152600401611086929190613b4d565b60606040518083038186803b15801561109e57600080fd5b505afa1580156110b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d69190613541565b925092509250826110f95760405162461bcd60e51b815260040161080490613a62565b6001600a600061110f6040880160208901613409565b6001600160a01b031681526020808201929092526040908101600090812061010089013582528352818120805460ff191694151594909417909355600192600a92909161116191908a01908a01613409565b6001600160a01b03168152602080820192909252604090810160009081206101008a013582529092529020805460ff19169115159190911790556112006111ae60e0860160c08701613409565b6111be6060870160408801613409565b846111d0610100890160e08a01613409565b6111e060408b0160208c01613409565b6111f060408b0160208c01613409565b8b606001358b61016001356121ff565b6112336112136060860160408701613409565b6112236040870160208801613409565b610a6e6040890160208a01613409565b61124360e0850160c08601613409565b6001600160a01b031661125c6040860160208701613409565b6001600160a01b03166112756040880160208901613409565b6001600160a01b03167f69a5015d8e6e78ecb358feddf51233e089e202439a99989bea48fd58a2415ad06112ab6108d089613ce1565b610100808b0135908a018035906112c59060e08d01613409565b6112d560608d0160408e01613409565b604080519586526020860194909452928401919091526001600160a01b039081166060848101919091529116608083015260a0820188905260c082018790528a013560e08201526101000160405180910390a450506001600055505050565b60006113408133611cc4565b6001600160a01b0382166113665760405162461bcd60e51b815260040161080490613a2b565b600580546001600160a01b0319166001600160a01b0384169081179091556040517fb4f5db40df3aced29e88a4babbc3b46e305e07d34098525d18b1497056e6383890600090a25050565b60006113bd8133611cc4565b610e3f61261a565b60008281526003602052604081206113dd9083612693565b9392505050565b60009182526002602090815260408084206001600160a01b0393909316845291905290205460ff1690565b600061141b8133611cc4565b506004805460ff19811660ff90911615179055565b8061147d5760405162461bcd60e51b815260206004820152601760248201527f43616e63656c3a2043616e6e6f7420626520656d7074790000000000000000006044820152606401610804565b60005b8181101561154e57336000908152600960205260409020548383838181106114b857634e487b7160e01b600052603260045260246000fd5b9050602002013510156114dd5760405162461bcd60e51b815260040161080490613b07565b336000908152600a6020526040812060019185858581811061150f57634e487b7160e01b600052603260045260246000fd5b90506020020135815260200190815260200160002060006101000a81548160ff021916908315150217905550808061154690613e33565b915050611480565b50336001600160a01b03167ffa0ae5d80fe3763c880a3839fab0294171a6f730d1f82c4cd5392c6f67b41732838360405161158a929190613906565b60405180910390a25050565b600260005414156115b95760405162461bcd60e51b815260040161080490613a99565b60026000556115cb6020820182613509565b80156115e157506115df6020830183613509565b155b6115fd5760405162461bcd60e51b8152600401610804906139ff565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016611638610100830160e08401613409565b6001600160a01b03161461168e5760405162461bcd60e51b815260206004820152601c60248201527f4f726465723a2043757272656e6379206d7573742062652057455448000000006044820152606401610804565b61169e6040830160208401613409565b6001600160a01b0316336001600160a01b0316146116ce5760405162461bcd60e51b815260040161080490613ad0565b34826040013511156117245761171f33306116ed346040870135613cca565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692919061269f565b611777565b348260400135146117775760405162461bcd60e51b815260206004820152601960248201527f4f726465723a204d73672e76616c756520746f6f2068696768000000000000006044820152606401610804565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156117d257600080fd5b505af11580156117e6573d6000803e3d6000fd5b505050505060006117fa826108d090613ce1565b90506118068282611e13565b6000808061181a60e0860160c08701613409565b6001600160a01b031663865781ca87876040518363ffffffff1660e01b8152600401611847929190613b72565b60606040518083038186803b15801561185f57600080fd5b505afa158015611873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118979190613541565b925092509250826118ba5760405162461bcd60e51b815260040161080490613a62565b6001600a60006118d06040890160208a01613409565b6001600160a01b03168152602080820192909252604090810160009081206101008a013582529092529020805460ff1916911515919091179055610a3b61191d60e0870160c08801613409565b61192d6060880160408901613409565b8461193e60408a0160208b01613409565b8a604001358a6101600135612710565b600061195a8133611cc4565b6001600160a01b0382166119805760405162461bcd60e51b815260040161080490613a2b565b600780546001600160a01b0319166001600160a01b0384169081179091556040517f80e3874461ebbd918ac3e81da0a92e5e51387d70f337237c9123e48d20e5a50890600090a25050565b6000818152600360205260408120610708906129a6565b336000908152600960205260409020548111611a105760405162461bcd60e51b815260040161080490613b07565b33600090815260096020526040902054611a2d906207a120613c73565b8110611a855760405162461bcd60e51b815260206004820152602160248201527f43616e63656c3a2043616e6e6f742063616e63656c206d6f7265206f726465726044820152607360f81b6064820152608401610804565b3360008181526009602052604090819020839055517f1e7178d84f0b0825c65795cd62e7972809ad3aac6917843aaec596161b2c0a9790611ac99084815260200190565b60405180910390a250565b6000611ae08133611cc4565b6001600160a01b038216611b065760405162461bcd60e51b815260040161080490613a2b565b600680546001600160a01b0319166001600160a01b0384169081179091556040517f36e2a376eabc3bc60cb88f29c288f53e36874a95a7f407330ab4f166b090569890600090a25050565b600082815260026020526040902060010154611b6d8133611cc4565b6107938383611d4a565b6000611b838133611cc4565b6001600160a01b038216611ba95760405162461bcd60e51b815260040161080490613a2b565b600880546001600160a01b0319166001600160a01b0384169081179091556040517f205d78ab41afe80bd6b6aaa5d7599d5300ff8690da3ab1302c1b552f7baf7d8c90600090a25050565b611bfe82826113e4565b6108175760008281526002602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611c363390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006113dd836001600160a01b0384166129b0565b60006001600160e01b03198216637965db0b60e01b148061070857506301ffc9a760e01b6001600160e01b0319831614610708565b611cce82826113e4565b61081757611ce6816001600160a01b031660146129ff565b611cf18360206129ff565b604051602001611d02929190613891565b60408051601f198184030181529082905262461bcd60e51b8252610804916004016139ec565b611d328282611bf4565b60008281526003602052604090206107939082611c7a565b611d548282612be1565b60008281526003602052604090206107939082612c48565b80516020808301516040808501516060860151608087015160a088015160c089015160e08a01516101008b01516101208c01516101408d01516101608e01516101808f01518051908e01209a5160009e611df69e7f40261ade532fa1d2c7293df30aaadb9b3c616fae525a0b56d3d411c841a850289e919d919c9b9a999897969594939201613940565b604051602081830303815290604052805190602001209050919050565b600a6000611e276040850160208601613409565b6001600160a01b0316815260208082019290925260409081016000908120610100860135825290925290205460ff16158015611e9c575060096000611e726040850160208601613409565b6001600160a01b03166001600160a01b031681526020019081526020016000205482610100013510155b611ee85760405162461bcd60e51b815260206004820152601d60248201527f4f726465723a204d61746368696e67206f7264657220657870697265640000006044820152606401610804565b6000611efa6040840160208501613409565b6001600160a01b03161415611f495760405162461bcd60e51b815260206004820152601560248201527427b93232b91d1024b73b30b634b21039b4b3b732b960591b6044820152606401610804565b60008260a0013511611f9d5760405162461bcd60e51b815260206004820152601960248201527f4f726465723a20416d6f756e742063616e6e6f742062652030000000000000006044820152606401610804565b611ff581611fb16040850160208601613409565b611fc36101c086016101a087016136e1565b856101c00135866101e001357f0000000000000000000000000000000000000000000000000000000000000000612c5d565b6120365760405162461bcd60e51b815260206004820152601260248201527114da59db985d1d5c994e88125b9d985b1a5960721b6044820152606401610804565b6005546001600160a01b03166343b938c5612058610100850160e08601613409565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b15801561209757600080fd5b505afa1580156120ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cf9190613525565b61211b5760405162461bcd60e51b815260206004820152601960248201527f43757272656e63793a204e6f742077686974656c6973746564000000000000006044820152606401610804565b6006546001600160a01b031663999ba27c61213c60e0850160c08601613409565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b15801561217b57600080fd5b505afa15801561218f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b39190613525565b6108175760405162461bcd60e51b815260206004820152601960248201527f53747261746567793a204e6f742077686974656c6973746564000000000000006044820152606401610804565b81600061220c8a83612dab565b60045490915061010090046001600160a01b03161580159061222d57508015155b1561226157600454612254906001600160a01b03898116918991610100909104168461269f565b61225e8183613cca565b91505b50600754604051637a7b1afd60e11b81526001600160a01b038a81166004830152602482018a905260448201869052600092839291169063f4f635fa90606401604080518083038186803b1580156122b857600080fd5b505afa1580156122cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f0919061346c565b90925090506001600160a01b0382161580159061230c57508015155b15612395576123266001600160a01b03891688848461269f565b6123308184613cca565b9250816001600160a01b0316898b6001600160a01b03167f27c4f0403323142b599832f26acd21c74a9e5b809f2215726e244a4ac588cd7d8b8560405161238c9291906001600160a01b03929092168252602082015260400190565b60405180910390a45b506123a290508383613cab565b6123ae82612710613cab565b10156123fc5760405162461bcd60e51b815260206004820152601a60248201527f466565733a20486967686572207468616e2065787065637465640000000000006044820152606401610804565b6124116001600160a01b03871686868461269f565b505050505050505050565b60085460405163cc15949360e01b81526001600160a01b038781166004830152600092169063cc1594939060240160206040518083038186803b15801561246257600080fd5b505afa158015612476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249a9190613425565b90506001600160a01b0381166125065760405162461bcd60e51b815260206004820152602b60248201527f5472616e736665723a204e6f204e4654207472616e73666572206d616e61676560448201526a7220617661696c61626c6560a81b6064820152608401610804565b6040516333f2fa9f60e01b81526001600160a01b0387811660048301528681166024830152858116604483015260648201859052608482018490528216906333f2fa9f9060a401600060405180830381600087803b15801561256757600080fd5b505af115801561257b573d6000803e3d6000fd5b50505050505050505050565b60015460ff166125d05760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610804565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60015460ff16156126605760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610804565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336125fd565b60006113dd8383612e40565b6040516001600160a01b038085166024830152831660448201526064810182905261270a9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612e78565b50505050565b81600061271d8883612dab565b60045490915061010090046001600160a01b03161580159061273e57508015155b1561278f57600454612782906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169161010090041683612f4a565b61278c8183613cca565b91505b50600754604051637a7b1afd60e11b81526001600160a01b0388811660048301526024820188905260448201869052600092839291169063f4f635fa90606401604080518083038186803b1580156127e657600080fd5b505afa1580156127fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281e919061346c565b90925090506001600160a01b0382161580159061283a57508015155b15612902576128736001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383612f4a565b61287d8184613cca565b9250816001600160a01b031687896001600160a01b03167f27c4f0403323142b599832f26acd21c74a9e5b809f2215726e244a4ac588cd7d7f0000000000000000000000000000000000000000000000000000000000000000856040516128f99291906001600160a01b03929092168252602082015260400190565b60405180910390a45b5061290f90508383613cab565b61291b82612710613cab565b10156129695760405162461bcd60e51b815260206004820152601a60248201527f466565733a20486967686572207468616e2065787065637465640000000000006044820152606401610804565b61299d6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168583612f4a565b50505050505050565b6000610708825490565b60008181526001830160205260408120546129f757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610708565b506000610708565b60606000612a0e836002613cab565b612a19906002613c73565b67ffffffffffffffff811115612a3f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612a69576020820181803683370190505b509050600360fc1b81600081518110612a9257634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612acf57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000612af3846002613cab565b612afe906001613c73565b90505b6001811115612b92576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612b4057634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110612b6457634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93612b8b81613e1c565b9050612b01565b5083156113dd5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610804565b612beb82826113e4565b156108175760008281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006113dd836001600160a01b038416612f7a565b60405161190160f01b602082015260228101829052604281018790526000908190606201604051602081830303815290604052805190602001209050612cac876001600160a01b03163b151590565b15612d7d57604080516020810187905280820186905260f888901b6001600160f81b0319166060820152815160418183030181526061820192839052630b135d3f60e11b9092526001600160a01b03891691631626ba7e91612d129185916065016139d3565b60206040518083038186803b158015612d2a57600080fd5b505afa158015612d3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6291906135fb565b6001600160e01b031916631626ba7e60e01b14915050612da1565b866001600160a01b0316612d9382888888613097565b6001600160a01b0316149150505b9695505050505050565b600080836001600160a01b0316639dd1cda66040518163ffffffff1660e01b815260040160206040518083038186803b158015612de757600080fd5b505afa158015612dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1f91906136c9565b9050612710612e2e8483613cab565b612e389190613c8b565b949350505050565b6000826000018281548110612e6557634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b6000612ecd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661322a9092919063ffffffff16565b8051909150156107935780806020019051810190612eeb9190613525565b6107935760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610804565b6040516001600160a01b03831660248201526044810182905261079390849063a9059cbb60e01b906064016126d3565b6000818152600183016020526040812054801561308d576000612f9e600183613cca565b8554909150600090612fb290600190613cca565b9050818114613033576000866000018281548110612fe057634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061301157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061305257634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610708565b6000915050610708565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156131095760405162461bcd60e51b815260206004820152601e60248201527f5369676e61747572653a20496e76616c6964207320706172616d6574657200006044820152606401610804565b8360ff16601b148061311e57508360ff16601c145b61316a5760405162461bcd60e51b815260206004820152601e60248201527f5369676e61747572653a20496e76616c6964207620706172616d6574657200006044820152606401610804565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156131be573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166132215760405162461bcd60e51b815260206004820152601960248201527f5369676e61747572653a20496e76616c6964207369676e6572000000000000006044820152606401610804565b95945050505050565b6060612e388484600085856001600160a01b0385163b61328c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610804565b600080866001600160a01b031685876040516132a89190613875565b60006040518083038185875af1925050503d80600081146132e5576040519150601f19603f3d011682016040523d82523d6000602084013e6132ea565b606091505b50915091506132fa828286613305565b979650505050505050565b606083156133145750816113dd565b8251156133245782518084602001fd5b8160405162461bcd60e51b815260040161080491906139ec565b803561334981613e7a565b919050565b803561334981613e8f565b600082601f830112613369578081fd5b813567ffffffffffffffff8082111561338457613384613e64565b604051601f8301601f19908116603f011681019082821181831017156133ac576133ac613e64565b816040528381528660208588010111156133c4578485fd5b8360208701602083013792830160200193909352509392505050565b600061020082840312156133f2578081fd5b50919050565b803560ff8116811461334957600080fd5b60006020828403121561341a578081fd5b81356113dd81613e7a565b600060208284031215613436578081fd5b81516113dd81613e7a565b60008060408385031215613453578081fd5b823561345e81613e7a565b946020939093013593505050565b6000806040838503121561347e578182fd5b825161348981613e7a565b6020939093015192949293505050565b600080602083850312156134ab578182fd5b823567ffffffffffffffff808211156134c2578384fd5b818501915085601f8301126134d5578384fd5b8135818111156134e3578485fd5b8660208260051b85010111156134f7578485fd5b60209290920196919550909350505050565b60006020828403121561351a578081fd5b81356113dd81613e8f565b600060208284031215613536578081fd5b81516113dd81613e8f565b600080600060608486031215613555578081fd5b835161356081613e8f565b602085015160409095015190969495509392505050565b600060208284031215613588578081fd5b5035919050565b600080604083850312156135a1578182fd5b8235915060208301356135b381613e7a565b809150509250929050565b600080604083850312156135d0578182fd5b50508035926020909101359150565b6000602082840312156135f0578081fd5b81356113dd81613e9d565b60006020828403121561360c578081fd5b81516113dd81613e9d565b60008060408385031215613629578182fd5b823567ffffffffffffffff80821115613640578384fd5b61364c868387016133e0565b93506020850135915080821115613661578283fd5b5061366e858286016133e0565b9150509250929050565b6000806040838503121561368a578182fd5b823567ffffffffffffffff808211156136a1578384fd5b9084019060c082870312156136b4578384fd5b90925060208401359080821115613661578283fd5b6000602082840312156136da578081fd5b5051919050565b6000602082840312156136f2578081fd5b6113dd826133f8565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000815180845261373c816020860160208601613df0565b601f01601f19169290920160200192915050565b6000610200613768846137628561334e565b15159052565b6137746020840161333e565b6001600160a01b0316602085015261378e6040840161333e565b6001600160a01b038116604086015250606083013560608501526080830135608085015260a083013560a08501526137c860c0840161333e565b6001600160a01b031660c08501526137e260e0840161333e565b6001600160a01b031660e0850152610100838101359085015261012080840135908501526101408084013590850152610160808401359085015261018061382b81850185613c27565b838388015261383d84880182846136fb565b93505050506101a06138508185016133f8565b60ff16908501526101c083810135908501526101e09283013592909301919091525090565b60008251613887818460208701613df0565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516138c9816017850160208801613df0565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516138fa816028840160208801613df0565b01602801949350505050565b6020808252810182905260006001600160fb1b03831115613925578081fd5b8260051b808560408501379190910160400190815292915050565b8e81528d151560208201526001600160a01b038d811660408301528c1660608201526101c081018b60808301528a60a08301528960c083015261398e60e083018a6001600160a01b03169052565b6001600160a01b0388166101008301526101208201969096526101408101949094526101608401929092526101808301526101a0909101529998505050505050505050565b828152604060208201526000612e386040830184613724565b6020815260006113dd6020830184613724565b6020808252601290820152714f726465723a2057726f6e6720736964657360701b604082015260600190565b6020808252601d908201527f4f776e65723a2043616e6e6f74206265206e756c6c2061646472657373000000604082015260600190565b6020808252601b908201527f53747261746567793a20457865637574696f6e20696e76616c69640000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601f908201527f4f726465723a2054616b6572206d757374206265207468652073656e64657200604082015260600190565b60208082526026908201527f43616e63656c3a204f72646572206e6f6e6365206c6f776572207468616e20636040820152651d5c9c995b9d60d21b606082015260800190565b604081526000613b606040830185613750565b82810360208401526132218185613750565b6040815260008335613b8381613e8f565b151560408301526020840135613b9881613e7a565b60018060a01b03811660608401525060408401356080830152606084013560a0830152608084013560c0830152613bd260a0850185613c27565b60c060e0850152613be8610100850182846136fb565b91505082810360208401526132218185613750565b604051610200810167ffffffffffffffff81118282101715613c2157613c21613e64565b60405290565b6000808335601e19843603018112613c3d578283fd5b830160208101925035905067ffffffffffffffff811115613c5d57600080fd5b803603831315613c6c57600080fd5b9250929050565b60008219821115613c8657613c86613e4e565b500190565b600082613ca657634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615613cc557613cc5613e4e565b500290565b600082821015613cdc57613cdc613e4e565b500390565b60006102008236031215613cf3578081fd5b613cfb613bfd565b613d048361334e565b8152613d126020840161333e565b6020820152613d236040840161333e565b6040820152606083013560608201526080830135608082015260a083013560a0820152613d5260c0840161333e565b60c0820152613d6360e0840161333e565b60e082015261010083810135908201526101208084013590820152610140808401359082015261016080840135908201526101808084013567ffffffffffffffff811115613daf578384fd5b613dbb36828701613359565b8284015250506101a0613dcf8185016133f8565b908201526101c083810135908201526101e092830135928101929092525090565b60005b83811015613e0b578181015183820152602001613df3565b8381111561270a5750506000910152565b600081613e2b57613e2b613e4e565b506000190190565b6000600019821415613e4757613e47613e4e565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610e3f57600080fd5b8015158114610e3f57600080fd5b6001600160e01b031981168114610e3f57600080fdfea2646970667358221220cf30d0871f4b5ac52655851e843dcf3609a97c9d9a3235da3992e4aa9a47d2e264736f6c6343000804003300000000000000000000000045eb210f33583022c7f9bf981bb3569eeba0f77e00000000000000000000000036766780336e393e10bb4fd6b5ed36ef29a4f86700000000000000000000000055091b45e4a1bb494c52191323269c3a03893be70000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae23000000000000000000000000a16226396d79dc7b3bc70de0daca4eef11742a9e
Deployed Bytecode
0x6080604052600436106102045760003560e01c80635e14f68e11610118578063ad5c4648116100a0578063ca15c8731161006f578063ca15c87314610643578063cbd2ec6514610663578063d4ff41dc14610683578063d547741f146106a3578063f75ff53f146106c357600080fd5b8063ad5c4648146105a8578063b4e4b296146105dc578063c5498769146105ef578063c808367f1461060f57600080fd5b80639010d07c116100e75780639010d07c1461051e57806391d148541461053e578063978cb4ad1461055e5780639e53a69a14610573578063a217fddf1461059357600080fd5b80635e14f68e146104a457806364df049e146104c45780638456cb59146104e957806387e4401f146104fe57600080fd5b806336568abe1161019b5780634266581e1161016a5780634266581e146103ff578063483abb9f1461042c578063503b65f11461044c5780635c975abb1461046c5780635ce052d71461048457600080fd5b806336568abe1461038a57806338e29209146103aa5780633b6d032e146103ca5780633f4ba83a146103ea57600080fd5b8063248a9ca3116101d7578063248a9ca3146102b25780632f2ff15d146102f057806331e27e27146103105780633644e5151461035657600080fd5b806301ffc9a7146102095780630f747d741461023e578063115523ad146102765780631df47f8014610290575b600080fd5b34801561021557600080fd5b506102296102243660046135df565b6106e3565b60405190151581526020015b60405180910390f35b34801561024a57600080fd5b5060055461025e906001600160a01b031681565b6040516001600160a01b039091168152602001610235565b34801561028257600080fd5b506004546102299060ff1681565b34801561029c57600080fd5b506102b06102ab366004613409565b61070e565b005b3480156102be57600080fd5b506102e26102cd366004613577565b60009081526002602052604090206001015490565b604051908152602001610235565b3480156102fc57600080fd5b506102b061030b36600461358f565b61076d565b34801561031c57600080fd5b5061022961032b366004613441565b6001600160a01b03919091166000908152600a60209081526040808320938352929052205460ff1690565b34801561036257600080fd5b506102e27f60aca2186c2e5b82cf7b43e39c12bdef6429513f48404925fb1181ff4bb2c9b381565b34801561039657600080fd5b506102b06103a536600461358f565b610798565b3480156103b657600080fd5b506102b06103c5366004613678565b61081b565b3480156103d657600080fd5b506102b06103e5366004613678565b610b59565b3480156103f657600080fd5b506102b0610e2b565b34801561040b57600080fd5b506102e261041a366004613409565b60096020526000908152604090205481565b34801561043857600080fd5b5060065461025e906001600160a01b031681565b34801561045857600080fd5b506102b0610467366004613617565b610e42565b34801561047857600080fd5b5060015460ff16610229565b34801561049057600080fd5b506102b061049f366004613409565b611334565b3480156104b057600080fd5b5060085461025e906001600160a01b031681565b3480156104d057600080fd5b5060045461025e9061010090046001600160a01b031681565b3480156104f557600080fd5b506102b06113b1565b34801561050a57600080fd5b5060075461025e906001600160a01b031681565b34801561052a57600080fd5b5061025e6105393660046135be565b6113c5565b34801561054a57600080fd5b5061022961055936600461358f565b6113e4565b34801561056a57600080fd5b506102b061140f565b34801561057f57600080fd5b506102b061058e366004613499565b611430565b34801561059f57600080fd5b506102e2600081565b3480156105b457600080fd5b5061025e7f0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae2381565b6102b06105ea366004613678565b611596565b3480156105fb57600080fd5b506102b061060a366004613409565b61194e565b34801561061b57600080fd5b506102e27f1e2c5569f098f7e49e870b02a4d692e6052286f838402c5bec0c17dc6339954681565b34801561064f57600080fd5b506102e261065e366004613577565b6119cb565b34801561066f57600080fd5b506102b061067e366004613577565b6119e2565b34801561068f57600080fd5b506102b061069e366004613409565b611ad4565b3480156106af57600080fd5b506102b06106be36600461358f565b611b51565b3480156106cf57600080fd5b506102b06106de366004613409565b611b77565b60006001600160e01b03198216635a05180f60e01b1480610708575061070882611c8f565b92915050565b600061071a8133611cc4565b60048054610100600160a81b0319166101006001600160a01b038516908102919091179091556040517f8cffb07faa2874440346743bdc0a86b06c3335cc47dc49b327d10e77b73ceb1090600090a25050565b6000828152600260205260409020600101546107898133611cc4565b6107938383611d28565b505050565b6001600160a01b038116331461080d5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6108178282611d4a565b5050565b6002600054141561083e5760405162461bcd60e51b815260040161080490613a99565b60026000556108506020820182613509565b801561086657506108646020830183613509565b155b6108825760405162461bcd60e51b8152600401610804906139ff565b6108926040830160208401613409565b6001600160a01b0316336001600160a01b0316146108c25760405162461bcd60e51b815260040161080490613ad0565b60006108d56108d083613ce1565b611d6c565b90506108e18282611e13565b600080806108f560e0860160c08701613409565b6001600160a01b031663865781ca87876040518363ffffffff1660e01b8152600401610922929190613b72565b60606040518083038186803b15801561093a57600080fd5b505afa15801561094e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109729190613541565b925092509250826109955760405162461bcd60e51b815260040161080490613a62565b6001600a60006109ab6040890160208a01613409565b6001600160a01b03168152602080820192909252604090810160009081206101008a013582529092529020805460ff1916911515919091179055610a3b6109f860e0870160c08801613409565b610a086060880160408901613409565b84610a1a6101008a0160e08b01613409565b33610a2b60408c0160208d01613409565b8c604001358c61016001356121ff565b610a75610a4e6060870160408801613409565b610a5e6040880160208901613409565b610a6e60408a0160208b01613409565b858561241c565b610a8560e0860160c08701613409565b6001600160a01b0316610a9e6040870160208801613409565b6001600160a01b0316610ab76040890160208a01613409565b6001600160a01b03167f95fb6205e23ff6bda16a2d1dba56b9ad7c783f67c96fa149785052f47696f2be876101008a01803590610af79060e08d01613409565b610b0760608d0160408e01613409565b6040805194855260208501939093526001600160a01b03918216848401521660608301526080820188905260a082018790528b013560c082015260e00160405180910390a45050600160005550505050565b60026000541415610b7c5760405162461bcd60e51b815260040161080490613a99565b6002600055610b8e6020820182613509565b158015610ba35750610ba36020830183613509565b610bbf5760405162461bcd60e51b8152600401610804906139ff565b610bcf6040830160208401613409565b6001600160a01b0316336001600160a01b031614610bff5760405162461bcd60e51b815260040161080490613ad0565b6000610c0d6108d083613ce1565b9050610c198282611e13565b60008080610c2d60e0860160c08701613409565b6001600160a01b031663ad2390ac87876040518363ffffffff1660e01b8152600401610c5a929190613b72565b60606040518083038186803b158015610c7257600080fd5b505afa158015610c86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610caa9190613541565b92509250925082610ccd5760405162461bcd60e51b815260040161080490613a62565b6001600a6000610ce36040890160208a01613409565b6001600160a01b03168152602080820192909252604090810160009081206101008a0135825290925290819020805460ff191692151592909217909155610d4590610d349060608801908801613409565b33610a6e6040890160208a01613409565b610da9610d5860e0870160c08801613409565b610d686060880160408901613409565b84610d7a6101008a0160e08b01613409565b610d8a60408b0160208c01613409565b610d9a60408d0160208e01613409565b8c604001358d608001356121ff565b610db960e0860160c08701613409565b6001600160a01b0316610dd26040870160208801613409565b6001600160a01b0316610deb6040890160208a01613409565b6001600160a01b03167f68cd251d4d267c6e2034ff0088b990352b97b2002c0476587d0c4da889c11330876101008a01803590610af79060e08d01613409565b6000610e378133611cc4565b610e3f612587565b50565b60026000541415610e655760405162461bcd60e51b815260040161080490613a99565b600260005560015460ff1615610eb05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610804565b60045460ff161580610ee75750610ee77f1e2c5569f098f7e49e870b02a4d692e6052286f838402c5bec0c17dc63399546336113e4565b610f595760405162461bcd60e51b815260206004820152603760248201527f4d696e74656445786368616e67653a206e6f207065726d697373696f6e20746f60448201527f2063616c6c206d61746368206d616b6572206f726465720000000000000000006064820152608401610804565b610f666020830183613509565b158015610f7b5750610f7b6020820182613509565b610f975760405162461bcd60e51b8152600401610804906139ff565b610fac82610fa76108d082613ce1565b611e13565b610fbc81610fa76108d082613ce1565b610fcc60e0820160c08301613409565b6001600160a01b0316610fe560e0840160c08501613409565b6001600160a01b0316146110455760405162461bcd60e51b815260206004820152602160248201527f4f726465723a20426f7468207374726174656779206d7573742062652073616d6044820152606560f81b6064820152608401610804565b6000808061105960e0850160c08601613409565b6001600160a01b031663fb9c39ec86866040518363ffffffff1660e01b8152600401611086929190613b4d565b60606040518083038186803b15801561109e57600080fd5b505afa1580156110b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d69190613541565b925092509250826110f95760405162461bcd60e51b815260040161080490613a62565b6001600a600061110f6040880160208901613409565b6001600160a01b031681526020808201929092526040908101600090812061010089013582528352818120805460ff191694151594909417909355600192600a92909161116191908a01908a01613409565b6001600160a01b03168152602080820192909252604090810160009081206101008a013582529092529020805460ff19169115159190911790556112006111ae60e0860160c08701613409565b6111be6060870160408801613409565b846111d0610100890160e08a01613409565b6111e060408b0160208c01613409565b6111f060408b0160208c01613409565b8b606001358b61016001356121ff565b6112336112136060860160408701613409565b6112236040870160208801613409565b610a6e6040890160208a01613409565b61124360e0850160c08601613409565b6001600160a01b031661125c6040860160208701613409565b6001600160a01b03166112756040880160208901613409565b6001600160a01b03167f69a5015d8e6e78ecb358feddf51233e089e202439a99989bea48fd58a2415ad06112ab6108d089613ce1565b610100808b0135908a018035906112c59060e08d01613409565b6112d560608d0160408e01613409565b604080519586526020860194909452928401919091526001600160a01b039081166060848101919091529116608083015260a0820188905260c082018790528a013560e08201526101000160405180910390a450506001600055505050565b60006113408133611cc4565b6001600160a01b0382166113665760405162461bcd60e51b815260040161080490613a2b565b600580546001600160a01b0319166001600160a01b0384169081179091556040517fb4f5db40df3aced29e88a4babbc3b46e305e07d34098525d18b1497056e6383890600090a25050565b60006113bd8133611cc4565b610e3f61261a565b60008281526003602052604081206113dd9083612693565b9392505050565b60009182526002602090815260408084206001600160a01b0393909316845291905290205460ff1690565b600061141b8133611cc4565b506004805460ff19811660ff90911615179055565b8061147d5760405162461bcd60e51b815260206004820152601760248201527f43616e63656c3a2043616e6e6f7420626520656d7074790000000000000000006044820152606401610804565b60005b8181101561154e57336000908152600960205260409020548383838181106114b857634e487b7160e01b600052603260045260246000fd5b9050602002013510156114dd5760405162461bcd60e51b815260040161080490613b07565b336000908152600a6020526040812060019185858581811061150f57634e487b7160e01b600052603260045260246000fd5b90506020020135815260200190815260200160002060006101000a81548160ff021916908315150217905550808061154690613e33565b915050611480565b50336001600160a01b03167ffa0ae5d80fe3763c880a3839fab0294171a6f730d1f82c4cd5392c6f67b41732838360405161158a929190613906565b60405180910390a25050565b600260005414156115b95760405162461bcd60e51b815260040161080490613a99565b60026000556115cb6020820182613509565b80156115e157506115df6020830183613509565b155b6115fd5760405162461bcd60e51b8152600401610804906139ff565b6001600160a01b037f0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae2316611638610100830160e08401613409565b6001600160a01b03161461168e5760405162461bcd60e51b815260206004820152601c60248201527f4f726465723a2043757272656e6379206d7573742062652057455448000000006044820152606401610804565b61169e6040830160208401613409565b6001600160a01b0316336001600160a01b0316146116ce5760405162461bcd60e51b815260040161080490613ad0565b34826040013511156117245761171f33306116ed346040870135613cca565b6001600160a01b037f0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae231692919061269f565b611777565b348260400135146117775760405162461bcd60e51b815260206004820152601960248201527f4f726465723a204d73672e76616c756520746f6f2068696768000000000000006044820152606401610804565b7f0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae236001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156117d257600080fd5b505af11580156117e6573d6000803e3d6000fd5b505050505060006117fa826108d090613ce1565b90506118068282611e13565b6000808061181a60e0860160c08701613409565b6001600160a01b031663865781ca87876040518363ffffffff1660e01b8152600401611847929190613b72565b60606040518083038186803b15801561185f57600080fd5b505afa158015611873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118979190613541565b925092509250826118ba5760405162461bcd60e51b815260040161080490613a62565b6001600a60006118d06040890160208a01613409565b6001600160a01b03168152602080820192909252604090810160009081206101008a013582529092529020805460ff1916911515919091179055610a3b61191d60e0870160c08801613409565b61192d6060880160408901613409565b8461193e60408a0160208b01613409565b8a604001358a6101600135612710565b600061195a8133611cc4565b6001600160a01b0382166119805760405162461bcd60e51b815260040161080490613a2b565b600780546001600160a01b0319166001600160a01b0384169081179091556040517f80e3874461ebbd918ac3e81da0a92e5e51387d70f337237c9123e48d20e5a50890600090a25050565b6000818152600360205260408120610708906129a6565b336000908152600960205260409020548111611a105760405162461bcd60e51b815260040161080490613b07565b33600090815260096020526040902054611a2d906207a120613c73565b8110611a855760405162461bcd60e51b815260206004820152602160248201527f43616e63656c3a2043616e6e6f742063616e63656c206d6f7265206f726465726044820152607360f81b6064820152608401610804565b3360008181526009602052604090819020839055517f1e7178d84f0b0825c65795cd62e7972809ad3aac6917843aaec596161b2c0a9790611ac99084815260200190565b60405180910390a250565b6000611ae08133611cc4565b6001600160a01b038216611b065760405162461bcd60e51b815260040161080490613a2b565b600680546001600160a01b0319166001600160a01b0384169081179091556040517f36e2a376eabc3bc60cb88f29c288f53e36874a95a7f407330ab4f166b090569890600090a25050565b600082815260026020526040902060010154611b6d8133611cc4565b6107938383611d4a565b6000611b838133611cc4565b6001600160a01b038216611ba95760405162461bcd60e51b815260040161080490613a2b565b600880546001600160a01b0319166001600160a01b0384169081179091556040517f205d78ab41afe80bd6b6aaa5d7599d5300ff8690da3ab1302c1b552f7baf7d8c90600090a25050565b611bfe82826113e4565b6108175760008281526002602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611c363390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006113dd836001600160a01b0384166129b0565b60006001600160e01b03198216637965db0b60e01b148061070857506301ffc9a760e01b6001600160e01b0319831614610708565b611cce82826113e4565b61081757611ce6816001600160a01b031660146129ff565b611cf18360206129ff565b604051602001611d02929190613891565b60408051601f198184030181529082905262461bcd60e51b8252610804916004016139ec565b611d328282611bf4565b60008281526003602052604090206107939082611c7a565b611d548282612be1565b60008281526003602052604090206107939082612c48565b80516020808301516040808501516060860151608087015160a088015160c089015160e08a01516101008b01516101208c01516101408d01516101608e01516101808f01518051908e01209a5160009e611df69e7f40261ade532fa1d2c7293df30aaadb9b3c616fae525a0b56d3d411c841a850289e919d919c9b9a999897969594939201613940565b604051602081830303815290604052805190602001209050919050565b600a6000611e276040850160208601613409565b6001600160a01b0316815260208082019290925260409081016000908120610100860135825290925290205460ff16158015611e9c575060096000611e726040850160208601613409565b6001600160a01b03166001600160a01b031681526020019081526020016000205482610100013510155b611ee85760405162461bcd60e51b815260206004820152601d60248201527f4f726465723a204d61746368696e67206f7264657220657870697265640000006044820152606401610804565b6000611efa6040840160208501613409565b6001600160a01b03161415611f495760405162461bcd60e51b815260206004820152601560248201527427b93232b91d1024b73b30b634b21039b4b3b732b960591b6044820152606401610804565b60008260a0013511611f9d5760405162461bcd60e51b815260206004820152601960248201527f4f726465723a20416d6f756e742063616e6e6f742062652030000000000000006044820152606401610804565b611ff581611fb16040850160208601613409565b611fc36101c086016101a087016136e1565b856101c00135866101e001357f60aca2186c2e5b82cf7b43e39c12bdef6429513f48404925fb1181ff4bb2c9b3612c5d565b6120365760405162461bcd60e51b815260206004820152601260248201527114da59db985d1d5c994e88125b9d985b1a5960721b6044820152606401610804565b6005546001600160a01b03166343b938c5612058610100850160e08601613409565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b15801561209757600080fd5b505afa1580156120ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cf9190613525565b61211b5760405162461bcd60e51b815260206004820152601960248201527f43757272656e63793a204e6f742077686974656c6973746564000000000000006044820152606401610804565b6006546001600160a01b031663999ba27c61213c60e0850160c08601613409565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b15801561217b57600080fd5b505afa15801561218f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b39190613525565b6108175760405162461bcd60e51b815260206004820152601960248201527f53747261746567793a204e6f742077686974656c6973746564000000000000006044820152606401610804565b81600061220c8a83612dab565b60045490915061010090046001600160a01b03161580159061222d57508015155b1561226157600454612254906001600160a01b03898116918991610100909104168461269f565b61225e8183613cca565b91505b50600754604051637a7b1afd60e11b81526001600160a01b038a81166004830152602482018a905260448201869052600092839291169063f4f635fa90606401604080518083038186803b1580156122b857600080fd5b505afa1580156122cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f0919061346c565b90925090506001600160a01b0382161580159061230c57508015155b15612395576123266001600160a01b03891688848461269f565b6123308184613cca565b9250816001600160a01b0316898b6001600160a01b03167f27c4f0403323142b599832f26acd21c74a9e5b809f2215726e244a4ac588cd7d8b8560405161238c9291906001600160a01b03929092168252602082015260400190565b60405180910390a45b506123a290508383613cab565b6123ae82612710613cab565b10156123fc5760405162461bcd60e51b815260206004820152601a60248201527f466565733a20486967686572207468616e2065787065637465640000000000006044820152606401610804565b6124116001600160a01b03871686868461269f565b505050505050505050565b60085460405163cc15949360e01b81526001600160a01b038781166004830152600092169063cc1594939060240160206040518083038186803b15801561246257600080fd5b505afa158015612476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249a9190613425565b90506001600160a01b0381166125065760405162461bcd60e51b815260206004820152602b60248201527f5472616e736665723a204e6f204e4654207472616e73666572206d616e61676560448201526a7220617661696c61626c6560a81b6064820152608401610804565b6040516333f2fa9f60e01b81526001600160a01b0387811660048301528681166024830152858116604483015260648201859052608482018490528216906333f2fa9f9060a401600060405180830381600087803b15801561256757600080fd5b505af115801561257b573d6000803e3d6000fd5b50505050505050505050565b60015460ff166125d05760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610804565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60015460ff16156126605760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610804565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336125fd565b60006113dd8383612e40565b6040516001600160a01b038085166024830152831660448201526064810182905261270a9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612e78565b50505050565b81600061271d8883612dab565b60045490915061010090046001600160a01b03161580159061273e57508015155b1561278f57600454612782906001600160a01b037f0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae2381169161010090041683612f4a565b61278c8183613cca565b91505b50600754604051637a7b1afd60e11b81526001600160a01b0388811660048301526024820188905260448201869052600092839291169063f4f635fa90606401604080518083038186803b1580156127e657600080fd5b505afa1580156127fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281e919061346c565b90925090506001600160a01b0382161580159061283a57508015155b15612902576128736001600160a01b037f0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae23168383612f4a565b61287d8184613cca565b9250816001600160a01b031687896001600160a01b03167f27c4f0403323142b599832f26acd21c74a9e5b809f2215726e244a4ac588cd7d7f0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae23856040516128f99291906001600160a01b03929092168252602082015260400190565b60405180910390a45b5061290f90508383613cab565b61291b82612710613cab565b10156129695760405162461bcd60e51b815260206004820152601a60248201527f466565733a20486967686572207468616e2065787065637465640000000000006044820152606401610804565b61299d6001600160a01b037f0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae23168583612f4a565b50505050505050565b6000610708825490565b60008181526001830160205260408120546129f757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610708565b506000610708565b60606000612a0e836002613cab565b612a19906002613c73565b67ffffffffffffffff811115612a3f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612a69576020820181803683370190505b509050600360fc1b81600081518110612a9257634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612acf57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000612af3846002613cab565b612afe906001613c73565b90505b6001811115612b92576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612b4057634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110612b6457634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93612b8b81613e1c565b9050612b01565b5083156113dd5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610804565b612beb82826113e4565b156108175760008281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006113dd836001600160a01b038416612f7a565b60405161190160f01b602082015260228101829052604281018790526000908190606201604051602081830303815290604052805190602001209050612cac876001600160a01b03163b151590565b15612d7d57604080516020810187905280820186905260f888901b6001600160f81b0319166060820152815160418183030181526061820192839052630b135d3f60e11b9092526001600160a01b03891691631626ba7e91612d129185916065016139d3565b60206040518083038186803b158015612d2a57600080fd5b505afa158015612d3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6291906135fb565b6001600160e01b031916631626ba7e60e01b14915050612da1565b866001600160a01b0316612d9382888888613097565b6001600160a01b0316149150505b9695505050505050565b600080836001600160a01b0316639dd1cda66040518163ffffffff1660e01b815260040160206040518083038186803b158015612de757600080fd5b505afa158015612dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1f91906136c9565b9050612710612e2e8483613cab565b612e389190613c8b565b949350505050565b6000826000018281548110612e6557634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b6000612ecd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661322a9092919063ffffffff16565b8051909150156107935780806020019051810190612eeb9190613525565b6107935760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610804565b6040516001600160a01b03831660248201526044810182905261079390849063a9059cbb60e01b906064016126d3565b6000818152600183016020526040812054801561308d576000612f9e600183613cca565b8554909150600090612fb290600190613cca565b9050818114613033576000866000018281548110612fe057634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061301157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061305257634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610708565b6000915050610708565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156131095760405162461bcd60e51b815260206004820152601e60248201527f5369676e61747572653a20496e76616c6964207320706172616d6574657200006044820152606401610804565b8360ff16601b148061311e57508360ff16601c145b61316a5760405162461bcd60e51b815260206004820152601e60248201527f5369676e61747572653a20496e76616c6964207620706172616d6574657200006044820152606401610804565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156131be573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166132215760405162461bcd60e51b815260206004820152601960248201527f5369676e61747572653a20496e76616c6964207369676e6572000000000000006044820152606401610804565b95945050505050565b6060612e388484600085856001600160a01b0385163b61328c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610804565b600080866001600160a01b031685876040516132a89190613875565b60006040518083038185875af1925050503d80600081146132e5576040519150601f19603f3d011682016040523d82523d6000602084013e6132ea565b606091505b50915091506132fa828286613305565b979650505050505050565b606083156133145750816113dd565b8251156133245782518084602001fd5b8160405162461bcd60e51b815260040161080491906139ec565b803561334981613e7a565b919050565b803561334981613e8f565b600082601f830112613369578081fd5b813567ffffffffffffffff8082111561338457613384613e64565b604051601f8301601f19908116603f011681019082821181831017156133ac576133ac613e64565b816040528381528660208588010111156133c4578485fd5b8360208701602083013792830160200193909352509392505050565b600061020082840312156133f2578081fd5b50919050565b803560ff8116811461334957600080fd5b60006020828403121561341a578081fd5b81356113dd81613e7a565b600060208284031215613436578081fd5b81516113dd81613e7a565b60008060408385031215613453578081fd5b823561345e81613e7a565b946020939093013593505050565b6000806040838503121561347e578182fd5b825161348981613e7a565b6020939093015192949293505050565b600080602083850312156134ab578182fd5b823567ffffffffffffffff808211156134c2578384fd5b818501915085601f8301126134d5578384fd5b8135818111156134e3578485fd5b8660208260051b85010111156134f7578485fd5b60209290920196919550909350505050565b60006020828403121561351a578081fd5b81356113dd81613e8f565b600060208284031215613536578081fd5b81516113dd81613e8f565b600080600060608486031215613555578081fd5b835161356081613e8f565b602085015160409095015190969495509392505050565b600060208284031215613588578081fd5b5035919050565b600080604083850312156135a1578182fd5b8235915060208301356135b381613e7a565b809150509250929050565b600080604083850312156135d0578182fd5b50508035926020909101359150565b6000602082840312156135f0578081fd5b81356113dd81613e9d565b60006020828403121561360c578081fd5b81516113dd81613e9d565b60008060408385031215613629578182fd5b823567ffffffffffffffff80821115613640578384fd5b61364c868387016133e0565b93506020850135915080821115613661578283fd5b5061366e858286016133e0565b9150509250929050565b6000806040838503121561368a578182fd5b823567ffffffffffffffff808211156136a1578384fd5b9084019060c082870312156136b4578384fd5b90925060208401359080821115613661578283fd5b6000602082840312156136da578081fd5b5051919050565b6000602082840312156136f2578081fd5b6113dd826133f8565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000815180845261373c816020860160208601613df0565b601f01601f19169290920160200192915050565b6000610200613768846137628561334e565b15159052565b6137746020840161333e565b6001600160a01b0316602085015261378e6040840161333e565b6001600160a01b038116604086015250606083013560608501526080830135608085015260a083013560a08501526137c860c0840161333e565b6001600160a01b031660c08501526137e260e0840161333e565b6001600160a01b031660e0850152610100838101359085015261012080840135908501526101408084013590850152610160808401359085015261018061382b81850185613c27565b838388015261383d84880182846136fb565b93505050506101a06138508185016133f8565b60ff16908501526101c083810135908501526101e09283013592909301919091525090565b60008251613887818460208701613df0565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516138c9816017850160208801613df0565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516138fa816028840160208801613df0565b01602801949350505050565b6020808252810182905260006001600160fb1b03831115613925578081fd5b8260051b808560408501379190910160400190815292915050565b8e81528d151560208201526001600160a01b038d811660408301528c1660608201526101c081018b60808301528a60a08301528960c083015261398e60e083018a6001600160a01b03169052565b6001600160a01b0388166101008301526101208201969096526101408101949094526101608401929092526101808301526101a0909101529998505050505050505050565b828152604060208201526000612e386040830184613724565b6020815260006113dd6020830184613724565b6020808252601290820152714f726465723a2057726f6e6720736964657360701b604082015260600190565b6020808252601d908201527f4f776e65723a2043616e6e6f74206265206e756c6c2061646472657373000000604082015260600190565b6020808252601b908201527f53747261746567793a20457865637574696f6e20696e76616c69640000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601f908201527f4f726465723a2054616b6572206d757374206265207468652073656e64657200604082015260600190565b60208082526026908201527f43616e63656c3a204f72646572206e6f6e6365206c6f776572207468616e20636040820152651d5c9c995b9d60d21b606082015260800190565b604081526000613b606040830185613750565b82810360208401526132218185613750565b6040815260008335613b8381613e8f565b151560408301526020840135613b9881613e7a565b60018060a01b03811660608401525060408401356080830152606084013560a0830152608084013560c0830152613bd260a0850185613c27565b60c060e0850152613be8610100850182846136fb565b91505082810360208401526132218185613750565b604051610200810167ffffffffffffffff81118282101715613c2157613c21613e64565b60405290565b6000808335601e19843603018112613c3d578283fd5b830160208101925035905067ffffffffffffffff811115613c5d57600080fd5b803603831315613c6c57600080fd5b9250929050565b60008219821115613c8657613c86613e4e565b500190565b600082613ca657634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615613cc557613cc5613e4e565b500290565b600082821015613cdc57613cdc613e4e565b500390565b60006102008236031215613cf3578081fd5b613cfb613bfd565b613d048361334e565b8152613d126020840161333e565b6020820152613d236040840161333e565b6040820152606083013560608201526080830135608082015260a083013560a0820152613d5260c0840161333e565b60c0820152613d6360e0840161333e565b60e082015261010083810135908201526101208084013590820152610140808401359082015261016080840135908201526101808084013567ffffffffffffffff811115613daf578384fd5b613dbb36828701613359565b8284015250506101a0613dcf8185016133f8565b908201526101c083810135908201526101e092830135928101929092525090565b60005b83811015613e0b578181015183820152602001613df3565b8381111561270a5750506000910152565b600081613e2b57613e2b613e4e565b506000190190565b6000600019821415613e4757613e47613e4e565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610e3f57600080fd5b8015158114610e3f57600080fd5b6001600160e01b031981168114610e3f57600080fdfea2646970667358221220cf30d0871f4b5ac52655851e843dcf3609a97c9d9a3235da3992e4aa9a47d2e264736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000045eb210f33583022c7f9bf981bb3569eeba0f77e00000000000000000000000036766780336e393e10bb4fd6b5ed36ef29a4f86700000000000000000000000055091b45e4a1bb494c52191323269c3a03893be70000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae23000000000000000000000000a16226396d79dc7b3bc70de0daca4eef11742a9e
-----Decoded View---------------
Arg [0] : _currencyManager (address): 0x45eB210f33583022C7f9bF981bb3569EEbA0f77E
Arg [1] : _executionManager (address): 0x36766780336E393e10BB4Fd6B5Ed36Ef29A4F867
Arg [2] : _royaltyFeeManager (address): 0x55091b45E4a1bB494c52191323269C3A03893be7
Arg [3] : _WETH (address): 0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23
Arg [4] : _protocolFeeRecipient (address): 0xa16226396d79dc7B3Bc70DE0daCa4Eef11742a9E
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000045eb210f33583022c7f9bf981bb3569eeba0f77e
Arg [1] : 00000000000000000000000036766780336e393e10bb4fd6b5ed36ef29a4f867
Arg [2] : 00000000000000000000000055091b45e4a1bb494c52191323269c3a03893be7
Arg [3] : 0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae23
Arg [4] : 000000000000000000000000a16226396d79dc7b3bc70de0daca4eef11742a9e
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
POL | 100.00% | $0.220722 | 10.5 | $2.32 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.