Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0xf230d7cd0de9630d7f5d4b757e6f8fca2f3700ef.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
- Contract name:
- PluginMap
- Optimization enabled
- true
- Compiler version
- v0.8.18+commit.87f61d96
- Optimization runs
- 1000
- Verified at
- 2023-07-24T18:07:15.661204Z
@thirdweb-dev/contracts/extension/plugin/PluginMap.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "../interface/plugin/IPluginMap.sol";
import "../../openzeppelin-presets/utils/EnumerableSet.sol";
/**
* @author thirdweb.com
*/
contract PluginMap is IPluginMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
EnumerableSet.Bytes32Set private allSelectors;
mapping(address => EnumerableSet.Bytes32Set) private selectorsForPlugin;
mapping(bytes4 => Plugin) private pluginForSelector;
/*///////////////////////////////////////////////////////////////
Constructor + initializer logic
//////////////////////////////////////////////////////////////*/
constructor(Plugin[] memory _pluginsToAdd) {
uint256 len = _pluginsToAdd.length;
for (uint256 i = 0; i < len; i += 1) {
_setPlugin(_pluginsToAdd[i]);
}
}
/*///////////////////////////////////////////////////////////////
View functions
//////////////////////////////////////////////////////////////*/
/// @dev View address of the plugged-in functionality contract for a given function signature.
function getPluginForFunction(bytes4 _selector) public view returns (address) {
address _pluginAddress = pluginForSelector[_selector].pluginAddress;
require(_pluginAddress != address(0), "Map: No plugin available for selector");
return _pluginAddress;
}
/// @dev View all funtionality as list of function signatures.
function getAllFunctionsOfPlugin(address _pluginAddress) external view returns (bytes4[] memory registered) {
uint256 len = selectorsForPlugin[_pluginAddress].length();
registered = new bytes4[](len);
for (uint256 i = 0; i < len; i += 1) {
registered[i] = bytes4(selectorsForPlugin[_pluginAddress].at(i));
}
}
/// @dev View all funtionality existing on the contract.
function getAllPlugins() external view returns (Plugin[] memory _plugins) {
uint256 len = allSelectors.length();
_plugins = new Plugin[](len);
for (uint256 i = 0; i < len; i += 1) {
bytes4 selector = bytes4(allSelectors.at(i));
_plugins[i] = pluginForSelector[selector];
}
}
/*///////////////////////////////////////////////////////////////
Internal functions
//////////////////////////////////////////////////////////////*/
/// @dev Add functionality to the contract.
function _setPlugin(Plugin memory _plugin) internal {
require(allSelectors.add(bytes32(_plugin.functionSelector)), "Map: Selector exists");
require(
_plugin.functionSelector == bytes4(keccak256(abi.encodePacked(_plugin.functionSignature))),
"Map: Incorrect selector"
);
pluginForSelector[_plugin.functionSelector] = _plugin;
selectorsForPlugin[_plugin.pluginAddress].add(bytes32(_plugin.functionSelector));
emit PluginSet(_plugin.functionSelector, _plugin.functionSignature, _plugin.pluginAddress);
}
}
@thirdweb-dev/contracts/extension/interface/plugin/IPluginMap.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.11;
/// @author thirdweb
interface IPluginMap {
/**
* @notice An interface to describe a plug-in.
*
* @param functionSelector 4-byte function selector.
* @param functionSignature Function representation as a string. E.g. "transfer(address,address,uint256)"
* @param pluginAddress Address of the contract containing the function.
*/
struct Plugin {
bytes4 functionSelector;
string functionSignature;
address pluginAddress;
}
/// @dev Emitted when a function selector is mapped to a particular plug-in smart contract, during construction of Map.
event PluginSet(bytes4 indexed functionSelector, string indexed functionSignature, address indexed pluginAddress);
/// @dev Returns the plug-in contract for a given function.
function getPluginForFunction(bytes4 functionSelector) external view returns (address);
/// @dev Returns all functions that are mapped to the given plug-in contract.
function getAllFunctionsOfPlugin(address pluginAddress) external view returns (bytes4[] memory);
/// @dev Returns all plug-ins known by Map.
function getAllPlugins() external view returns (Plugin[] memory);
}
@thirdweb-dev/contracts/openzeppelin-presets/utils/EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}
Compiler Settings
{"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"]}},"optimizer":{"runs":1000,"enabled":true},"libraries":{}}
Contract ABI
[{"type":"constructor","inputs":[{"type":"tuple[]","name":"_pluginsToAdd","internalType":"struct IPluginMap.Plugin[]","components":[{"type":"bytes4"},{"type":"string"},{"type":"address"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes4[]","name":"registered","internalType":"bytes4[]"}],"name":"getAllFunctionsOfPlugin","inputs":[{"type":"address","name":"_pluginAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"_plugins","internalType":"struct IPluginMap.Plugin[]","components":[{"type":"bytes4"},{"type":"string"},{"type":"address"}]}],"name":"getAllPlugins","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getPluginForFunction","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"event","name":"PluginSet","inputs":[{"type":"bytes4","name":"functionSelector","indexed":true},{"type":"string","name":"functionSignature","indexed":true},{"type":"address","name":"pluginAddress","indexed":true}],"anonymous":false}]
Contract Creation Code
0x608080604052346200058e5762000cfd908138038092620000218284620005a8565b823960208183810103126200058e578051916001600160401b0383116200058e57808201601f8484010112156200058e5781830151926001600160401b038411620003b1578360051b91604051946200007e6020850187620005a8565b855260208501918185016020858388010101116200058e57602081860101925b6020858388010101841062000467578680516000915b818310620000cc576040516105fb9081620007028239f35b8051831015620004515760208360051b8201015192620000f663ffffffff60e01b855116620005f1565b156200040c5763ffffffff60e01b8451166020850151604051906200013b602083816200012d8183019586815193849201620005cc565b8101038085520183620005a8565b905190206001600160e01b03191603620003c75763ffffffff60e01b84511660005260036020526040600020845160e01c63ffffffff19825416178155602085015194855160018060401b038111620003b1576001830154600181811c91168015620003a6575b60208210146200039057601f811162000344575b506020601f8211600114620002ce5781929394959697600092620002c2575b50508160011b916000199060031b1c19161760018301555b60408181018051600294850180546001600160a01b0319166001600160a01b0392831690811790915560009081526020959095529190932082516200026d929162000243916001600160e01b0319169062000674565b50602063ffffffff60e01b84511693015193511692602060405192828480945193849201620005cc565b8101039020907f3773a9e2d436c841075ce219f31cf6a8f4947415b7ed528ab2e6ca69f4ee4d6f600080a460018101809111620002ac579190620000b4565b634e487b7160e01b600052601160045260246000fd5b015190508780620001d5565b6001840160005260206000209060005b601f19841681106200032b5750600193949596979883601f1981161062000311575b505050811b016001830155620001ed565b015160001960f88460031b161c1916905587808062000300565b9091602060018192858d015181550193019101620002de565b600184016000526020600020601f830160051c81016020841062000388575b601f830160051c820181106200037b575050620001b6565b6000815560010162000363565b508062000363565b634e487b7160e01b600052602260045260246000fd5b90607f1690620001a2565b634e487b7160e01b600052604160045260246000fd5b60405162461bcd60e51b815260206004820152601760248201527f4d61703a20496e636f72726563742073656c6563746f720000000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601460248201527f4d61703a2053656c6563746f72206578697374730000000000000000000000006044820152606490fd5b634e487b7160e01b600052603260045260246000fd5b83516001600160401b0381116200058e576060878401820185890103601f1901126200058e5760405190606082016001600160401b0381118382101762000593576040528784018101602001516001600160e01b0319811681036200058e578252878401810160400151906001600160401b0382116200058e57858901603f8383888d0101010112156200058e578885018101820160200151916001600160401b0383116200059357604051906200052a601f8501601f191660200183620005a8565b838252878b01878c01840182018501604001116200058e576060938b60406200055e93868b602088019401010101620005cc565b60208401528885010101516001600160a01b03811681036200058e5760408201528152602093840193016200009e565b600080fd5b60246000634e487b7160e01b81526041600452fd5b601f909101601f19168101906001600160401b03821190821017620003b157604052565b60005b838110620005e05750506000910152565b8181015183820152602001620005cf565b6000818152600160205260408120546200066f578054680100000000000000008110156200065b576001810180835581101562000647579082604092828052602083200155805492815260016020522055600190565b634e487b7160e01b82526032600452602482fd5b634e487b7160e01b82526041600452602482fd5b905090565b91906001830160009082825280602052604082205415600014620006fb5784549468010000000000000000861015620006e75760018601808255861015620006d357836040949596828552602085200155549382526020522055600190565b634e487b7160e01b83526032600452602483fd5b634e487b7160e01b83526041600452602483fd5b5092505056fe60406080815260048036101561001457600080fd5b600060e08135811c9081635c573f2e146103f25781636b86400e14610127575063a520a38a1461004357600080fd5b346101245760203660031901126101245781356001600160e01b0319811680910361012057815260036020528290206002015473ffffffffffffffffffffffffffffffffffffffff1690811561009d575060209151908152f35b60849060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602560248201527f4d61703a204e6f20706c7567696e20617661696c61626c6520666f722073656c60448201527f6563746f720000000000000000000000000000000000000000000000000000006064820152fd5b5080fd5b80fd5b9293905034610120578160031936011261012057919290805461014981610583565b9261015685519485610561565b818452601f19958661016784610583565b01845b8181106103c1575050835b83811061024f57505050508251926020908185019282865284518094528186019083838660051b89010196019781935b8685106101b25788880389f35b90919293949596603f19898203018552868a51916001600160e01b031983511681528482840151606090818585015280518092850152885b828110610237575050608081840181018990529486015173ffffffffffffffffffffffffffffffffffffffff16868401529c83019c601f01160190910197969560010194019291906101a5565b818101860151858201608001528c95899450016101ea565b6001600160e01b0319979694959780827f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301541687526020600381528688209087519261029b8461052f565b8254861b1683526001908183018951928b9180549081831c9183811680156103b7575b86841081146103a357838852908115610382575060011461034b575b5050509173ffffffffffffffffffffffffffffffffffffffff9391610303826002950383610561565b85015201541686820152610317828a61059b565b52610322818961059b565b5060018101809111610338579694939596610175565b602486601185634e487b7160e01b835252fd5b8d52838d208d93509091905b82841061036f575050508201810181610303846102da565b8054868501860152928401928101610357565b60ff1916868801525050151560051b840183019150829050610303846102da565b5060248f60228e634e487b7160e01b835252fd5b92607f16926102be565b6020908896979998516103d38161052f565b888152826060818301528989830152828c01015201979594969761016a565b505090346101205760208060031936011261052b5781359273ffffffffffffffffffffffffffffffffffffffff84168094036101245790939291828252600290818652848320549061044382610583565b9261045087519485610561565b82845261045c83610583565b8489019690601f1901368837855b8481106104bb57505050505083519485948186019282875251809352850193925b82811061049a57505050500390f35b83516001600160e01b0319168552869550938101939281019260010161048b565b81879698999a975282875289862080548210156105185786526001600160e01b0319818888200154166104ee828a61059b565b52600181018091116105055798979694959861046a565b602486601186634e487b7160e01b835252fd5b602487603287634e487b7160e01b835252fd5b8280fd5b6060810190811067ffffffffffffffff82111761054b57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761054b57604052565b67ffffffffffffffff811161054b5760051b60200190565b80518210156105af5760209160051b010190565b634e487b7160e01b600052603260045260246000fdfea2646970667358221220523ecfaaa31b232a667b46f85f7e7553bd781959c126bae8e4d0a528c9f1674d64736f6c6343000812003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008e000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010c00000000000000000000000000000000000000000000000000000000000001160000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000012a0000000000000000000000000000000000000000000000000000000000000134000000000000000000000000000000000000000000000000000000000000013e000000000000000000000000000000000000000000000000000000000000014c00000000000000000000000000000000000000000000000000000000000001560000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000016c00000000000000000000000000000000000000000000000000000000000001760000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000019800000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001fa0000000000000000000000000000000000000000000000000000000000000204000000000000000000000000000000000000000000000000000000000000020e048dd77df0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000002c617070726f76654275796572466f724c697374696e672875696e743235362c616464726573732c626f6f6c290000000000000000000000000000000000000000ea8f9a3c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c530000000000000000000000000000000000000000000000000000000000000032617070726f766543757272656e6379466f724c697374696e672875696e743235362c616464726573732c75696e74323536290000000000000000000000000000704232dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000003762757946726f6d4c697374696e672875696e743235362c616464726573732c75696e743235362c616464726573732c75696e7432353629000000000000000000305a67a80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000001663616e63656c4c697374696e672875696e743235362900000000000000000000746415b50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000004d6372656174654c697374696e672828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c292900000000000000000000000000000000000000fb14079d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000002863757272656e63795072696365466f724c697374696e672875696e743235362c6164647265737329000000000000000000000000000000000000000000000000c5275fb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000001f676574416c6c4c697374696e67732875696e743235362c75696e74323536290031654b4d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c530000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c69644c697374696e67732875696e743235362c75696e743235362900000000000000000000000000000000000000000000000000000000107a274a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c5300000000000000000000000000000000000000000000000000000000000000136765744c697374696e672875696e7432353629000000000000000000000000009cfbe2a60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000002a69734275796572417070726f766564466f724c697374696e672875696e743235362c616464726573732900000000000000000000000000000000000000000000a85190470000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000002d697343757272656e6379417070726f766564466f724c697374696e672875696e743235362c6164647265737329000000000000000000000000000000000000004a36e5f70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000004373656c6563744c697374696e67732875696e743235362c75696e74382c616464726573732c616464726573732c75696e743235362c75696e7433322c75696e743332290000000000000000000000000000000000000000000000000000000000c78b616c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000000f746f74616c4c697374696e67732829000000000000000000000000000000000007b677580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c5300000000000000000000000000000000000000000000000000000000000000557570646174654c697374696e672875696e743235362c28616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c292900000000000000000000000f5928ad0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000001d76616c69646174654c697374696e6742617369632875696e74323536290000003eec10920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008193b178f600be94779626924997fedc792c2c53000000000000000000000000000000000000000000000000000000000000001c76616c69646174654c697374696e6746756c6c2875696e7432353629000000000858e5ad0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000001d626964496e41756374696f6e2875696e743235362c75696e743235362900000096b5a7550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000001663616e63656c41756374696f6e2875696e743235362900000000000000000000a286b5a20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a356980000000000000000000000000000000000000000000000000000000000000017636f6c6c65637441756374696f6e2875696e7432353629000000000000000000ebf05a620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e5061796f75742875696e743235362900000003a54fe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e546f6b656e732875696e743235362900000016654d400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000005c63726561746541756374696f6e2828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743235362c75696e7436342c75696e7436342c75696e7436342c75696e743634292900000000c291537c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000001f676574416c6c41756374696f6e732875696e743235362c75696e7432353629007b0638010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a356980000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c696441756374696f6e732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000078bd79350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000001367657441756374696f6e2875696e7432353629000000000000000000000000006891939d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000001667657457696e6e696e674269642875696e7432353629000000000000000000001389b1170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a356980000000000000000000000000000000000000000000000000000000000000019697341756374696f6e457870697265642875696e7432353629000000000000002eb566bd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000002069734e657757696e6e696e674269642875696e743235362c75696e7432353629e2283ed80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000004c73656c65637441756374696f6e732875696e743235362c75696e7431362c616464726573732c616464726573732c75696e743235362c616464726573732c75696e7433322c75696e74333229000000000000000000000000000000000000000016002f4a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000000f746f74616c41756374696f6e7328290000000000000000000000000000000000cde0b4f90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000003e52cb16834ac2097a79ef02aade636bc5a35698000000000000000000000000000000000000000000000000000000000000001876616c696461746541756374696f6e2875696e74323536290000000000000000c815729d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd00000000000000000000000000000000000000000000000000000000000000146163636570744f666665722875696e7432353629000000000000000000000000ef706adf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd000000000000000000000000000000000000000000000000000000000000001463616e63656c4f666665722875696e7432353629000000000000000000000000c1edcfbe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd000000000000000000000000000000000000000000000000000000000000001d676574416c6c4f66666572732875696e743235362c75696e743235362900000091940b3e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd0000000000000000000000000000000000000000000000000000000000000022676574416c6c56616c69644f66666572732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000000004579268a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd00000000000000000000000000000000000000000000000000000000000000116765744f666665722875696e7432353629000000000000000000000000000000016767fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd000000000000000000000000000000000000000000000000000000000000003c6d616b654f666665722828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e74323536292900000000cbd69d6b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd000000000000000000000000000000000000000000000000000000000000005173656c6563744f66666572732875696e743235362c75696e74382c616464726573732c616464726573732c75696e743235362c616464726573732c616464726573732c75696e7433322c75696e74333229000000000000000000000000000000a9fd8ed1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd000000000000000000000000000000000000000000000000000000000000000d746f74616c4f6666657273282900000000000000000000000000000000000000336607f6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd000000000000000000000000000000000000000000000000000000000000001b76616c69646174654f6666657242617369632875696e74323536290000000000d31d5c27000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c13fd63fae16591c241c89cac5279247b0ac02dd000000000000000000000000000000000000000000000000000000000000001a76616c69646174654f6666657246756c6c2875696e7432353629000000000000
Deployed ByteCode
0x60406080815260048036101561001457600080fd5b600060e08135811c9081635c573f2e146103f25781636b86400e14610127575063a520a38a1461004357600080fd5b346101245760203660031901126101245781356001600160e01b0319811680910361012057815260036020528290206002015473ffffffffffffffffffffffffffffffffffffffff1690811561009d575060209151908152f35b60849060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602560248201527f4d61703a204e6f20706c7567696e20617661696c61626c6520666f722073656c60448201527f6563746f720000000000000000000000000000000000000000000000000000006064820152fd5b5080fd5b80fd5b9293905034610120578160031936011261012057919290805461014981610583565b9261015685519485610561565b818452601f19958661016784610583565b01845b8181106103c1575050835b83811061024f57505050508251926020908185019282865284518094528186019083838660051b89010196019781935b8685106101b25788880389f35b90919293949596603f19898203018552868a51916001600160e01b031983511681528482840151606090818585015280518092850152885b828110610237575050608081840181018990529486015173ffffffffffffffffffffffffffffffffffffffff16868401529c83019c601f01160190910197969560010194019291906101a5565b818101860151858201608001528c95899450016101ea565b6001600160e01b0319979694959780827f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301541687526020600381528688209087519261029b8461052f565b8254861b1683526001908183018951928b9180549081831c9183811680156103b7575b86841081146103a357838852908115610382575060011461034b575b5050509173ffffffffffffffffffffffffffffffffffffffff9391610303826002950383610561565b85015201541686820152610317828a61059b565b52610322818961059b565b5060018101809111610338579694939596610175565b602486601185634e487b7160e01b835252fd5b8d52838d208d93509091905b82841061036f575050508201810181610303846102da565b8054868501860152928401928101610357565b60ff1916868801525050151560051b840183019150829050610303846102da565b5060248f60228e634e487b7160e01b835252fd5b92607f16926102be565b6020908896979998516103d38161052f565b888152826060818301528989830152828c01015201979594969761016a565b505090346101205760208060031936011261052b5781359273ffffffffffffffffffffffffffffffffffffffff84168094036101245790939291828252600290818652848320549061044382610583565b9261045087519485610561565b82845261045c83610583565b8489019690601f1901368837855b8481106104bb57505050505083519485948186019282875251809352850193925b82811061049a57505050500390f35b83516001600160e01b0319168552869550938101939281019260010161048b565b81879698999a975282875289862080548210156105185786526001600160e01b0319818888200154166104ee828a61059b565b52600181018091116105055798979694959861046a565b602486601186634e487b7160e01b835252fd5b602487603287634e487b7160e01b835252fd5b8280fd5b6060810190811067ffffffffffffffff82111761054b57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761054b57604052565b67ffffffffffffffff811161054b5760051b60200190565b80518210156105af5760209160051b010190565b634e487b7160e01b600052603260045260246000fdfea2646970667358221220523ecfaaa31b232a667b46f85f7e7553bd781959c126bae8e4d0a528c9f1674d64736f6c63430008120033