Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- PaymentVerifierRegistry
- Optimization enabled
- true
- Compiler version
- v0.8.18+commit.87f61d96
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2026-01-12T22:08:38.572619Z
contracts/registries/PaymentVerifierRegistry.sol
//SPDX-License-Identifier: MIT
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Bytes32ArrayUtils } from "../external/Bytes32ArrayUtils.sol";
import { IPaymentVerifierRegistry } from "../interfaces/IPaymentVerifierRegistry.sol";
pragma solidity ^0.8.18;
contract PaymentVerifierRegistry is Ownable, IPaymentVerifierRegistry {
using Bytes32ArrayUtils for bytes32[];
/* ============ Structs ============ */
struct PaymentMethodConfig {
bool initialized;
address verifier;
mapping(bytes32 => bool) isCurrency;
bytes32[] currencies;
}
/* ============ Events ============ */
event PaymentMethodAdded(bytes32 indexed paymentMethod);
event PaymentMethodRemoved(bytes32 indexed paymentMethod);
event CurrencyAdded(bytes32 indexed paymentMethod, bytes32 indexed currencyCode);
event CurrencyRemoved(bytes32 indexed paymentMethod, bytes32 indexed currencyCode);
/* ============ State Variables ============ */
mapping(bytes32 => PaymentMethodConfig) public store;
bytes32[] public paymentMethods;
/* ============ Constructor ============ */
constructor() Ownable() {}
/* ============ External Functions ============ */
/**
* Adds a new payment method with processors and currencies
* @param _paymentMethod The payment method hash; Hash the payment method name in lowercase
* @param _verifier The verifier address to add for this payment method
* @param _currencies Array of currency code hashes to support
*/
function addPaymentMethod(
bytes32 _paymentMethod,
address _verifier,
bytes32[] calldata _currencies
) external onlyOwner {
require(!store[_paymentMethod].initialized, "Payment method already exists");
require(_verifier != address(0), "Invalid verifier");
require(_currencies.length > 0, "Invalid currencies length");
store[_paymentMethod].initialized = true;
store[_paymentMethod].verifier = _verifier;
addCurrencies(_paymentMethod, _currencies);
paymentMethods.push(_paymentMethod);
emit PaymentMethodAdded(_paymentMethod);
}
/**
* Removes a payment method and associated configuration
* @param _paymentMethod The payment method to remove
* @dev Only callable by owner
*/
function removePaymentMethod(bytes32 _paymentMethod) external onlyOwner {
require(store[_paymentMethod].initialized, "Payment method does not exist");
bytes32[] memory currencies = store[_paymentMethod].currencies;
for (uint256 i = 0; i < currencies.length; i++) {
_removeCurrency(_paymentMethod, currencies[i]);
}
delete store[_paymentMethod];
paymentMethods.removeStorage(_paymentMethod);
emit PaymentMethodRemoved(_paymentMethod);
}
/**
* Adds supported currencies for a specific payment method
* @param _paymentMethod The payment method hash
* @param _currencies Array of currency code hashes (e.g., keccak256("USD"), keccak256("EUR"))
*/
function addCurrencies(bytes32 _paymentMethod, bytes32[] calldata _currencies) public onlyOwner {
require(store[_paymentMethod].initialized, "Payment method does not exist");
require(_currencies.length > 0, "Invalid currencies length");
for (uint256 i = 0; i < _currencies.length; i++) {
_addCurrency(_paymentMethod, _currencies[i]);
}
}
/**
* Removes supported currencies for a specific payment method
* @param _paymentMethod The payment method hash
* @param _currencies Array of currency code hashes to remove
*/
function removeCurrencies(bytes32 _paymentMethod, bytes32[] calldata _currencies) external onlyOwner {
require(_currencies.length > 0, "Invalid currencies length");
for (uint256 i = 0; i < _currencies.length; i++) {
_removeCurrency(_paymentMethod, _currencies[i]);
}
}
/* ============ External View Functions ============ */
function isPaymentMethod(bytes32 _paymentMethod) external view returns (bool) {
return store[_paymentMethod].initialized;
}
function getPaymentMethods() external view returns (bytes32[] memory) {
return paymentMethods;
}
function getVerifier(bytes32 _paymentMethod) external view returns (address) {
return store[_paymentMethod].verifier;
}
function isCurrency(bytes32 _paymentMethod, bytes32 _currencyCode) external view returns (bool) {
return store[_paymentMethod].isCurrency[_currencyCode];
}
function getCurrencies(bytes32 _paymentMethod) external view returns (bytes32[] memory) {
return store[_paymentMethod].currencies;
}
/* ============ Internal Functions ============ */
function _addCurrency(bytes32 _paymentMethod, bytes32 _currencyCode) internal {
require(_currencyCode != bytes32(0), "Invalid currency code");
require(!store[_paymentMethod].isCurrency[_currencyCode], "Currency already exists");
store[_paymentMethod].isCurrency[_currencyCode] = true;
store[_paymentMethod].currencies.push(_currencyCode);
emit CurrencyAdded(_paymentMethod, _currencyCode);
}
function _removeCurrency(bytes32 _paymentMethod, bytes32 _currencyCode) internal {
require(store[_paymentMethod].isCurrency[_currencyCode], "Currency does not exist");
store[_paymentMethod].isCurrency[_currencyCode] = false;
store[_paymentMethod].currencies.removeStorage(_currencyCode);
emit CurrencyRemoved(_paymentMethod, _currencyCode);
}
}
@openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
contracts/external/Bytes32ArrayUtils.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/**
* @title Bytes32ArrayUtils
* @author ZKP2P
*
* Fork of Set Protocol's AddressArrayUtils library adapted for usage with bytes32 arrays.
*/
library Bytes32ArrayUtils {
uint256 constant internal MAX_INT = 2**256 - 1;
/**
* Finds the index of the first occurrence of the given element.
* @param A The input array to search
* @param a The value to find
* @return Returns (index and isIn) for the first occurrence starting from index 0
*/
function indexOf(bytes32[] memory A, bytes32 a) internal pure returns (uint256, bool) {
uint256 length = A.length;
for (uint256 i = 0; i < length; i++) {
if (A[i] == a) {
return (i, true);
}
}
return (MAX_INT, false);
}
/**
* Returns true if the value is present in the list. Uses indexOf internally.
* @param A The input array to search
* @param a The value to find
* @return Returns isIn for the first occurrence starting from index 0
*/
function contains(bytes32[] memory A, bytes32 a) internal pure returns (bool) {
(, bool isIn) = indexOf(A, a);
return isIn;
}
/**
* Returns true if there are 2 elements that are the same in an array
* @param A The input array to search
* @return Returns boolean for the first occurrence of a duplicate
*/
function hasDuplicate(bytes32[] memory A) internal pure returns(bool) {
require(A.length > 0, "A is empty");
for (uint256 i = 0; i < A.length - 1; i++) {
bytes32 current = A[i];
for (uint256 j = i + 1; j < A.length; j++) {
if (current == A[j]) {
return true;
}
}
}
return false;
}
/**
* @param A The input array to search
* @param a The bytes32 to remove
* @return Returns the array with the object removed.
*/
function remove(bytes32[] memory A, bytes32 a)
internal
pure
returns (bytes32[] memory)
{
(uint256 index, bool isIn) = indexOf(A, a);
if (!isIn) {
revert("bytes32 not in array.");
} else {
(bytes32[] memory _A,) = pop(A, index);
return _A;
}
}
/**
* @param A The input array to search
* @param a The bytes32 to remove
*/
function removeStorage(bytes32[] storage A, bytes32 a)
internal
{
(uint256 index, bool isIn) = indexOf(A, a);
if (!isIn) {
revert("bytes32 not in array.");
} else {
uint256 lastIndex = A.length - 1; // If the array would be empty, the previous line would throw, so no underflow here
if (index != lastIndex) { A[index] = A[lastIndex]; }
A.pop();
}
}
/**
* Removes specified index from array
* @param A The input array to search
* @param index The index to remove
* @return Returns the new array and the removed entry
*/
function pop(bytes32[] memory A, uint256 index)
internal
pure
returns (bytes32[] memory, bytes32)
{
uint256 length = A.length;
require(index < A.length, "Index must be < A length");
bytes32[] memory newBytes = new bytes32[](length - 1);
for (uint256 i = 0; i < index; i++) {
newBytes[i] = A[i];
}
for (uint256 j = index + 1; j < length; j++) {
newBytes[j - 1] = A[j];
}
return (newBytes, A[index]);
}
}
contracts/interfaces/IPaymentVerifierRegistry.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
interface IPaymentVerifierRegistry {
function isPaymentMethod(bytes32 _paymentMethod) external view returns (bool);
function getPaymentMethods() external view returns (bytes32[] memory);
function getVerifier(bytes32 _paymentMethod) external view returns (address);
function isCurrency(bytes32 _paymentMethod, bytes32 _currencyCode) external view returns (bool);
function getCurrencies(bytes32 _paymentMethod) external view returns (bytes32[] memory);
}
Compiler Settings
{"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","devdoc","userdoc","storageLayout","evm.gasEstimates"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":true},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"CurrencyAdded","inputs":[{"type":"bytes32","name":"paymentMethod","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"currencyCode","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"CurrencyRemoved","inputs":[{"type":"bytes32","name":"paymentMethod","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"currencyCode","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PaymentMethodAdded","inputs":[{"type":"bytes32","name":"paymentMethod","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"PaymentMethodRemoved","inputs":[{"type":"bytes32","name":"paymentMethod","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addCurrencies","inputs":[{"type":"bytes32","name":"_paymentMethod","internalType":"bytes32"},{"type":"bytes32[]","name":"_currencies","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addPaymentMethod","inputs":[{"type":"bytes32","name":"_paymentMethod","internalType":"bytes32"},{"type":"address","name":"_verifier","internalType":"address"},{"type":"bytes32[]","name":"_currencies","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"getCurrencies","inputs":[{"type":"bytes32","name":"_paymentMethod","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"getPaymentMethods","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getVerifier","inputs":[{"type":"bytes32","name":"_paymentMethod","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isCurrency","inputs":[{"type":"bytes32","name":"_paymentMethod","internalType":"bytes32"},{"type":"bytes32","name":"_currencyCode","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isPaymentMethod","inputs":[{"type":"bytes32","name":"_paymentMethod","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"paymentMethods","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeCurrencies","inputs":[{"type":"bytes32","name":"_paymentMethod","internalType":"bytes32"},{"type":"bytes32[]","name":"_currencies","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removePaymentMethod","inputs":[{"type":"bytes32","name":"_paymentMethod","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"initialized","internalType":"bool"},{"type":"address","name":"verifier","internalType":"address"}],"name":"store","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
Contract Creation Code
0x6080806040523461005b5760008054336001600160a01b0319821681178355916001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3610fa890816100618239f35b600080fdfe60406080815260048036101561001457600080fd5b600091823560e01c806312b1fe9314610953578063334c2ef31461071157806358aabeeb146106bc5780635e5658d21461067e578063654cf88c14610640578063715018a6146105e65780638b90cdc9146105aa5780638da5cb5b1461057e5780639072ec4e14610551578063a1627cd0146104d8578063a9ce20aa1461049f578063dbcb3005146101bd578063eeb7b248146101865763f2fde38b146100ba57600080fd5b34610182576020366003190112610182576001600160a01b0382358181169391929084900361017e576100eb610ba5565b831561012c57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b906020608492519162461bcd60e51b8352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152fd5b8480fd5b8280fd5b50903461018257602036600319011261018257358252600160209081529181902054905160089190911c6001600160a01b03168152f35b5090346101825760603660031901126101825780359160248035916001600160a01b0383169081840361049b5760449182359067ffffffffffffffff82116104975761020d839236908901610aad565b610218959195610ba5565b898b526001976020938985528c60ff9788912054166104565715610422578861029087878f8f610295968815159661024f88610bfd565b828452808c5284842080546001600160a81b03191660089390931b610100600160a81b031692909217179055610283610ba5565b81528d8952205416610c84565b610bfd565b8a5b81811061031b575050505050505060025492600160401b84101561030a5750506102ca8284926102e39401600255610b52565b90919082549060031b91821b91600019901b1916179055565b7fa8b7ef1cdeb8ecb963885f69266685a6c19778bdbe18fd82fb494d536ae5ede88280a280f35b634e487b7160e01b86526041905284fd5b610326818389610dac565b3580156103e95786868e8e81528c88528c8282200184825288522054166103ae57906103a9918c7fc8f017475bca3c28175d8dbac507c62a1cd9150a8da85f8b39e8947d4f5464408f8281528d89528d8a82200184825289528d8a82209060ff198254161790558281528d89526103a28460028c842001610c49565b80a3610d2f565b610297565b855162461bcd60e51b8152808c018690526017818b01527643757272656e637920616c72656164792065786973747360481b81860152606490fd5b855162461bcd60e51b8152808c018690526015818b015274496e76616c69642063757272656e637920636f646560581b81860152606490fd5b845162461bcd60e51b8152808b018590526010818a01526f24b73b30b634b2103b32b934b334b2b960811b81850152606490fd5b855162461bcd60e51b8152808c01869052601d818b01527f5061796d656e74206d6574686f6420616c72656164792065786973747300000081860152606490fd5b8880fd5b8680fd5b5090346101825781600319360112610182578160209360ff92358152600185526001828220016024358252855220541690519015158152f35b50823461054e578060031936011261054e57815191829160025480855260208095019460028352600080516020610f5383398151915292905b828210610537576105338686610529828b0383610d0d565b5191829182610b17565b0390f35b835487529586019560019384019390910190610511565b80fd5b509034610182576020366003190112610182578160209360ff923581526001855220541690519015158152f35b8382346105a657816003193601126105a657905490516001600160a01b039091168152602090f35b5080fd5b509034610182576020366003190112610182573560025481101561018257600260209352600080516020610f5383398151915201549051908152f35b833461054e578060031936011261054e576105ff610ba5565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b509034610182576020366003190112610182579181923581526001602052205481519060ff81161515825260018060a01b039060081c166020820152f35b5090346101825760203660031901126101825790610529600282610533956106b59535815260016020522001825193848092610cd0565b0383610d0d565b833461054e576106cb36610ae3565b6106d6929192610ba5565b6106e1811515610bfd565b835b8181106106ee578480f35b8061070761070061070c938588610dac565b3585610dbc565b610d2f565b6106e3565b5034610182576020908160031936011261094f57823593610730610ba5565b84815260019485845261074860ff8484205416610c84565b80825285845260028661076761076e8387872001875192838092610cd0565b0382610d0d565b84825b610923575b505050818352868552808484208481550180549084815581610900575b50508351815480825282855297839087830190600080516020610f5383398151915290875b8a8d82106108ea5750505050916107d4816107d9940382610d0d565b610d68565b90979061081b57845162461bcd60e51b81528088018790526015602482015274313cba32b99999103737ba1034b71030b93930bc9760591b6044820152606490fd5b8688600019928381019081116108d757808203610899575b505082549081156108865750019061085e61084d83610b52565b8154906000199060031b1b19169055565b557f0c831f94d9f98b9753b9607b5f1d9b1758d364178abe6e854ee65e97519c57648280a280f35b634e487b7160e01b865260319052602485fd5b6108d0916108a96108b292610b52565b92905491610b52565b91909260031b1c9082549060031b91821b91600019901b1916179055565b8580610833565b634e487b7160e01b875260118352602487fd5b83548552889550909301929181019181016107b8565b845287868520918201915b8281106109185750610793565b85815501889061090b565b815181101561094a578061070761093d6109449385610d54565b5187610dbc565b82610771565b610776565b8380fd5b5090346101825761096336610ae3565b91909261096e610ba5565b81865260019060209082825260ff9461098b86898b205416610c84565b610996811515610bfd565b885b8181106109a3578980f35b6109ae81838a610dac565b358015610a7257868b52858552858a8c2001818c528552878a8c205416610a35579081610a06610a309360028d8f8c81528b8b528b828220018482528b528181208c60ff198254161790558c81528b8b522001610c49565b877fc8f017475bca3c28175d8dbac507c62a1cd9150a8da85f8b39e8947d4f5464408d80a3610d2f565b610998565b895162461bcd60e51b8152808501869052601760248201527643757272656e637920616c72656164792065786973747360481b6044820152606490fd5b895162461bcd60e51b81528085018690526015602482015274496e76616c69642063757272656e637920636f646560581b6044820152606490fd5b9181601f84011215610ade5782359167ffffffffffffffff8311610ade576020808501948460051b010111610ade57565b600080fd5b906040600319830112610ade57600435916024359067ffffffffffffffff8211610ade57610b1391600401610aad565b9091565b6020908160408183019282815285518094520193019160005b828110610b3e575050505090565b835185529381019392810192600101610b30565b600254811015610b77576002600052600080516020610f538339815191520190600090565b634e487b7160e01b600052603260045260246000fd5b8054821015610b775760005260206000200190600090565b6000546001600160a01b03163303610bb957565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b15610c0457565b60405162461bcd60e51b815260206004820152601960248201527f496e76616c69642063757272656e63696573206c656e677468000000000000006044820152606490fd5b90815491600160401b831015610c6e57826102ca916001610c6c95018155610b8d565b565b634e487b7160e01b600052604160045260246000fd5b15610c8b57565b60405162461bcd60e51b815260206004820152601d60248201527f5061796d656e74206d6574686f6420646f6573206e6f742065786973740000006044820152606490fd5b90815480825260208092019260005281600020916000905b828210610cf6575050505090565b835485529384019360019384019390910190610ce8565b90601f8019910116810190811067ffffffffffffffff821117610c6e57604052565b6000198114610d3e5760010190565b634e487b7160e01b600052601160045260246000fd5b8051821015610b775760209160051b010190565b9081519160005b838110610d83575050505060001990600090565b82610d8e8284610d54565b5114610da257610d9d90610d2f565b610d6f565b9250505090600190565b9190811015610b775760051b0190565b9060009082825260209260018452604092600184822001838252855260ff848220541615610f0e5781815260018552600184822001838252855283812060ff19815416905581815260018552600284822001610e228486516107d4816107678187610cd0565b610e6257855162461bcd60e51b8152600481018890526015602482015274313cba32b99999103737ba1034b71030b93930bc9760591b6044820152606490fd5b9193955080929450549060001991828101908111610efa57808203610ed8575b505081548015610ec4577f55afc4295737baf9bf7759d75fb64ad7bf91bf4c80c9a6a22b23d61a7924b4b59392910190610ebf61084d8383610b8d565b5580a3565b634e487b7160e01b84526031600452602484fd5b610ef391610ee96108b29286610b8d565b9290549186610b8d565b3880610e82565b634e487b7160e01b85526011600452602485fd5b835162461bcd60e51b815260048101869052601760248201527f43757272656e637920646f6573206e6f742065786973740000000000000000006044820152606490fdfe405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acea26469706673582212201c03713117a101562cd66986eee1a37132fbd3fbac3f787f597d0a9662d70c1f64736f6c63430008120033
Deployed ByteCode
0x60406080815260048036101561001457600080fd5b600091823560e01c806312b1fe9314610953578063334c2ef31461071157806358aabeeb146106bc5780635e5658d21461067e578063654cf88c14610640578063715018a6146105e65780638b90cdc9146105aa5780638da5cb5b1461057e5780639072ec4e14610551578063a1627cd0146104d8578063a9ce20aa1461049f578063dbcb3005146101bd578063eeb7b248146101865763f2fde38b146100ba57600080fd5b34610182576020366003190112610182576001600160a01b0382358181169391929084900361017e576100eb610ba5565b831561012c57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b906020608492519162461bcd60e51b8352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152fd5b8480fd5b8280fd5b50903461018257602036600319011261018257358252600160209081529181902054905160089190911c6001600160a01b03168152f35b5090346101825760603660031901126101825780359160248035916001600160a01b0383169081840361049b5760449182359067ffffffffffffffff82116104975761020d839236908901610aad565b610218959195610ba5565b898b526001976020938985528c60ff9788912054166104565715610422578861029087878f8f610295968815159661024f88610bfd565b828452808c5284842080546001600160a81b03191660089390931b610100600160a81b031692909217179055610283610ba5565b81528d8952205416610c84565b610bfd565b8a5b81811061031b575050505050505060025492600160401b84101561030a5750506102ca8284926102e39401600255610b52565b90919082549060031b91821b91600019901b1916179055565b7fa8b7ef1cdeb8ecb963885f69266685a6c19778bdbe18fd82fb494d536ae5ede88280a280f35b634e487b7160e01b86526041905284fd5b610326818389610dac565b3580156103e95786868e8e81528c88528c8282200184825288522054166103ae57906103a9918c7fc8f017475bca3c28175d8dbac507c62a1cd9150a8da85f8b39e8947d4f5464408f8281528d89528d8a82200184825289528d8a82209060ff198254161790558281528d89526103a28460028c842001610c49565b80a3610d2f565b610297565b855162461bcd60e51b8152808c018690526017818b01527643757272656e637920616c72656164792065786973747360481b81860152606490fd5b855162461bcd60e51b8152808c018690526015818b015274496e76616c69642063757272656e637920636f646560581b81860152606490fd5b845162461bcd60e51b8152808b018590526010818a01526f24b73b30b634b2103b32b934b334b2b960811b81850152606490fd5b855162461bcd60e51b8152808c01869052601d818b01527f5061796d656e74206d6574686f6420616c72656164792065786973747300000081860152606490fd5b8880fd5b8680fd5b5090346101825781600319360112610182578160209360ff92358152600185526001828220016024358252855220541690519015158152f35b50823461054e578060031936011261054e57815191829160025480855260208095019460028352600080516020610f5383398151915292905b828210610537576105338686610529828b0383610d0d565b5191829182610b17565b0390f35b835487529586019560019384019390910190610511565b80fd5b509034610182576020366003190112610182578160209360ff923581526001855220541690519015158152f35b8382346105a657816003193601126105a657905490516001600160a01b039091168152602090f35b5080fd5b509034610182576020366003190112610182573560025481101561018257600260209352600080516020610f5383398151915201549051908152f35b833461054e578060031936011261054e576105ff610ba5565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b509034610182576020366003190112610182579181923581526001602052205481519060ff81161515825260018060a01b039060081c166020820152f35b5090346101825760203660031901126101825790610529600282610533956106b59535815260016020522001825193848092610cd0565b0383610d0d565b833461054e576106cb36610ae3565b6106d6929192610ba5565b6106e1811515610bfd565b835b8181106106ee578480f35b8061070761070061070c938588610dac565b3585610dbc565b610d2f565b6106e3565b5034610182576020908160031936011261094f57823593610730610ba5565b84815260019485845261074860ff8484205416610c84565b80825285845260028661076761076e8387872001875192838092610cd0565b0382610d0d565b84825b610923575b505050818352868552808484208481550180549084815581610900575b50508351815480825282855297839087830190600080516020610f5383398151915290875b8a8d82106108ea5750505050916107d4816107d9940382610d0d565b610d68565b90979061081b57845162461bcd60e51b81528088018790526015602482015274313cba32b99999103737ba1034b71030b93930bc9760591b6044820152606490fd5b8688600019928381019081116108d757808203610899575b505082549081156108865750019061085e61084d83610b52565b8154906000199060031b1b19169055565b557f0c831f94d9f98b9753b9607b5f1d9b1758d364178abe6e854ee65e97519c57648280a280f35b634e487b7160e01b865260319052602485fd5b6108d0916108a96108b292610b52565b92905491610b52565b91909260031b1c9082549060031b91821b91600019901b1916179055565b8580610833565b634e487b7160e01b875260118352602487fd5b83548552889550909301929181019181016107b8565b845287868520918201915b8281106109185750610793565b85815501889061090b565b815181101561094a578061070761093d6109449385610d54565b5187610dbc565b82610771565b610776565b8380fd5b5090346101825761096336610ae3565b91909261096e610ba5565b81865260019060209082825260ff9461098b86898b205416610c84565b610996811515610bfd565b885b8181106109a3578980f35b6109ae81838a610dac565b358015610a7257868b52858552858a8c2001818c528552878a8c205416610a35579081610a06610a309360028d8f8c81528b8b528b828220018482528b528181208c60ff198254161790558c81528b8b522001610c49565b877fc8f017475bca3c28175d8dbac507c62a1cd9150a8da85f8b39e8947d4f5464408d80a3610d2f565b610998565b895162461bcd60e51b8152808501869052601760248201527643757272656e637920616c72656164792065786973747360481b6044820152606490fd5b895162461bcd60e51b81528085018690526015602482015274496e76616c69642063757272656e637920636f646560581b6044820152606490fd5b9181601f84011215610ade5782359167ffffffffffffffff8311610ade576020808501948460051b010111610ade57565b600080fd5b906040600319830112610ade57600435916024359067ffffffffffffffff8211610ade57610b1391600401610aad565b9091565b6020908160408183019282815285518094520193019160005b828110610b3e575050505090565b835185529381019392810192600101610b30565b600254811015610b77576002600052600080516020610f538339815191520190600090565b634e487b7160e01b600052603260045260246000fd5b8054821015610b775760005260206000200190600090565b6000546001600160a01b03163303610bb957565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b15610c0457565b60405162461bcd60e51b815260206004820152601960248201527f496e76616c69642063757272656e63696573206c656e677468000000000000006044820152606490fd5b90815491600160401b831015610c6e57826102ca916001610c6c95018155610b8d565b565b634e487b7160e01b600052604160045260246000fd5b15610c8b57565b60405162461bcd60e51b815260206004820152601d60248201527f5061796d656e74206d6574686f6420646f6573206e6f742065786973740000006044820152606490fd5b90815480825260208092019260005281600020916000905b828210610cf6575050505090565b835485529384019360019384019390910190610ce8565b90601f8019910116810190811067ffffffffffffffff821117610c6e57604052565b6000198114610d3e5760010190565b634e487b7160e01b600052601160045260246000fd5b8051821015610b775760209160051b010190565b9081519160005b838110610d83575050505060001990600090565b82610d8e8284610d54565b5114610da257610d9d90610d2f565b610d6f565b9250505090600190565b9190811015610b775760051b0190565b9060009082825260209260018452604092600184822001838252855260ff848220541615610f0e5781815260018552600184822001838252855283812060ff19815416905581815260018552600284822001610e228486516107d4816107678187610cd0565b610e6257855162461bcd60e51b8152600481018890526015602482015274313cba32b99999103737ba1034b71030b93930bc9760591b6044820152606490fd5b9193955080929450549060001991828101908111610efa57808203610ed8575b505081548015610ec4577f55afc4295737baf9bf7759d75fb64ad7bf91bf4c80c9a6a22b23d61a7924b4b59392910190610ebf61084d8383610b8d565b5580a3565b634e487b7160e01b84526031600452602484fd5b610ef391610ee96108b29286610b8d565b9290549186610b8d565b3880610e82565b634e487b7160e01b85526011600452602485fd5b835162461bcd60e51b815260048101869052601760248201527f43757272656e637920646f6573206e6f742065786973740000000000000000006044820152606490fdfe405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acea26469706673582212201c03713117a101562cd66986eee1a37132fbd3fbac3f787f597d0a9662d70c1f64736f6c63430008120033