More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
MultisigWallet
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // This file is part of the MultisigWallet project. // Portions of this code are derived from the OpenZeppelin Contracts library. // OpenZeppelin Contracts are licensed under the MIT License. // See the LICENSE and NOTICE files for more details. pragma solidity ^0.8.7; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; /** * @title MultisigWallet * @dev A multisig wallet contract that requires multiple confirmations for transactions, including managing owners. */ contract MultisigWallet is ReentrancyGuard, IERC721Receiver { /** * @notice Emitted when a deposit is made. * @param sender The address that sent the deposit. * @param amountOrTokenId The amount of Ether or the token ID for ERC721 deposits. * @param balance The new balance of the wallet after the deposit. */ event Deposit(address indexed sender, uint256 indexed amountOrTokenId, uint256 indexed balance); /** * @notice Emitted when a transaction is submitted. * @param _transactionType The type of the submitted transaction. * @param txIndex The index of the submitted transaction. * @param to The address to which the transaction is directed. * @param value The amount of Ether sent in the transaction. * @param tokenAddress The address of the token contract (if applicable). * @param amountOrTokenId The amount of tokens or the token ID (if applicable). * @param owner The address of the owner who submitted the transaction. * @param data The data payload of the transaction. */ event SubmitTransaction( TransactionType indexed _transactionType, uint256 indexed txIndex, address indexed to, uint256 value, address tokenAddress, uint256 amountOrTokenId, address owner, bytes data ); /** * @notice Emitted when a transaction is confirmed by an owner. * @param owner The address of the owner who confirmed the transaction. * @param txIndex The index of the confirmed transaction. */ event ConfirmTransaction(address indexed owner, uint256 indexed txIndex); /** * @notice Emitted when a confirmation for a transaction is revoked by an owner. * @param owner The address of the owner who revoked the confirmation. * @param txIndex The index of the transaction for which the confirmation was revoked. */ event RevokeConfirmation(address indexed owner, uint256 indexed txIndex); /** * @notice Emitted when a transaction is executed. * @param _transactionType The type of the executed transaction. * @param txIndex The index of the executed transaction. * @param to The address to which the transaction was sent. * @param value The amount of Ether sent in the transaction. * @param tokenAddress The address of the token contract (if applicable). * @param amountOrTokenId The amount of tokens or the token ID (if applicable). * @param owner The address of the owner who executed the transaction. * @param data The data payload of the transaction. */ event ExecuteTransaction( TransactionType indexed _transactionType, uint256 indexed txIndex, address indexed to, uint256 value, address tokenAddress, uint256 amountOrTokenId, address owner, bytes data ); /** * @notice Emitted for each transfer within a batch transaction. * @param recipient The recipient address of the transfer. * @param tokenAddress The token contract address (if applicable, `address(0)` for Ether). * @param value The amount of Ether or ERC20 tokens transferred. * @param tokenId The ID of the ERC721 token transferred (if applicable). * @notice Test a large BatchTransfer on a local testnet first to check if the gascosts are within the EVM constraint */ event BatchTransferExecuted( address indexed recipient, address indexed tokenAddress, uint256 value, uint256 indexed tokenId ); /** * @notice Emitted when a new owner is added to the multisig wallet. * @param owner The address of the owner that was added. */ event OwnerAdded(address indexed owner); /** * @notice Emitted when an owner is removed from the multisig wallet. * @param owner The address of the owner that was removed. */ event OwnerRemoved(address indexed owner); /** * @notice Emitted when all pending transactions are deactivated. */ event PendingTransactionsDeactivated(); /** * @notice Emitted when an owner deactivates their own pending transaction. * @param txIndex The index of the transaction that was deactivated. * @param owner The address of the owner who deactivated the transaction. */ event DeactivatedMyPendingTransaction(uint256 indexed txIndex, address indexed owner); /** * @notice Emitted when the contract receives an ERC721 token. * @param operator The address which initiated the transfer (i.e., msg.sender). * @param from The address which previously owned the token. * @param tokenId The identifier of the token being transferred. * @param data Additional data with no specified format. */ event ERC721Received(address indexed operator, address indexed from, uint256 indexed tokenId, bytes data); /** * @enum TransactionType * @dev Represents the type of transaction in the multisig wallet. * @param ETH Ether transfer. * @param ERC20 ERC20 token transfer. * @param ERC721 ERC721 token transfer. * @param AddOwner Adding a new owner. * @param RemoveOwner Removing an existing owner. * @param BatchTransaction multiple transfers in one ransaction. * @param Other Any other transaction type. */ enum TransactionType { ETH, // 0 ERC20, // 1 ERC721, // 2 AddOwner, // 3 RemoveOwner, // 4 BatchTransaction, // 5 Other // 6 } /** * @struct Transaction * @dev Represents a transaction within the multisig wallet. * @param transactionType The type of the transaction. * @param isActive Indicates if the transaction is active. * @param numConfirmations The number of confirmations the transaction has received. * @param owner The address of the owner who submitted the transaction. * @param to The destination address of the transaction. * @param value The amount of Ether involved in the transaction. * @param data The data payload of the transaction. */ struct Transaction { TransactionType transactionType; bool isActive; uint64 numConfirmations; address owner; address to; uint256 value; bytes data; } /// @notice Struct to represent individual bulk transfer details struct BatchTransaction { address to; // Recipient address address tokenAddress; // Token contract address (address(0) for ETH) uint256 value; // Ether amount (if ETH) or token amount uint256 tokenId; // Token ID (for ERC721) } /// @notice Array of multisig wallet owners. address[] public owners; /// @notice Mapping to check if an address is an owner. mapping(address => bool) public isOwner; /// @notice Nested mapping to track confirmations: transaction index => owner => confirmation status. mapping(uint256 => mapping(address => bool)) public isConfirmed; /// @notice Array of all submitted transactions. Transaction[] public transactions; /** * @notice Modifier to restrict access to only multisig owners. * @dev Reverts if the caller is not an owner. */ modifier onlyMultisigOwner() { require(isOwner[msg.sender], "MultisigWallet: Not a multisig owner"); _; } /** * @notice Modifier to check if a transaction exists. * @dev Reverts if the transaction does not exist. * @param _txIndex The index of the transaction. */ modifier txExists(uint256 _txIndex) { require(_txIndex < transactions.length, "MultisigWallet: Transaction does not exist"); _; } /** * @notice Modifier to check if a transaction is active. * @dev Reverts if the transaction is not active. * @param _txIndex The index of the transaction. */ modifier isActive(uint256 _txIndex) { require(transactions[_txIndex].isActive, "MultisigWallet: Transaction not active"); _; } /** * @notice Modifier to ensure the transaction has not been confirmed by the caller. * @dev Reverts if the transaction is already confirmed by the caller. * @param _txIndex The index of the transaction. */ modifier notConfirmed(uint256 _txIndex) { require(!isConfirmed[_txIndex][msg.sender], "MultisigWallet: transaction already confirmed by this owner"); _; } /** * @notice Initializes the multisig wallet with a list of owners. * @dev The constructor sets the initial owners and ensures no duplicates or zero addresses. * @param _owners The array of addresses to be set as initial owners. */ constructor(address[] memory _owners) { require(_owners.length > 0, "MultisigWallet: at least one owner required"); for (uint256 i = 0; i < _owners.length; i++) { address owner = _owners[i]; require(owner != address(0), "MultisigWallet: owner address cannot be zero"); require(!isOwner[owner], "MultisigWallet: duplicate owner address"); isOwner[owner] = true; owners.push(owner); } } /** * @notice Fallback function to receive Ether. * @dev Emits a {Deposit} event upon receiving Ether. */ receive() external payable { emit Deposit(msg.sender, msg.value, address(this).balance); } /** * @notice Submits a transaction to be confirmed by the owners. * @dev Depending on the transaction type, it decodes the data and emits a {SubmitTransaction} event. Once submitted the transaction gets directly confirmed for that owner by calling the confirmTransaction funcion. * @param _transactionType The type of the transaction. * @param _to The address to send the transaction to. * @param _value The amount of Ether to send (if applicable). * @param _data The data payload of the transaction. */ function submitTransaction(TransactionType _transactionType, address _to, uint256 _value, bytes memory _data) public onlyMultisigOwner { uint256 txIndex = transactions.length; transactions.push( Transaction({ transactionType: _transactionType, to: _to, value: _value, data: _data, isActive: true, numConfirmations: 0, owner: msg.sender }) ); address recipient = _to; address tokenAddress = address(0); uint256 _amountOrTokenId = 0; if (_transactionType == TransactionType.ERC20 || _transactionType == TransactionType.ERC721) { // Decode the data to extract the token address and amount / tokenId (address to, uint256 amountOrTokenId) = decodeTransactionData(_transactionType, _data); recipient = to; tokenAddress = _to; _amountOrTokenId = amountOrTokenId; } emit SubmitTransaction( _transactionType, txIndex, recipient, _value, tokenAddress, _amountOrTokenId, msg.sender, _data ); confirmTransaction(txIndex); } /** * @notice Confirms a submitted transaction. * @dev Increments the confirmation count and executes the transaction if enough confirmations are reached. * @param _txIndex The index of the transaction to confirm. */ function confirmTransaction(uint256 _txIndex) public onlyMultisigOwner txExists(_txIndex) isActive(_txIndex) notConfirmed(_txIndex) { Transaction storage transaction = transactions[_txIndex]; isConfirmed[_txIndex][msg.sender] = true; uint64 newNumConfirmations = transaction.numConfirmations + 1; // doing that to safe gas transaction.numConfirmations = newNumConfirmations; TransactionType txType = transaction.transactionType; // doing that to safe gas in the hasEnoughConfirmations function emit ConfirmTransaction(msg.sender, _txIndex); if (hasEnoughConfirmations(newNumConfirmations, txType)) { executeTransaction(_txIndex); // this means that the owner who gives the last needed confirmation has to pay for the execution gas fees } } /** * @notice Executes a confirmed transaction. * @dev Performs the actual transaction based on its type and marks it as inactive after execution. For adding or removing multisig owners, the respective internal function get called. * @param _txIndex The index of the transaction to execute. */ function executeTransaction(uint256 _txIndex) public txExists(_txIndex) isActive(_txIndex) nonReentrant onlyMultisigOwner { Transaction storage transaction = transactions[_txIndex]; uint64 numConfirmations = transaction.numConfirmations; TransactionType txType = transaction.transactionType; require( hasEnoughConfirmations(numConfirmations, txType), "MultisigWallet: insufficient confirmations to execute" ); address to = transaction.to; uint256 value = transaction.value; bytes memory data = transaction.data; address recipient = to; address tokenAddress = address(0); uint256 amountOrTokenId = 0; if (txType == TransactionType.BatchTransaction) { BatchTransaction[] memory transfers = abi.decode(data, (BatchTransaction[])); uint256 len = transfers.length; for (uint256 i = 0; i < len; i++) { BatchTransaction memory transfer = transfers[i]; if (transfer.tokenAddress == address(0)) { // Ether transfer require((transfer.tokenId == 0), "BatchTransfer: ETH transfer with TokenId doesn't make sense"); (bool success,) = transfer.to.call{value: transfer.value}(""); require(success, "BatchTransfer: Ether transfer failed"); } else if (transfer.tokenId == 0) { // ERC20 transfer require( IERC20(transfer.tokenAddress).transfer(transfer.to, transfer.value), "BatchTransfer: ERC20 transfer failed" ); } else { // ERC721 transfer IERC721(transfer.tokenAddress).safeTransferFrom(address(this), transfer.to, transfer.tokenId); } // Emit BatchTransferExecuted event emit BatchTransferExecuted(transfer.to, transfer.tokenAddress, transfer.value, transfer.tokenId); } } if (txType == TransactionType.AddOwner) { addOwnerInternal(to, _txIndex); } else if (txType == TransactionType.RemoveOwner) { removeOwnerInternal(to, _txIndex); } if (txType == TransactionType.ETH || txType == TransactionType.Other) { require(to != address(this), "MultisigWallet: cannot call internal functions"); (bool success,) = to.call{value: value}(data); require(success, "MultisigWallet: external call failed"); } if (txType == TransactionType.ERC20 || txType == TransactionType.ERC721) { require(to != address(this), "MultisigWallet: cannot call internal functions"); (bool success,) = to.call{value: value}(data); require(success, "MultisigWallet: external call failed"); // Decode the data to extract the token address and amount / tokenId (address _to, uint256 _amountOrTokenId) = decodeTransactionData(txType, data); recipient = _to; tokenAddress = to; amountOrTokenId = _amountOrTokenId; } transaction.isActive = false; emit ExecuteTransaction(txType, _txIndex, recipient, value, tokenAddress, amountOrTokenId, msg.sender, data); } /** * @notice Revokes a confirmation for a transaction. * @dev Decrements the confirmation count. * @param _txIndex The index of the transaction to revoke confirmation for. */ function revokeConfirmation(uint256 _txIndex) public onlyMultisigOwner txExists(_txIndex) isActive(_txIndex) { Transaction storage transaction = transactions[_txIndex]; require(transaction.isActive, "MultisigWallet: Transaction is not active"); require(isConfirmed[_txIndex][msg.sender], "MultisigWallet: Transaction has not been confirmed"); transaction.numConfirmations -= 1; isConfirmed[_txIndex][msg.sender] = false; emit RevokeConfirmation(msg.sender, _txIndex); } /** * @notice Submits a transaction to send Ether to a specified address. * @dev Utilizes {submitTransaction} with `TransactionType.ETH`. * @param _to The recipient address. * @param _amount The amount of Ether to send (in Wei). */ function sendETH(address _to, uint256 _amount) public onlyMultisigOwner { require(_to != address(0), "MultisigWallet: receiver address required"); require(_amount > 0, "MultisigWallet: Ether (Wei) amount required"); submitTransaction(TransactionType.ETH, _to, _amount, ""); } /** * @notice Adds a new owner to the multisig wallet. * @dev Submits a transaction of type `AddOwner` which requires confirmations. * @param _newOwner The address of the new owner to be added. */ function addOwner(address _newOwner) public onlyMultisigOwner { require(_newOwner != address(0), "MultisigWallet: new owner address required"); require(!isOwner[_newOwner], "MultisigWallet: owner already exists"); submitTransaction(TransactionType.AddOwner, _newOwner, 0, ""); } /** * @notice Internal function to add a new owner after sufficient confirmations. * @dev Adds the new owner, updates mappings, and emits an {OwnerAdded} event. * @param _newOwner The address of the new owner to be added. * @param _txIndex The index of the transaction that triggered the addition. */ function addOwnerInternal(address _newOwner, uint256 _txIndex) internal onlyMultisigOwner txExists(_txIndex) isActive(_txIndex) { Transaction storage transaction = transactions[_txIndex]; require( transaction.numConfirmations * 3 >= owners.length * 2, "MultisigWallet: insufficient confirmations to add owner" ); require(!isOwner[_newOwner], "MultisigWallet: address is already an owner"); // Clear pending transactions before adding the new owner deactivatePendingTransactions(); isOwner[_newOwner] = true; owners.push(_newOwner); emit OwnerAdded(_newOwner); } /** * @notice Removes an existing owner from the multisig wallet. * @dev Submits a transaction of type `RemoveOwner` which requires confirmations. * @param _owner The address of the owner to be removed. */ function removeOwner(address _owner) public onlyMultisigOwner { require(_owner != address(0), "MultisigWallet: owner Address that is to be removed is required"); require(isOwner[_owner], "MultisigWallet: address is not an owner"); submitTransaction(TransactionType.RemoveOwner, _owner, 0, ""); } /** * @notice Internal function to remove an owner after sufficient confirmations. * @dev Removes the owner, updates mappings, and emits an {OwnerRemoved} event. * @param _owner The address of the owner to be removed. * @param _txIndex The index of the transaction that triggered the removal. */ function removeOwnerInternal(address _owner, uint256 _txIndex) internal onlyMultisigOwner txExists(_txIndex) isActive(_txIndex) { Transaction storage transaction = transactions[_txIndex]; require( transaction.numConfirmations * 3 >= owners.length * 2, "MultisigWallet: insufficient confirmations to remove owner" ); require(isOwner[_owner], "MultisigWallet: address is not an owner"); require(owners.length > 1, "MultisigWallet: cannot remove the last owner"); // Clear pending transactions before adding the new owner deactivatePendingTransactions(); isOwner[_owner] = false; for (uint256 i = 0; i < owners.length; i++) { if (owners[i] == _owner) { owners[i] = owners[owners.length - 1]; owners.pop(); break; } } emit OwnerRemoved(_owner); } /** * @notice Submits a transaction to transfer ERC20 tokens. * @dev Encodes the ERC20 `transfer` function call and submits it as a transaction. * @param _token The ERC20 token contract. * @param _to The recipient address. * @param _amount The amount of tokens to transfer. */ function transferERC20(IERC20 _token, address _to, uint256 _amount) public onlyMultisigOwner { require(address(_token) != address(0), "MultisigWallet: token address required"); require(_to != address(0), "MultisigWallet: receiver address required"); require(_amount > 0, "MultisigWallet: token amount required"); // Encode the transfer data bytes memory data = abi.encodeWithSelector(_token.transfer.selector, _to, _amount); // Submit the transaction for confirmation submitTransaction(TransactionType.ERC20, address(_token), 0, data); } /** * @notice Submits a transaction to transfer ERC20 tokens using `transferFrom`. * @dev Encodes the ERC20 `transferFrom` function call and submits it as a transaction. * @param _token The ERC20 token contract. * @param _from The address from which tokens will be transferred. * @param _to The recipient address. * @param _amount The amount of tokens to transfer. */ function transferFromERC20(IERC20 _token, address _from, address _to, uint256 _amount) public onlyMultisigOwner { require(address(_token) != address(0), "MultisigWallet: token address required"); require(_from != address(0), "MultisigWallet: the token-owners address is required"); require(_to != address(0), "MultisigWallet: receiver address required"); require(_amount > 0, "MultisigWallet: token amount required"); // Encode the transferFrom data bytes memory data = abi.encodeWithSelector(_token.transferFrom.selector, _from, _to, _amount); // Submit the transaction for confirmation submitTransaction(TransactionType.ERC20, address(_token), 0, data); } /** * @notice Submits a transaction to transfer an ERC721 token. * @dev Encodes the ERC721 `safeTransferFrom` function call and submits it as a transaction. * @param _token The ERC721 token contract. * @param _from The current owner of the token. * @param _to The recipient address. * @param _tokenId The ID of the token to transfer. */ function safeTransferFromERC721(address _token, address _from, address _to, uint256 _tokenId) public onlyMultisigOwner { require(address(_token) != address(0), "MultisigWallet: token address required"); require(_from != address(0), "MultisigWallet: the tokenowners address is required"); require(_to != address(0), "MultisigWallet: receiver address required"); // Encode the transferFrom data bytes memory data = abi.encodeWithSignature("safeTransferFrom(address,address,uint256)", _from, _to, _tokenId); submitTransaction(TransactionType.ERC721, _token, 0, data); } /** * @notice Submits a BulkTransfer transaction * @dev Encodes an array of BulkTransfer structs into the data payload * @param transfers Array of BulkTransfer structs representing the transfers */ function batchTransfer(BatchTransaction[] memory transfers) public onlyMultisigOwner { bytes memory data = abi.encode(transfers); submitTransaction(TransactionType.BatchTransaction, address(this), 0, data); } /** * @notice Deactivates all pending (active) transactions. * @dev Iterates through all transactions and marks them as inactive. * Emits a {PendingTransactionsDeactivated} event upon completion. */ function deactivatePendingTransactions() internal { uint256 length = transactions.length; for (uint256 i = 0; i < length;) { Transaction storage txn = transactions[i]; if (txn.isActive) { txn.isActive = false; } unchecked { ++i; } } emit PendingTransactionsDeactivated(); } /** * @notice Allows an owner to deactivate their own pending transaction. * @dev Marks the specified transaction as inactive if it was submitted by the caller. * @param _txIndex The index of the transaction to deactivate. */ function deactivateMyPendingTransaction(uint256 _txIndex) public txExists(_txIndex) isActive(_txIndex) onlyMultisigOwner { require( transactions[_txIndex].owner == msg.sender, "MultisigWallet: only the owner can clear their submitted transaction" ); // Deactivate Transaction transactions[_txIndex].isActive = false; emit DeactivatedMyPendingTransaction(_txIndex, msg.sender); } /** * @notice Checks if a transaction has received enough confirmations to be executed. * @dev The required number of confirmations varies based on the transaction type. * @param numConfirmations The current number of confirmations. * @param transactionType The type of the transaction. * @return True if the transaction has enough confirmations, false otherwise. */ function hasEnoughConfirmations(uint64 numConfirmations, TransactionType transactionType) internal view returns (bool) { if (transactionType == TransactionType.AddOwner || transactionType == TransactionType.RemoveOwner) { // Important decisions require 2/3 or more confirmations return numConfirmations * 3 >= owners.length * 2; } else { // Normal decisions require more than 50% confirmations return numConfirmations * 2 > owners.length; } } /** * @notice Decodes the transaction data based on the transaction type. * @dev Extracts relevant parameters from the data payload for ERC20 and ERC721 transactions. * @param transactionType The type of the transaction. * @param data The data payload of the transaction. * @return to The recipient address extracted from the data. * @return amountOrTokenId The amount of tokens or token ID extracted from the data. */ function decodeTransactionData(TransactionType transactionType, bytes memory data) internal pure returns (address to, uint256 amountOrTokenId) { if (transactionType == TransactionType.ERC20) { // ERC20 transfer(address recipient, uint256 amount) require(data.length == 68 || data.length == 100, "MultisigWallet: invalid data length for ERC20 transfer"); // Use assembly to extract parameters directly if (data.length == 68) { // Handle ERC20 transfer(address to, uint256 amount) assembly { // data points to the bytes array in memory // Skip the first 32 bytes (length) and 4 bytes (selector) let paramsOffset := add(data, 36) to := mload(paramsOffset) // Load address (to) at data + 36 amountOrTokenId := mload(add(paramsOffset, 32)) // Load uint256 (amount) at data + 68 } return (to, amountOrTokenId); } else if (data.length == 100) { // Handle ERC20 transferFrom(address from, address to, uint256 amount) assembly { // Skip the first 32 bytes (length) and 4 bytes (selector) let paramsOffset := add(data, 36) // from is at data + 36, but we don't need to use it let toAddr := mload(add(paramsOffset, 32)) // Load address (to) at data + 68 let amount := mload(add(paramsOffset, 64)) // Load uint256 (amount) at data + 100 to := toAddr amountOrTokenId := amount } return (to, amountOrTokenId); } } else if (transactionType == TransactionType.ERC721) { // ERC721 safeTransferFrom(address from, address to, uint256 tokenId) require(data.length == 100, "MultisigWallet: invalid data length for ERC721 transfer"); // Use assembly to extract parameters directly assembly { let paramsOffset := add(data, 36) // Skipping 'from' address (we don't need it for the return value) to := mload(add(paramsOffset, 32)) // Load address (to) amountOrTokenId := mload(add(paramsOffset, 64)) // Load uint256 (tokenId) } return (to, amountOrTokenId); } else { revert("MultisigWallet: unsupported transaction type for data decoding"); } } /** * @notice Handles the receipt of an ERC721 token. * @dev This function is called whenever an ERC721 `safeTransfer` is performed to this contract. * It must return the function selector to confirm the token transfer. * If any other value is returned or the interface is not implemented, the transfer will be reverted. * @param operator The address which called `safeTransferFrom`. * @param from The address which previously owned the token. * @param tokenId The NFT identifier which is being transferred. * @param data Additional data with no specified format. * @return bytes4 Returns `IERC721Receiver.onERC721Received.selector` to confirm the token transfer. */ function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external override returns (bytes4) { emit ERC721Received(operator, from, tokenId, data); return this.onERC721Received.selector; } /** * @notice Retrieves the total number of owners. * @return ownerCount The number of current owners in the multisig wallet. */ function getOwnerCount() public view returns (uint256) { uint256 ownerCount = owners.length; return ownerCount; } /** * @notice Retrieves the list of all owners. * @return ownersList An array containing the addresses of all current owners. */ function getOwners() public view returns (address[] memory) { return owners; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @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; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or * {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the address zero. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be * reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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); }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address[]","name":"_owners","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"BatchTransferExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"txIndex","type":"uint256"}],"name":"ConfirmTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"txIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"DeactivatedMyPendingTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"amountOrTokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ERC721Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum MultisigWallet.TransactionType","name":"_transactionType","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"txIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOrTokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ExecuteTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"OwnerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"OwnerRemoved","type":"event"},{"anonymous":false,"inputs":[],"name":"PendingTransactionsDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"txIndex","type":"uint256"}],"name":"RevokeConfirmation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum MultisigWallet.TransactionType","name":"_transactionType","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"txIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOrTokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"SubmitTransaction","type":"event"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"addOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct MultisigWallet.BatchTransaction[]","name":"transfers","type":"tuple[]"}],"name":"batchTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txIndex","type":"uint256"}],"name":"confirmTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txIndex","type":"uint256"}],"name":"deactivateMyPendingTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txIndex","type":"uint256"}],"name":"executeTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getOwnerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"isConfirmed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"owners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"removeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txIndex","type":"uint256"}],"name":"revokeConfirmation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFromERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sendETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum MultisigWallet.TransactionType","name":"_transactionType","type":"uint8"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"submitTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"transactions","outputs":[{"internalType":"enum MultisigWallet.TransactionType","name":"transactionType","type":"uint8"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint64","name":"numConfirmations","type":"uint64"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferFromERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561001057600080fd5b5060405161361838038061361883398101604081905261002f9161025a565b6001600055805161009b5760405162461bcd60e51b815260206004820152602b60248201527f4d756c746973696757616c6c65743a206174206c65617374206f6e65206f776e60448201526a195c881c995c5d5a5c995960aa1b60648201526084015b60405180910390fd5b60005b81518110156102215760008282815181106100bb576100bb610329565b6020026020010151905060006001600160a01b0316816001600160a01b03160361013c5760405162461bcd60e51b815260206004820152602c60248201527f4d756c746973696757616c6c65743a206f776e6572206164647265737320636160448201526b6e6e6f74206265207a65726f60a01b6064820152608401610092565b6001600160a01b03811660009081526002602052604090205460ff16156101b55760405162461bcd60e51b815260206004820152602760248201527f4d756c746973696757616c6c65743a206475706c6963617465206f776e6572206044820152666164647265737360c81b6064820152608401610092565b6001600160a01b03166000818152600260205260408120805460ff1916600190811790915580548082018255918190527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690910180546001600160a01b0319169092179091550161009e565b505061033f565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b038116811461025557600080fd5b919050565b60006020828403121561026c57600080fd5b81516001600160401b0381111561028257600080fd5b8201601f8101841361029357600080fd5b80516001600160401b038111156102ac576102ac610228565b604051600582901b90603f8201601f191681016001600160401b03811182821017156102da576102da610228565b6040529182526020818401810192908101878411156102f857600080fd5b6020850194505b8385101561031e576103108561023e565b8152602094850194016102ff565b509695505050505050565b634e487b7160e01b600052603260045260246000fd5b6132ca8061034e6000396000f3fe6080604052600436106101185760003560e01c80638dbcc2e0116100a0578063d47a1a2711610064578063d47a1a271461039b578063d59dafd0146103bb578063dd71105d146103db578063ee22610b146103fb578063ef18374a1461041b57600080fd5b80638dbcc2e0146102e65780639ace38c2146103065780639db5dbe414610339578063a0e67e2b14610359578063c01a8c841461037b57600080fd5b806320ea8d86116100e757806320ea8d861461020b5780632f54bf6e1461022b57806364a197f31461026b5780637065cb481461028b57806380f59a65146102ab57600080fd5b8063025e7c2714610153578063150b7a0214610190578063173825d9146101c95780631afecd1c146101eb57600080fd5b3661014e576040514790349033907f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1590600090a4005b600080fd5b34801561015f57600080fd5b5061017361016e3660046126bb565b610439565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561019c57600080fd5b506101b06101ab3660046126e9565b610463565b6040516001600160e01b03199091168152602001610187565b3480156101d557600080fd5b506101e96101e4366004612788565b6104c5565b005b3480156101f757600080fd5b506101e96102063660046126bb565b6105d1565b34801561021757600080fd5b506101e96102263660046126bb565b610796565b34801561023757600080fd5b5061025b610246366004612788565b60026020526000908152604090205460ff1681565b6040519015158152602001610187565b34801561027757600080fd5b506101e96102863660046127ac565b6109da565b34801561029757600080fd5b506101e96102a6366004612788565b610ab3565b3480156102b757600080fd5b5061025b6102c63660046127d8565b600360209081526000928352604080842090915290825290205460ff1681565b3480156102f257600080fd5b506101e9610301366004612876565b610bd9565b34801561031257600080fd5b506103266103213660046126bb565b610e28565b60405161018797969594939291906129a7565b34801561034557600080fd5b506101e9610354366004612a21565b610f1c565b34801561036557600080fd5b5061036e611012565b6040516101879190612a62565b34801561038757600080fd5b506101e96103963660046126bb565b611074565b3480156103a757600080fd5b506101e96103b6366004612ad1565b611287565b3480156103c757600080fd5b506101e96103d6366004612bbb565b6112e8565b3480156103e757600080fd5b506101e96103f6366004612bbb565b61143d565b34801561040757600080fd5b506101e96104163660046126bb565b6115a8565b34801561042757600080fd5b50600154604051908152602001610187565b6001818154811061044957600080fd5b6000918252602090912001546001600160a01b0316905081565b600083856001600160a01b0316876001600160a01b03167fa05d90f300156ad1b545bc5d8197024456f21d22a708f5af04dd293e3d60525186866040516104ab929190612c0c565b60405180910390a450630a85bd0160e11b95945050505050565b3360009081526002602052604090205460ff166104fd5760405162461bcd60e51b81526004016104f490612c3b565b60405180910390fd5b6001600160a01b0381166105795760405162461bcd60e51b815260206004820152603f60248201527f4d756c746973696757616c6c65743a206f776e6572204164647265737320746860448201527f617420697320746f2062652072656d6f7665642069732072657175697265640060648201526084016104f4565b6001600160a01b03811660009081526002602052604090205460ff166105b15760405162461bcd60e51b81526004016104f490612c7f565b6105ce600482600060405180602001604052806000815250610bd9565b50565b600454819081106105f45760405162461bcd60e51b81526004016104f490612cc6565b816004818154811061060857610608612d10565b6000918252602090912060049091020154610100900460ff1661063d5760405162461bcd60e51b81526004016104f490612d26565b3360009081526002602052604090205460ff1661066c5760405162461bcd60e51b81526004016104f490612c3b565b336001600160a01b03166004848154811061068957610689612d10565b6000918252602090912060049091020154600160501b90046001600160a01b03161461072b5760405162461bcd60e51b8152602060048201526044602482018190527f4d756c746973696757616c6c65743a206f6e6c7920746865206f776e65722063908201527f616e20636c656172207468656972207375626d6974746564207472616e7361636064820152633a34b7b760e11b608482015260a4016104f4565b60006004848154811061074057610740612d10565b60009182526020822060049091020180549215156101000261ff001990931692909217909155604051339185917f2c8d5957f60f56ae0608f50dbce4cda251ec4ed938d7d2ef7e10297719fdf2539190a3505050565b3360009081526002602052604090205460ff166107c55760405162461bcd60e51b81526004016104f490612c3b565b600454819081106107e85760405162461bcd60e51b81526004016104f490612cc6565b81600481815481106107fc576107fc612d10565b6000918252602090912060049091020154610100900460ff166108315760405162461bcd60e51b81526004016104f490612d26565b60006004848154811061084657610846612d10565b600091825260209091206004909102018054909150610100900460ff166108c15760405162461bcd60e51b815260206004820152602960248201527f4d756c746973696757616c6c65743a205472616e73616374696f6e206973206e6044820152686f742061637469766560b81b60648201526084016104f4565b600084815260036020908152604080832033845290915290205460ff166109455760405162461bcd60e51b815260206004820152603260248201527f4d756c746973696757616c6c65743a205472616e73616374696f6e20686173206044820152711b9bdd081899595b8818dbdb999a5c9b595960721b60648201526084016104f4565b805460019082906002906109699084906201000090046001600160401b0316612d82565b82546001600160401b039182166101009390930a9283029190920219909116179055506000848152600360209081526040808320338085529252808320805460ff191690555186927ff0dca620e2e81f7841d07bcc105e1704fb01475b278a9d4c236e1c62945edd5591a350505050565b3360009081526002602052604090205460ff16610a095760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b038216610a2f5760405162461bcd60e51b81526004016104f490612da1565b60008111610a935760405162461bcd60e51b815260206004820152602b60248201527f4d756c746973696757616c6c65743a20457468657220285765692920616d6f7560448201526a1b9d081c995c5d5a5c995960aa1b60648201526084016104f4565b610aaf6000838360405180602001604052806000815250610bd9565b5050565b3360009081526002602052604090205460ff16610ae25760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b038116610b4b5760405162461bcd60e51b815260206004820152602a60248201527f4d756c746973696757616c6c65743a206e6577206f776e6572206164647265736044820152691cc81c995c5d5a5c995960b21b60648201526084016104f4565b6001600160a01b03811660009081526002602052604090205460ff1615610bc05760405162461bcd60e51b8152602060048201526024808201527f4d756c746973696757616c6c65743a206f776e657220616c72656164792065786044820152636973747360e01b60648201526084016104f4565b6105ce6003826000604051806020016040528060008152505b3360009081526002602052604090205460ff16610c085760405162461bcd60e51b81526004016104f490612c3b565b600480546040805160e0810190915290919080876006811115610c2d57610c2d612941565b8152600160208083018290526000604084018190523360608501526001600160a01b038a16608085015260a0840189905260c09093018790528454808301865594835290912082516004909402018054929390929091839160ff191690836006811115610c9c57610c9c612941565b021790555060208201518154604084015160608501516001600160a01b03908116600160501b027fffff0000000000000000000000000000000000000000ffffffffffffffffffff6001600160401b03909316620100000269ffffffffffffffff000019951515610100029590951669ffffffffffffffffff00199094169390931793909317161782556080830151600183018054919092166001600160a01b031990911617905560a0820151600282015560c08201516003820190610d629082612e6b565b5085915060009050806001886006811115610d7f57610d7f612941565b1480610d9c57506002886006811115610d9a57610d9a612941565b145b15610db957600080610dae8a88611dbe565b909550899450925050505b826001600160a01b031684896006811115610dd657610dd6612941565b7f7a9333d5a9c2b79797bf46d7626bd8cda468b400f501bc0ed09cdef2d294c9dd898686338c604051610e0d959493929190612f29565b60405180910390a4610e1e84611074565b5050505050505050565b60048181548110610e3857600080fd5b6000918252602090912060049091020180546001820154600283015460038401805460ff8086169750610100860416956001600160401b0362010000870416956001600160a01b03600160501b9091048116951693929091610e9990612dea565b80601f0160208091040260200160405190810160405280929190818152602001828054610ec590612dea565b8015610f125780601f10610ee757610100808354040283529160200191610f12565b820191906000526020600020905b815481529060010190602001808311610ef557829003601f168201915b5050505050905087565b3360009081526002602052604090205460ff16610f4b5760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b038316610f715760405162461bcd60e51b81526004016104f490612f6d565b6001600160a01b038216610f975760405162461bcd60e51b81526004016104f490612da1565b60008111610fb75760405162461bcd60e51b81526004016104f490612fb3565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261100c600185600084610bd9565b50505050565b6060600180548060200260200160405190810160405280929190818152602001828054801561106a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161104c575b5050505050905090565b3360009081526002602052604090205460ff166110a35760405162461bcd60e51b81526004016104f490612c3b565b600454819081106110c65760405162461bcd60e51b81526004016104f490612cc6565b81600481815481106110da576110da612d10565b6000918252602090912060049091020154610100900460ff1661110f5760405162461bcd60e51b81526004016104f490612d26565b6000838152600360209081526040808320338452909152902054839060ff16156111a15760405162461bcd60e51b815260206004820152603b60248201527f4d756c746973696757616c6c65743a207472616e73616374696f6e20616c726560448201527f61647920636f6e6669726d65642062792074686973206f776e6572000000000060648201526084016104f4565b6000600485815481106111b6576111b6612d10565b600091825260208083208884526003825260408085203386529092529083208054600160ff19909116811790915560049290920201805490935061120a91620100009091046001600160401b031690612ff8565b82546001600160401b038216620100000269ffffffffffffffff00001982168117855560405192935060ff90811691161790879033907f5cbe105e36805f7820e291f799d5794ff948af2a5f664e580382defb6339004190600090a36112708282611fa5565b1561127e5761127e876115a8565b50505050505050565b3360009081526002602052604090205460ff166112b65760405162461bcd60e51b81526004016104f490612c3b565b6000816040516020016112c99190613017565b6040516020818303038152906040529050610aaf600530600084610bd9565b3360009081526002602052604090205460ff166113175760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b03841661133d5760405162461bcd60e51b81526004016104f490612f6d565b6001600160a01b0383166113af5760405162461bcd60e51b815260206004820152603360248201527f4d756c746973696757616c6c65743a2074686520746f6b656e6f776e657273206044820152721859191c995cdcc81a5cc81c995c5d5a5c9959606a1b60648201526084016104f4565b6001600160a01b0382166113d55760405162461bcd60e51b81526004016104f490612da1565b6040516001600160a01b038085166024830152831660448201526064810182905260009060840160408051601f198184030181529190526020810180516001600160e01b0316632142170760e11b1790529050611436600286600084610bd9565b5050505050565b3360009081526002602052604090205460ff1661146c5760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b0384166114925760405162461bcd60e51b81526004016104f490612f6d565b6001600160a01b0383166115055760405162461bcd60e51b815260206004820152603460248201527f4d756c746973696757616c6c65743a2074686520746f6b656e2d6f776e657273604482015273081859191c995cdcc81a5cc81c995c5d5a5c995960621b60648201526084016104f4565b6001600160a01b03821661152b5760405162461bcd60e51b81526004016104f490612da1565b6000811161154b5760405162461bcd60e51b81526004016104f490612fb3565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611436600186600084610bd9565b600454819081106115cb5760405162461bcd60e51b81526004016104f490612cc6565b81600481815481106115df576115df612d10565b6000918252602090912060049091020154610100900460ff166116145760405162461bcd60e51b81526004016104f490612d26565b61161c612029565b3360009081526002602052604090205460ff1661164b5760405162461bcd60e51b81526004016104f490612c3b565b60006004848154811061166057611660612d10565b6000918252602090912060049091020180549091506001600160401b03620100008204169060ff166116928282611fa5565b6116fc5760405162461bcd60e51b815260206004820152603560248201527f4d756c746973696757616c6c65743a20696e73756666696369656e7420636f6e6044820152746669726d6174696f6e7320746f206578656375746560581b60648201526084016104f4565b600183015460028401546003850180546001600160a01b03909316926000919061172590612dea565b80601f016020809104026020016040519081016040528092919081815260200182805461175190612dea565b801561179e5780601f106117735761010080835404028352916020019161179e565b820191906000526020600020905b81548152906001019060200180831161178157829003601f168201915b5093945086935060009250829150600590508760068111156117c2576117c2612941565b03611b23576000848060200190518101906117dd9190613080565b805190915060005b81811015611b1f57600083828151811061180157611801612d10565b6020026020010151905060006001600160a01b031681602001516001600160a01b031603611959576060810151156118a15760405162461bcd60e51b815260206004820152603b60248201527f42617463685472616e736665723a20455448207472616e73666572207769746860448201527f20546f6b656e496420646f65736e2774206d616b652073656e7365000000000060648201526084016104f4565b805160408083015190516000926001600160a01b031691908381818185875af1925050503d80600081146118f1576040519150601f19603f3d011682016040523d82523d6000602084013e6118f6565b606091505b50509050806119535760405162461bcd60e51b8152602060048201526024808201527f42617463685472616e736665723a204574686572207472616e736665722066616044820152631a5b195960e21b60648201526084016104f4565b50611ab8565b8060600151600003611a425760208101518151604080840151905163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af11580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e5919061315b565b611a3d5760405162461bcd60e51b8152602060048201526024808201527f42617463685472616e736665723a204552433230207472616e736665722066616044820152631a5b195960e21b60648201526084016104f4565b611ab8565b602081015181516060830151604051632142170760e11b81523060048201526001600160a01b03928316602482015260448101919091529116906342842e0e90606401600060405180830381600087803b158015611a9f57600080fd5b505af1158015611ab3573d6000803e3d6000fd5b505050505b806060015181602001516001600160a01b031682600001516001600160a01b03167f11545b22e85dd851103fdaeff84f4db960c8ea9ef39898c3f2b32b8e14913bfd8460400151604051611b0e91815260200190565b60405180910390a4506001016117e5565b5050505b6003876006811115611b3757611b37612941565b03611b4b57611b46868d612053565b611b6e565b6004876006811115611b5f57611b5f612941565b03611b6e57611b6e868d6122d0565b6000876006811115611b8257611b82612941565b1480611b9f57506006876006811115611b9d57611b9d612941565b145b15611c4c57306001600160a01b03871603611bcc5760405162461bcd60e51b81526004016104f49061317d565b6000866001600160a01b03168686604051611be791906131cb565b60006040518083038185875af1925050503d8060008114611c24576040519150601f19603f3d011682016040523d82523d6000602084013e611c29565b606091505b5050905080611c4a5760405162461bcd60e51b81526004016104f4906131e7565b505b6001876006811115611c6057611c60612941565b1480611c7d57506002876006811115611c7b57611c7b612941565b145b15611d4157306001600160a01b03871603611caa5760405162461bcd60e51b81526004016104f49061317d565b6000866001600160a01b03168686604051611cc591906131cb565b60006040518083038185875af1925050503d8060008114611d02576040519150601f19603f3d011682016040523d82523d6000602084013e611d07565b606091505b5050905080611d285760405162461bcd60e51b81526004016104f4906131e7565b600080611d358a88611dbe565b90965089955093505050505b885461ff00191689556001600160a01b0383168c886006811115611d6757611d67612941565b7f8486d3d18fdaaf4d3cd166a7275bd95df5e8087a2cc662f6c33164f3052ea6be888686338b604051611d9e959493929190612f29565b60405180910390a4505050505050505050611db96001600055565b505050565b6000806001846006811115611dd557611dd5612941565b03611e8f57825160441480611deb575082516064145b611e565760405162461bcd60e51b815260206004820152603660248201527f4d756c746973696757616c6c65743a20696e76616c69642064617461206c656e60448201527533ba34103337b91022a9219918103a3930b739b332b960511b60648201526084016104f4565b8251604403611e7057505060248101516044820151611f9e565b8251606403611e8a57505060448101516064820151611f9e565b611f9e565b6002846006811115611ea357611ea3612941565b03611f30578251606414611f1f5760405162461bcd60e51b815260206004820152603760248201527f4d756c746973696757616c6c65743a20696e76616c69642064617461206c656e60448201527f67746820666f7220455243373231207472616e7366657200000000000000000060648201526084016104f4565b505060448101516064820151611f9e565b60405162461bcd60e51b815260206004820152603e60248201527f4d756c746973696757616c6c65743a20756e737570706f72746564207472616e60448201527f73616374696f6e207479706520666f722064617461206465636f64696e67000060648201526084016104f4565b9250929050565b60006003826006811115611fbb57611fbb612941565b1480611fd857506004826006811115611fd657611fd6612941565b145b1561200857600154611feb90600261322b565b611ff6846003613242565b6001600160401b031610159050612023565b600154612016846002613242565b6001600160401b03161190505b92915050565b60026000540361204c57604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b3360009081526002602052604090205460ff166120825760405162461bcd60e51b81526004016104f490612c3b565b600454819081106120a55760405162461bcd60e51b81526004016104f490612cc6565b81600481815481106120b9576120b9612d10565b6000918252602090912060049091020154610100900460ff166120ee5760405162461bcd60e51b81526004016104f490612d26565b60006004848154811061210357612103612d10565b60009182526020909120600154600490920201915061212390600261322b565b815461213f906201000090046001600160401b03166003613242565b6001600160401b031610156121bc5760405162461bcd60e51b815260206004820152603760248201527f4d756c746973696757616c6c65743a20696e73756666696369656e7420636f6e60448201527f6669726d6174696f6e7320746f20616464206f776e657200000000000000000060648201526084016104f4565b6001600160a01b03851660009081526002602052604090205460ff16156122395760405162461bcd60e51b815260206004820152602b60248201527f4d756c746973696757616c6c65743a206164647265737320697320616c72656160448201526a323c9030b71037bbb732b960a91b60648201526084016104f4565b612241612636565b6001600160a01b038516600081815260026020526040808220805460ff19166001908117909155805480820182559083527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03191684179055517f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a25050505050565b3360009081526002602052604090205460ff166122ff5760405162461bcd60e51b81526004016104f490612c3b565b600454819081106123225760405162461bcd60e51b81526004016104f490612cc6565b816004818154811061233657612336612d10565b6000918252602090912060049091020154610100900460ff1661236b5760405162461bcd60e51b81526004016104f490612d26565b60006004848154811061238057612380612d10565b6000918252602090912060015460049092020191506123a090600261322b565b81546123bc906201000090046001600160401b03166003613242565b6001600160401b031610156124395760405162461bcd60e51b815260206004820152603a60248201527f4d756c746973696757616c6c65743a20696e73756666696369656e7420636f6e60448201527f6669726d6174696f6e7320746f2072656d6f7665206f776e657200000000000060648201526084016104f4565b6001600160a01b03851660009081526002602052604090205460ff166124715760405162461bcd60e51b81526004016104f490612c7f565b60018054116124d75760405162461bcd60e51b815260206004820152602c60248201527f4d756c746973696757616c6c65743a2063616e6e6f742072656d6f766520746860448201526b32903630b9ba1037bbb732b960a11b60648201526084016104f4565b6124df612636565b6001600160a01b0385166000908152600260205260408120805460ff191690555b6001548110156125fa57856001600160a01b03166001828154811061252757612527612d10565b6000918252602090912001546001600160a01b0316036125f2576001805461255090829061326b565b8154811061256057612560612d10565b600091825260209091200154600180546001600160a01b03909216918390811061258c5761258c612d10565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060018054806125cb576125cb61327e565b600082815260209020810160001990810180546001600160a01b03191690550190556125fa565b600101612500565b506040516001600160a01b038616907f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90600090a25050505050565b60045460005b8181101561268e5760006004828154811061265957612659612d10565b600091825260209091206004909102018054909150610100900460ff161561268557805461ff00191681555b5060010161263c565b506040517fbbb8e378f092289f6721a3c81d4263fcbfee5d004ba72a2f80ac4c118c3975cc90600090a150565b6000602082840312156126cd57600080fd5b5035919050565b6001600160a01b03811681146105ce57600080fd5b60008060008060006080868803121561270157600080fd5b853561270c816126d4565b9450602086013561271c816126d4565b93506040860135925060608601356001600160401b0381111561273e57600080fd5b8601601f8101881361274f57600080fd5b80356001600160401b0381111561276557600080fd5b88602082840101111561277757600080fd5b959894975092955050506020019190565b60006020828403121561279a57600080fd5b81356127a5816126d4565b9392505050565b600080604083850312156127bf57600080fd5b82356127ca816126d4565b946020939093013593505050565b600080604083850312156127eb57600080fd5b8235915060208301356127fd816126d4565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b038111828210171561284057612840612808565b60405290565b604051601f8201601f191681016001600160401b038111828210171561286e5761286e612808565b604052919050565b6000806000806080858703121561288c57600080fd5b84356007811061289b57600080fd5b935060208501356128ab816126d4565b92506040850135915060608501356001600160401b038111156128cd57600080fd5b8501601f810187136128de57600080fd5b80356001600160401b038111156128f7576128f7612808565b61290a601f8201601f1916602001612846565b81815288602083850101111561291f57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b634e487b7160e01b600052602160045260246000fd5b60005b8381101561297257818101518382015260200161295a565b50506000910152565b60008151808452612993816020860160208601612957565b601f01601f19169290920160200192915050565b6000600789106129c757634e487b7160e01b600052602160045260246000fd5b88825287151560208301526001600160401b03871660408301526001600160a01b0386811660608401528516608083015260a0820184905260e060c08301819052612a149083018461297b565b9998505050505050505050565b600080600060608486031215612a3657600080fd5b8335612a41816126d4565b92506020840135612a51816126d4565b929592945050506040919091013590565b602080825282518282018190526000918401906040840190835b81811015612aa35783516001600160a01b0316835260209384019390920191600101612a7c565b509095945050505050565b60006001600160401b03821115612ac757612ac7612808565b5060051b60200190565b600060208284031215612ae357600080fd5b81356001600160401b03811115612af957600080fd5b8201601f81018413612b0a57600080fd5b8035612b1d612b1882612aae565b612846565b8082825260208201915060208360071b850101925086831115612b3f57600080fd5b6020840193505b82841015612bb15760808488031215612b5e57600080fd5b612b6661281e565b8435612b71816126d4565b81526020850135612b81816126d4565b60208281019190915260408681013590830152606080870135908301529083526080909401939190910190612b46565b9695505050505050565b60008060008060808587031215612bd157600080fd5b8435612bdc816126d4565b93506020850135612bec816126d4565b92506040850135612bfc816126d4565b9396929550929360600135925050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60208082526024908201527f4d756c746973696757616c6c65743a204e6f742061206d756c7469736967206f6040820152633bb732b960e11b606082015260800190565b60208082526027908201527f4d756c746973696757616c6c65743a2061646472657373206973206e6f742061604082015266371037bbb732b960c91b606082015260800190565b6020808252602a908201527f4d756c746973696757616c6c65743a205472616e73616374696f6e20646f6573604082015269081b9bdd08195e1a5cdd60b21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60208082526026908201527f4d756c746973696757616c6c65743a205472616e73616374696f6e206e6f742060408201526561637469766560d01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03828116828216039081111561202357612023612d6c565b60208082526029908201527f4d756c746973696757616c6c65743a2072656365697665722061646472657373604082015268081c995c5d5a5c995960ba1b606082015260800190565b600181811c90821680612dfe57607f821691505b602082108103612e1e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611db957806000526020600020601f840160051c81016020851015612e4b5750805b601f840160051c820191505b818110156114365760008155600101612e57565b81516001600160401b03811115612e8457612e84612808565b612e9881612e928454612dea565b84612e24565b6020601f821160018114612ecc5760008315612eb45750848201515b600019600385901b1c1916600184901b178455611436565b600084815260208120601f198516915b82811015612efc5787850151825560209485019460019092019101612edc565b5084821015612f1a5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b8581526001600160a01b038581166020830152604082018590528316606082015260a060808201819052600090612f629083018461297b565b979650505050505050565b60208082526026908201527f4d756c746973696757616c6c65743a20746f6b656e20616464726573732072656040820152651c5d5a5c995960d21b606082015260800190565b60208082526025908201527f4d756c746973696757616c6c65743a20746f6b656e20616d6f756e74207265716040820152641d5a5c995960da1b606082015260800190565b6001600160401b03818116838216019081111561202357612023612d6c565b602080825282518282018190526000918401906040840190835b81811015612aa357835180516001600160a01b03908116855260208083015190911681860152604080830151908601526060918201519185019190915290930192608090920191600101613031565b60006020828403121561309257600080fd5b81516001600160401b038111156130a857600080fd5b8201601f810184136130b957600080fd5b80516130c7612b1882612aae565b8082825260208201915060208360071b8501019250868311156130e957600080fd5b6020840193505b82841015612bb1576080848803121561310857600080fd5b61311061281e565b845161311b816126d4565b8152602085015161312b816126d4565b602082810191909152604086810151908301526060808701519083015290835260809094019391909101906130f0565b60006020828403121561316d57600080fd5b815180151581146127a557600080fd5b6020808252602e908201527f4d756c746973696757616c6c65743a2063616e6e6f742063616c6c20696e746560408201526d726e616c2066756e6374696f6e7360901b606082015260800190565b600082516131dd818460208701612957565b9190910192915050565b60208082526024908201527f4d756c746973696757616c6c65743a2065787465726e616c2063616c6c2066616040820152631a5b195960e21b606082015260800190565b808202811582820484141761202357612023612d6c565b6001600160401b03818116838216029081169081811461326457613264612d6c565b5092915050565b8181038181111561202357612023612d6c565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220f5393edd02b5cfb950699c3d9c82962c92d3c1a3d65cd41314b18472faaad8d664736f6c634300081c003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000d5a4ed9d14bc273ce995b4e7e8fa0a21e59f8f3b000000000000000000000000bae2957b8c6cc7d39b7fdf5e82cf8c467b86be400000000000000000000000005a7c04218942c1c9baed35289a9b3edfed6f216f
Deployed Bytecode
0x6080604052600436106101185760003560e01c80638dbcc2e0116100a0578063d47a1a2711610064578063d47a1a271461039b578063d59dafd0146103bb578063dd71105d146103db578063ee22610b146103fb578063ef18374a1461041b57600080fd5b80638dbcc2e0146102e65780639ace38c2146103065780639db5dbe414610339578063a0e67e2b14610359578063c01a8c841461037b57600080fd5b806320ea8d86116100e757806320ea8d861461020b5780632f54bf6e1461022b57806364a197f31461026b5780637065cb481461028b57806380f59a65146102ab57600080fd5b8063025e7c2714610153578063150b7a0214610190578063173825d9146101c95780631afecd1c146101eb57600080fd5b3661014e576040514790349033907f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1590600090a4005b600080fd5b34801561015f57600080fd5b5061017361016e3660046126bb565b610439565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561019c57600080fd5b506101b06101ab3660046126e9565b610463565b6040516001600160e01b03199091168152602001610187565b3480156101d557600080fd5b506101e96101e4366004612788565b6104c5565b005b3480156101f757600080fd5b506101e96102063660046126bb565b6105d1565b34801561021757600080fd5b506101e96102263660046126bb565b610796565b34801561023757600080fd5b5061025b610246366004612788565b60026020526000908152604090205460ff1681565b6040519015158152602001610187565b34801561027757600080fd5b506101e96102863660046127ac565b6109da565b34801561029757600080fd5b506101e96102a6366004612788565b610ab3565b3480156102b757600080fd5b5061025b6102c63660046127d8565b600360209081526000928352604080842090915290825290205460ff1681565b3480156102f257600080fd5b506101e9610301366004612876565b610bd9565b34801561031257600080fd5b506103266103213660046126bb565b610e28565b60405161018797969594939291906129a7565b34801561034557600080fd5b506101e9610354366004612a21565b610f1c565b34801561036557600080fd5b5061036e611012565b6040516101879190612a62565b34801561038757600080fd5b506101e96103963660046126bb565b611074565b3480156103a757600080fd5b506101e96103b6366004612ad1565b611287565b3480156103c757600080fd5b506101e96103d6366004612bbb565b6112e8565b3480156103e757600080fd5b506101e96103f6366004612bbb565b61143d565b34801561040757600080fd5b506101e96104163660046126bb565b6115a8565b34801561042757600080fd5b50600154604051908152602001610187565b6001818154811061044957600080fd5b6000918252602090912001546001600160a01b0316905081565b600083856001600160a01b0316876001600160a01b03167fa05d90f300156ad1b545bc5d8197024456f21d22a708f5af04dd293e3d60525186866040516104ab929190612c0c565b60405180910390a450630a85bd0160e11b95945050505050565b3360009081526002602052604090205460ff166104fd5760405162461bcd60e51b81526004016104f490612c3b565b60405180910390fd5b6001600160a01b0381166105795760405162461bcd60e51b815260206004820152603f60248201527f4d756c746973696757616c6c65743a206f776e6572204164647265737320746860448201527f617420697320746f2062652072656d6f7665642069732072657175697265640060648201526084016104f4565b6001600160a01b03811660009081526002602052604090205460ff166105b15760405162461bcd60e51b81526004016104f490612c7f565b6105ce600482600060405180602001604052806000815250610bd9565b50565b600454819081106105f45760405162461bcd60e51b81526004016104f490612cc6565b816004818154811061060857610608612d10565b6000918252602090912060049091020154610100900460ff1661063d5760405162461bcd60e51b81526004016104f490612d26565b3360009081526002602052604090205460ff1661066c5760405162461bcd60e51b81526004016104f490612c3b565b336001600160a01b03166004848154811061068957610689612d10565b6000918252602090912060049091020154600160501b90046001600160a01b03161461072b5760405162461bcd60e51b8152602060048201526044602482018190527f4d756c746973696757616c6c65743a206f6e6c7920746865206f776e65722063908201527f616e20636c656172207468656972207375626d6974746564207472616e7361636064820152633a34b7b760e11b608482015260a4016104f4565b60006004848154811061074057610740612d10565b60009182526020822060049091020180549215156101000261ff001990931692909217909155604051339185917f2c8d5957f60f56ae0608f50dbce4cda251ec4ed938d7d2ef7e10297719fdf2539190a3505050565b3360009081526002602052604090205460ff166107c55760405162461bcd60e51b81526004016104f490612c3b565b600454819081106107e85760405162461bcd60e51b81526004016104f490612cc6565b81600481815481106107fc576107fc612d10565b6000918252602090912060049091020154610100900460ff166108315760405162461bcd60e51b81526004016104f490612d26565b60006004848154811061084657610846612d10565b600091825260209091206004909102018054909150610100900460ff166108c15760405162461bcd60e51b815260206004820152602960248201527f4d756c746973696757616c6c65743a205472616e73616374696f6e206973206e6044820152686f742061637469766560b81b60648201526084016104f4565b600084815260036020908152604080832033845290915290205460ff166109455760405162461bcd60e51b815260206004820152603260248201527f4d756c746973696757616c6c65743a205472616e73616374696f6e20686173206044820152711b9bdd081899595b8818dbdb999a5c9b595960721b60648201526084016104f4565b805460019082906002906109699084906201000090046001600160401b0316612d82565b82546001600160401b039182166101009390930a9283029190920219909116179055506000848152600360209081526040808320338085529252808320805460ff191690555186927ff0dca620e2e81f7841d07bcc105e1704fb01475b278a9d4c236e1c62945edd5591a350505050565b3360009081526002602052604090205460ff16610a095760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b038216610a2f5760405162461bcd60e51b81526004016104f490612da1565b60008111610a935760405162461bcd60e51b815260206004820152602b60248201527f4d756c746973696757616c6c65743a20457468657220285765692920616d6f7560448201526a1b9d081c995c5d5a5c995960aa1b60648201526084016104f4565b610aaf6000838360405180602001604052806000815250610bd9565b5050565b3360009081526002602052604090205460ff16610ae25760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b038116610b4b5760405162461bcd60e51b815260206004820152602a60248201527f4d756c746973696757616c6c65743a206e6577206f776e6572206164647265736044820152691cc81c995c5d5a5c995960b21b60648201526084016104f4565b6001600160a01b03811660009081526002602052604090205460ff1615610bc05760405162461bcd60e51b8152602060048201526024808201527f4d756c746973696757616c6c65743a206f776e657220616c72656164792065786044820152636973747360e01b60648201526084016104f4565b6105ce6003826000604051806020016040528060008152505b3360009081526002602052604090205460ff16610c085760405162461bcd60e51b81526004016104f490612c3b565b600480546040805160e0810190915290919080876006811115610c2d57610c2d612941565b8152600160208083018290526000604084018190523360608501526001600160a01b038a16608085015260a0840189905260c09093018790528454808301865594835290912082516004909402018054929390929091839160ff191690836006811115610c9c57610c9c612941565b021790555060208201518154604084015160608501516001600160a01b03908116600160501b027fffff0000000000000000000000000000000000000000ffffffffffffffffffff6001600160401b03909316620100000269ffffffffffffffff000019951515610100029590951669ffffffffffffffffff00199094169390931793909317161782556080830151600183018054919092166001600160a01b031990911617905560a0820151600282015560c08201516003820190610d629082612e6b565b5085915060009050806001886006811115610d7f57610d7f612941565b1480610d9c57506002886006811115610d9a57610d9a612941565b145b15610db957600080610dae8a88611dbe565b909550899450925050505b826001600160a01b031684896006811115610dd657610dd6612941565b7f7a9333d5a9c2b79797bf46d7626bd8cda468b400f501bc0ed09cdef2d294c9dd898686338c604051610e0d959493929190612f29565b60405180910390a4610e1e84611074565b5050505050505050565b60048181548110610e3857600080fd5b6000918252602090912060049091020180546001820154600283015460038401805460ff8086169750610100860416956001600160401b0362010000870416956001600160a01b03600160501b9091048116951693929091610e9990612dea565b80601f0160208091040260200160405190810160405280929190818152602001828054610ec590612dea565b8015610f125780601f10610ee757610100808354040283529160200191610f12565b820191906000526020600020905b815481529060010190602001808311610ef557829003601f168201915b5050505050905087565b3360009081526002602052604090205460ff16610f4b5760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b038316610f715760405162461bcd60e51b81526004016104f490612f6d565b6001600160a01b038216610f975760405162461bcd60e51b81526004016104f490612da1565b60008111610fb75760405162461bcd60e51b81526004016104f490612fb3565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261100c600185600084610bd9565b50505050565b6060600180548060200260200160405190810160405280929190818152602001828054801561106a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161104c575b5050505050905090565b3360009081526002602052604090205460ff166110a35760405162461bcd60e51b81526004016104f490612c3b565b600454819081106110c65760405162461bcd60e51b81526004016104f490612cc6565b81600481815481106110da576110da612d10565b6000918252602090912060049091020154610100900460ff1661110f5760405162461bcd60e51b81526004016104f490612d26565b6000838152600360209081526040808320338452909152902054839060ff16156111a15760405162461bcd60e51b815260206004820152603b60248201527f4d756c746973696757616c6c65743a207472616e73616374696f6e20616c726560448201527f61647920636f6e6669726d65642062792074686973206f776e6572000000000060648201526084016104f4565b6000600485815481106111b6576111b6612d10565b600091825260208083208884526003825260408085203386529092529083208054600160ff19909116811790915560049290920201805490935061120a91620100009091046001600160401b031690612ff8565b82546001600160401b038216620100000269ffffffffffffffff00001982168117855560405192935060ff90811691161790879033907f5cbe105e36805f7820e291f799d5794ff948af2a5f664e580382defb6339004190600090a36112708282611fa5565b1561127e5761127e876115a8565b50505050505050565b3360009081526002602052604090205460ff166112b65760405162461bcd60e51b81526004016104f490612c3b565b6000816040516020016112c99190613017565b6040516020818303038152906040529050610aaf600530600084610bd9565b3360009081526002602052604090205460ff166113175760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b03841661133d5760405162461bcd60e51b81526004016104f490612f6d565b6001600160a01b0383166113af5760405162461bcd60e51b815260206004820152603360248201527f4d756c746973696757616c6c65743a2074686520746f6b656e6f776e657273206044820152721859191c995cdcc81a5cc81c995c5d5a5c9959606a1b60648201526084016104f4565b6001600160a01b0382166113d55760405162461bcd60e51b81526004016104f490612da1565b6040516001600160a01b038085166024830152831660448201526064810182905260009060840160408051601f198184030181529190526020810180516001600160e01b0316632142170760e11b1790529050611436600286600084610bd9565b5050505050565b3360009081526002602052604090205460ff1661146c5760405162461bcd60e51b81526004016104f490612c3b565b6001600160a01b0384166114925760405162461bcd60e51b81526004016104f490612f6d565b6001600160a01b0383166115055760405162461bcd60e51b815260206004820152603460248201527f4d756c746973696757616c6c65743a2074686520746f6b656e2d6f776e657273604482015273081859191c995cdcc81a5cc81c995c5d5a5c995960621b60648201526084016104f4565b6001600160a01b03821661152b5760405162461bcd60e51b81526004016104f490612da1565b6000811161154b5760405162461bcd60e51b81526004016104f490612fb3565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611436600186600084610bd9565b600454819081106115cb5760405162461bcd60e51b81526004016104f490612cc6565b81600481815481106115df576115df612d10565b6000918252602090912060049091020154610100900460ff166116145760405162461bcd60e51b81526004016104f490612d26565b61161c612029565b3360009081526002602052604090205460ff1661164b5760405162461bcd60e51b81526004016104f490612c3b565b60006004848154811061166057611660612d10565b6000918252602090912060049091020180549091506001600160401b03620100008204169060ff166116928282611fa5565b6116fc5760405162461bcd60e51b815260206004820152603560248201527f4d756c746973696757616c6c65743a20696e73756666696369656e7420636f6e6044820152746669726d6174696f6e7320746f206578656375746560581b60648201526084016104f4565b600183015460028401546003850180546001600160a01b03909316926000919061172590612dea565b80601f016020809104026020016040519081016040528092919081815260200182805461175190612dea565b801561179e5780601f106117735761010080835404028352916020019161179e565b820191906000526020600020905b81548152906001019060200180831161178157829003601f168201915b5093945086935060009250829150600590508760068111156117c2576117c2612941565b03611b23576000848060200190518101906117dd9190613080565b805190915060005b81811015611b1f57600083828151811061180157611801612d10565b6020026020010151905060006001600160a01b031681602001516001600160a01b031603611959576060810151156118a15760405162461bcd60e51b815260206004820152603b60248201527f42617463685472616e736665723a20455448207472616e73666572207769746860448201527f20546f6b656e496420646f65736e2774206d616b652073656e7365000000000060648201526084016104f4565b805160408083015190516000926001600160a01b031691908381818185875af1925050503d80600081146118f1576040519150601f19603f3d011682016040523d82523d6000602084013e6118f6565b606091505b50509050806119535760405162461bcd60e51b8152602060048201526024808201527f42617463685472616e736665723a204574686572207472616e736665722066616044820152631a5b195960e21b60648201526084016104f4565b50611ab8565b8060600151600003611a425760208101518151604080840151905163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af11580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e5919061315b565b611a3d5760405162461bcd60e51b8152602060048201526024808201527f42617463685472616e736665723a204552433230207472616e736665722066616044820152631a5b195960e21b60648201526084016104f4565b611ab8565b602081015181516060830151604051632142170760e11b81523060048201526001600160a01b03928316602482015260448101919091529116906342842e0e90606401600060405180830381600087803b158015611a9f57600080fd5b505af1158015611ab3573d6000803e3d6000fd5b505050505b806060015181602001516001600160a01b031682600001516001600160a01b03167f11545b22e85dd851103fdaeff84f4db960c8ea9ef39898c3f2b32b8e14913bfd8460400151604051611b0e91815260200190565b60405180910390a4506001016117e5565b5050505b6003876006811115611b3757611b37612941565b03611b4b57611b46868d612053565b611b6e565b6004876006811115611b5f57611b5f612941565b03611b6e57611b6e868d6122d0565b6000876006811115611b8257611b82612941565b1480611b9f57506006876006811115611b9d57611b9d612941565b145b15611c4c57306001600160a01b03871603611bcc5760405162461bcd60e51b81526004016104f49061317d565b6000866001600160a01b03168686604051611be791906131cb565b60006040518083038185875af1925050503d8060008114611c24576040519150601f19603f3d011682016040523d82523d6000602084013e611c29565b606091505b5050905080611c4a5760405162461bcd60e51b81526004016104f4906131e7565b505b6001876006811115611c6057611c60612941565b1480611c7d57506002876006811115611c7b57611c7b612941565b145b15611d4157306001600160a01b03871603611caa5760405162461bcd60e51b81526004016104f49061317d565b6000866001600160a01b03168686604051611cc591906131cb565b60006040518083038185875af1925050503d8060008114611d02576040519150601f19603f3d011682016040523d82523d6000602084013e611d07565b606091505b5050905080611d285760405162461bcd60e51b81526004016104f4906131e7565b600080611d358a88611dbe565b90965089955093505050505b885461ff00191689556001600160a01b0383168c886006811115611d6757611d67612941565b7f8486d3d18fdaaf4d3cd166a7275bd95df5e8087a2cc662f6c33164f3052ea6be888686338b604051611d9e959493929190612f29565b60405180910390a4505050505050505050611db96001600055565b505050565b6000806001846006811115611dd557611dd5612941565b03611e8f57825160441480611deb575082516064145b611e565760405162461bcd60e51b815260206004820152603660248201527f4d756c746973696757616c6c65743a20696e76616c69642064617461206c656e60448201527533ba34103337b91022a9219918103a3930b739b332b960511b60648201526084016104f4565b8251604403611e7057505060248101516044820151611f9e565b8251606403611e8a57505060448101516064820151611f9e565b611f9e565b6002846006811115611ea357611ea3612941565b03611f30578251606414611f1f5760405162461bcd60e51b815260206004820152603760248201527f4d756c746973696757616c6c65743a20696e76616c69642064617461206c656e60448201527f67746820666f7220455243373231207472616e7366657200000000000000000060648201526084016104f4565b505060448101516064820151611f9e565b60405162461bcd60e51b815260206004820152603e60248201527f4d756c746973696757616c6c65743a20756e737570706f72746564207472616e60448201527f73616374696f6e207479706520666f722064617461206465636f64696e67000060648201526084016104f4565b9250929050565b60006003826006811115611fbb57611fbb612941565b1480611fd857506004826006811115611fd657611fd6612941565b145b1561200857600154611feb90600261322b565b611ff6846003613242565b6001600160401b031610159050612023565b600154612016846002613242565b6001600160401b03161190505b92915050565b60026000540361204c57604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b3360009081526002602052604090205460ff166120825760405162461bcd60e51b81526004016104f490612c3b565b600454819081106120a55760405162461bcd60e51b81526004016104f490612cc6565b81600481815481106120b9576120b9612d10565b6000918252602090912060049091020154610100900460ff166120ee5760405162461bcd60e51b81526004016104f490612d26565b60006004848154811061210357612103612d10565b60009182526020909120600154600490920201915061212390600261322b565b815461213f906201000090046001600160401b03166003613242565b6001600160401b031610156121bc5760405162461bcd60e51b815260206004820152603760248201527f4d756c746973696757616c6c65743a20696e73756666696369656e7420636f6e60448201527f6669726d6174696f6e7320746f20616464206f776e657200000000000000000060648201526084016104f4565b6001600160a01b03851660009081526002602052604090205460ff16156122395760405162461bcd60e51b815260206004820152602b60248201527f4d756c746973696757616c6c65743a206164647265737320697320616c72656160448201526a323c9030b71037bbb732b960a91b60648201526084016104f4565b612241612636565b6001600160a01b038516600081815260026020526040808220805460ff19166001908117909155805480820182559083527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03191684179055517f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a25050505050565b3360009081526002602052604090205460ff166122ff5760405162461bcd60e51b81526004016104f490612c3b565b600454819081106123225760405162461bcd60e51b81526004016104f490612cc6565b816004818154811061233657612336612d10565b6000918252602090912060049091020154610100900460ff1661236b5760405162461bcd60e51b81526004016104f490612d26565b60006004848154811061238057612380612d10565b6000918252602090912060015460049092020191506123a090600261322b565b81546123bc906201000090046001600160401b03166003613242565b6001600160401b031610156124395760405162461bcd60e51b815260206004820152603a60248201527f4d756c746973696757616c6c65743a20696e73756666696369656e7420636f6e60448201527f6669726d6174696f6e7320746f2072656d6f7665206f776e657200000000000060648201526084016104f4565b6001600160a01b03851660009081526002602052604090205460ff166124715760405162461bcd60e51b81526004016104f490612c7f565b60018054116124d75760405162461bcd60e51b815260206004820152602c60248201527f4d756c746973696757616c6c65743a2063616e6e6f742072656d6f766520746860448201526b32903630b9ba1037bbb732b960a11b60648201526084016104f4565b6124df612636565b6001600160a01b0385166000908152600260205260408120805460ff191690555b6001548110156125fa57856001600160a01b03166001828154811061252757612527612d10565b6000918252602090912001546001600160a01b0316036125f2576001805461255090829061326b565b8154811061256057612560612d10565b600091825260209091200154600180546001600160a01b03909216918390811061258c5761258c612d10565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060018054806125cb576125cb61327e565b600082815260209020810160001990810180546001600160a01b03191690550190556125fa565b600101612500565b506040516001600160a01b038616907f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90600090a25050505050565b60045460005b8181101561268e5760006004828154811061265957612659612d10565b600091825260209091206004909102018054909150610100900460ff161561268557805461ff00191681555b5060010161263c565b506040517fbbb8e378f092289f6721a3c81d4263fcbfee5d004ba72a2f80ac4c118c3975cc90600090a150565b6000602082840312156126cd57600080fd5b5035919050565b6001600160a01b03811681146105ce57600080fd5b60008060008060006080868803121561270157600080fd5b853561270c816126d4565b9450602086013561271c816126d4565b93506040860135925060608601356001600160401b0381111561273e57600080fd5b8601601f8101881361274f57600080fd5b80356001600160401b0381111561276557600080fd5b88602082840101111561277757600080fd5b959894975092955050506020019190565b60006020828403121561279a57600080fd5b81356127a5816126d4565b9392505050565b600080604083850312156127bf57600080fd5b82356127ca816126d4565b946020939093013593505050565b600080604083850312156127eb57600080fd5b8235915060208301356127fd816126d4565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b038111828210171561284057612840612808565b60405290565b604051601f8201601f191681016001600160401b038111828210171561286e5761286e612808565b604052919050565b6000806000806080858703121561288c57600080fd5b84356007811061289b57600080fd5b935060208501356128ab816126d4565b92506040850135915060608501356001600160401b038111156128cd57600080fd5b8501601f810187136128de57600080fd5b80356001600160401b038111156128f7576128f7612808565b61290a601f8201601f1916602001612846565b81815288602083850101111561291f57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b634e487b7160e01b600052602160045260246000fd5b60005b8381101561297257818101518382015260200161295a565b50506000910152565b60008151808452612993816020860160208601612957565b601f01601f19169290920160200192915050565b6000600789106129c757634e487b7160e01b600052602160045260246000fd5b88825287151560208301526001600160401b03871660408301526001600160a01b0386811660608401528516608083015260a0820184905260e060c08301819052612a149083018461297b565b9998505050505050505050565b600080600060608486031215612a3657600080fd5b8335612a41816126d4565b92506020840135612a51816126d4565b929592945050506040919091013590565b602080825282518282018190526000918401906040840190835b81811015612aa35783516001600160a01b0316835260209384019390920191600101612a7c565b509095945050505050565b60006001600160401b03821115612ac757612ac7612808565b5060051b60200190565b600060208284031215612ae357600080fd5b81356001600160401b03811115612af957600080fd5b8201601f81018413612b0a57600080fd5b8035612b1d612b1882612aae565b612846565b8082825260208201915060208360071b850101925086831115612b3f57600080fd5b6020840193505b82841015612bb15760808488031215612b5e57600080fd5b612b6661281e565b8435612b71816126d4565b81526020850135612b81816126d4565b60208281019190915260408681013590830152606080870135908301529083526080909401939190910190612b46565b9695505050505050565b60008060008060808587031215612bd157600080fd5b8435612bdc816126d4565b93506020850135612bec816126d4565b92506040850135612bfc816126d4565b9396929550929360600135925050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60208082526024908201527f4d756c746973696757616c6c65743a204e6f742061206d756c7469736967206f6040820152633bb732b960e11b606082015260800190565b60208082526027908201527f4d756c746973696757616c6c65743a2061646472657373206973206e6f742061604082015266371037bbb732b960c91b606082015260800190565b6020808252602a908201527f4d756c746973696757616c6c65743a205472616e73616374696f6e20646f6573604082015269081b9bdd08195e1a5cdd60b21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60208082526026908201527f4d756c746973696757616c6c65743a205472616e73616374696f6e206e6f742060408201526561637469766560d01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03828116828216039081111561202357612023612d6c565b60208082526029908201527f4d756c746973696757616c6c65743a2072656365697665722061646472657373604082015268081c995c5d5a5c995960ba1b606082015260800190565b600181811c90821680612dfe57607f821691505b602082108103612e1e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611db957806000526020600020601f840160051c81016020851015612e4b5750805b601f840160051c820191505b818110156114365760008155600101612e57565b81516001600160401b03811115612e8457612e84612808565b612e9881612e928454612dea565b84612e24565b6020601f821160018114612ecc5760008315612eb45750848201515b600019600385901b1c1916600184901b178455611436565b600084815260208120601f198516915b82811015612efc5787850151825560209485019460019092019101612edc565b5084821015612f1a5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b8581526001600160a01b038581166020830152604082018590528316606082015260a060808201819052600090612f629083018461297b565b979650505050505050565b60208082526026908201527f4d756c746973696757616c6c65743a20746f6b656e20616464726573732072656040820152651c5d5a5c995960d21b606082015260800190565b60208082526025908201527f4d756c746973696757616c6c65743a20746f6b656e20616d6f756e74207265716040820152641d5a5c995960da1b606082015260800190565b6001600160401b03818116838216019081111561202357612023612d6c565b602080825282518282018190526000918401906040840190835b81811015612aa357835180516001600160a01b03908116855260208083015190911681860152604080830151908601526060918201519185019190915290930192608090920191600101613031565b60006020828403121561309257600080fd5b81516001600160401b038111156130a857600080fd5b8201601f810184136130b957600080fd5b80516130c7612b1882612aae565b8082825260208201915060208360071b8501019250868311156130e957600080fd5b6020840193505b82841015612bb1576080848803121561310857600080fd5b61311061281e565b845161311b816126d4565b8152602085015161312b816126d4565b602082810191909152604086810151908301526060808701519083015290835260809094019391909101906130f0565b60006020828403121561316d57600080fd5b815180151581146127a557600080fd5b6020808252602e908201527f4d756c746973696757616c6c65743a2063616e6e6f742063616c6c20696e746560408201526d726e616c2066756e6374696f6e7360901b606082015260800190565b600082516131dd818460208701612957565b9190910192915050565b60208082526024908201527f4d756c746973696757616c6c65743a2065787465726e616c2063616c6c2066616040820152631a5b195960e21b606082015260800190565b808202811582820484141761202357612023612d6c565b6001600160401b03818116838216029081169081811461326457613264612d6c565b5092915050565b8181038181111561202357612023612d6c565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220f5393edd02b5cfb950699c3d9c82962c92d3c1a3d65cd41314b18472faaad8d664736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000d5a4ed9d14bc273ce995b4e7e8fa0a21e59f8f3b000000000000000000000000bae2957b8c6cc7d39b7fdf5e82cf8c467b86be400000000000000000000000005a7c04218942c1c9baed35289a9b3edfed6f216f
-----Decoded View---------------
Arg [0] : _owners (address[]): 0xd5A4Ed9d14bc273ce995B4E7E8fa0a21E59F8F3b,0xBae2957B8c6CC7D39b7fDF5e82Cf8C467B86Be40,0x5a7c04218942c1c9baED35289A9b3eDfEd6F216F
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [2] : 000000000000000000000000d5a4ed9d14bc273ce995b4e7e8fa0a21e59f8f3b
Arg [3] : 000000000000000000000000bae2957b8c6cc7d39b7fdf5e82cf8c467b86be40
Arg [4] : 0000000000000000000000005a7c04218942c1c9baed35289a9b3edfed6f216f
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.