Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Read Proxy
Write Contract
Write Proxy
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been partially verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- FNDCollectionFactory
- Optimization enabled
- true
- Compiler version
- v0.8.9+commit.e5eed63a
- Optimization runs
- 1337
- EVM Version
- london
- Verified at
- 2026-05-11T18:09:54.734914Z
Constructor Arguments
000000000000000000000000461aa494426e04fb2449068bad5948a0d720aef200000000000000000000000067df244584b67e8c51b10ad610aaffa9a402fdb6
Arg [0] (address) : 0x461aa494426e04fb2449068bad5948a0d720aef2
Arg [1] (address) : 0x67df244584b67e8c51b10ad610aaffa9a402fdb6
contracts/FNDCollectionFactory.sol
/*
・
* ★
・ 。
・ ゚☆ 。
* ★ ゚・。 * 。
* ☆ 。・゚*.。
゚ *.。☆。★ ・
` .-:::::-.` `-::---...```
`-:` .:+ssssoooo++//:.` .-/+shhhhhhhhhhhhhyyyssooo:
.--::. .+ossso+/////++/:://-` .////+shhhhhhhhhhhhhhhhhhhhhy
`-----::. `/+////+++///+++/:--:/+/- -////+shhhhhhhhhhhhhhhhhhhhhy
`------:::-` `//-.``.-/+ooosso+:-.-/oso- -////+shhhhhhhhhhhhhhhhhhhhhy
.--------:::-` :+:.` .-/osyyyyyyso++syhyo.-////+shhhhhhhhhhhhhhhhhhhhhy
`-----------:::-. +o+:-.-:/oyhhhhhhdhhhhhdddy:-////+shhhhhhhhhhhhhhhhhhhhhy
.------------::::-- `oys+/::/+shhhhhhhdddddddddy/-////+shhhhhhhhhhhhhhhhhhhhhy
.--------------:::::-` +ys+////+yhhhhhhhddddddddhy:-////+yhhhhhhhhhhhhhhhhhhhhhy
`----------------::::::-`.ss+/:::+oyhhhhhhhhhhhhhhho`-////+shhhhhhhhhhhhhhhhhhhhhy
.------------------:::::::.-so//::/+osyyyhhhhhhhhhys` -////+shhhhhhhhhhhhhhhhhhhhhy
`.-------------------::/:::::..+o+////+oosssyyyyyyys+` .////+shhhhhhhhhhhhhhhhhhhhhy
.--------------------::/:::.` -+o++++++oooosssss/. `-//+shhhhhhhhhhhhhhhhhhhhyo
.------- ``````.......--` `-/+ooooosso+/-` `./++++///:::--...``hhhhyo
`````
*
・ 。
・ ゚☆ 。
* ★ ゚・。 * 。
* ☆ 。・゚*.。
゚ *.。☆。★ ・
* ゚。·*・。 ゚*
☆゚・。°*. ゚
・ ゚*。・゚★。
・ *゚。 *
・゚*。★・
☆∴。 *
・ 。
*/
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-solc-8/proxy/Clones.sol";
import "@openzeppelin/contracts-solc-8/utils/Address.sol";
import "@openzeppelin/contracts-solc-8/utils/Strings.sol";
import "./interfaces/solc8/ICollectionContractInitializer.sol";
import "./interfaces/solc8/IRoles.sol";
import "./interfaces/solc8/ICollectionFactory.sol";
import "./interfaces/solc8/IProxyCall.sol";
/**
* @title A factory to create NFT collections.
* @notice Call this factory to create and initialize a minimal proxy pointing to the NFT collection contract.
*/
contract FNDCollectionFactory is ICollectionFactory {
using Address for address;
using Address for address payable;
using Clones for address;
using Strings for uint256;
/**
* @notice The contract address which manages common roles.
* @dev Used by the collections for a shared operator definition.
*/
IRoles public rolesContract;
/**
* @notice The address of the template all new collections will leverage.
*/
address public implementation;
/**
* @notice The address of the proxy call contract implementation.
* @dev Used by the collections to safely call another contract with arbitrary call data.
*/
IProxyCall public proxyCallContract;
/**
* @notice The implementation version new collections will use.
* @dev This is auto-incremented each time the implementation is changed.
*/
uint256 public version;
event RolesContractUpdated(address indexed rolesContract);
event CollectionCreated(
address indexed collectionContract,
address indexed creator,
uint256 indexed version,
string name,
string symbol,
uint256 nonce
);
event ImplementationUpdated(address indexed implementation, uint256 indexed version);
event ProxyCallContractUpdated(address indexed proxyCallContract);
modifier onlyAdmin() {
require(rolesContract.isAdmin(msg.sender), "FNDCollectionFactory: Caller does not have the Admin role");
_;
}
constructor(address _proxyCallContract, address _rolesContract) {
_updateRolesContract(_rolesContract);
_updateProxyCallContract(_proxyCallContract);
}
/**
* @notice Create a new collection contract.
* @param nonce An arbitrary value used to allow a creator to mint multiple collections.
* @dev The nonce is required and must be unique for the msg.sender + implementation version,
* otherwise this call will revert.
*/
function createCollection(
string calldata name,
string calldata symbol,
uint256 nonce
) external returns (address) {
require(bytes(symbol).length > 0, "FNDCollectionFactory: Symbol is required");
// This reverts if the NFT was previously created using this implementation version + msg.sender + nonce
address proxy = implementation.cloneDeterministic(_getSalt(msg.sender, nonce));
ICollectionContractInitializer(proxy).initialize(payable(msg.sender), name, symbol);
emit CollectionCreated(proxy, msg.sender, version, name, symbol, nonce);
// Returning the address created allows other contracts to integrate with this call
return address(proxy);
}
/**
* @notice Allows Foundation to change the admin role contract address.
*/
function adminUpdateRolesContract(address _rolesContract) external onlyAdmin {
_updateRolesContract(_rolesContract);
}
/**
* @notice Allows Foundation to change the collection implementation used for future collections.
* This call will auto-increment the version.
* Existing collections are not impacted.
*/
function adminUpdateImplementation(address _implementation) external onlyAdmin {
_updateImplementation(_implementation);
}
/**
* @notice Allows Foundation to change the proxy call contract address.
*/
function adminUpdateProxyCallContract(address _proxyCallContract) external onlyAdmin {
_updateProxyCallContract(_proxyCallContract);
}
/**
* @notice Returns the address of a collection given the current implementation version, creator, and nonce.
* This will return the same address whether the collection has already been created or not.
* @param nonce An arbitrary value used to allow a creator to mint multiple collections.
*/
function predictCollectionAddress(address creator, uint256 nonce) external view returns (address) {
return implementation.predictDeterministicAddress(_getSalt(creator, nonce));
}
function _updateRolesContract(address _rolesContract) private {
require(_rolesContract.isContract(), "FNDCollectionFactory: RolesContract is not a contract");
rolesContract = IRoles(_rolesContract);
emit RolesContractUpdated(_rolesContract);
}
/**
* @dev Updates the implementation address, increments the version, and initializes the template.
* Since the template is initialized when set, implementations cannot be re-used.
* To downgrade the implementation, deploy the same bytecode again and then update to that.
*/
function _updateImplementation(address _implementation) private {
require(_implementation.isContract(), "FNDCollectionFactory: Implementation is not a contract");
implementation = _implementation;
version++;
// The implementation is initialized when assigned so that others may not claim it as their own.
ICollectionContractInitializer(_implementation).initialize(
payable(address(rolesContract)),
string(abi.encodePacked("Foundation Collection Template v", version.toString())),
string(abi.encodePacked("FCTv", version.toString()))
);
emit ImplementationUpdated(_implementation, version);
}
function _updateProxyCallContract(address _proxyCallContract) private {
require(_proxyCallContract.isContract(), "FNDCollectionFactory: Proxy call address is not a contract");
proxyCallContract = IProxyCall(_proxyCallContract);
emit ProxyCallContractUpdated(_proxyCallContract);
}
function _getSalt(address creator, uint256 nonce) private pure returns (bytes32) {
return keccak256(abi.encodePacked(creator, nonce));
}
}
/ICollectionContractInitializer.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.0;
interface ICollectionContractInitializer {
function initialize(
address payable _creator,
string memory _name,
string memory _symbol
) external;
}
/ICollectionFactory.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.0;
import "./IRoles.sol";
import "./IProxyCall.sol";
interface ICollectionFactory {
function rolesContract() external returns (IRoles);
function proxyCallContract() external returns (IProxyCall);
}
/Strings.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
/Address.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
/Clones.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
* deploying minimal proxy contracts, also known as "clones".
*
* > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
* > a minimal bytecode implementation that delegates all calls to a known, fixed address.
*
* The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
* (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
* deterministic method.
*
* _Available since v3.4._
*/
library Clones {
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create opcode, which should never revert.
*/
function clone(address implementation) internal returns (address instance) {
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create(0, ptr, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy
* the clone. Using the same `implementation` and `salt` multiple time will revert, since
* the clones cannot be deployed twice at the same address.
*/
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create2(0, ptr, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
mstore(add(ptr, 0x38), shl(0x60, deployer))
mstore(add(ptr, 0x4c), salt)
mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
predicted := keccak256(add(ptr, 0x37), 0x55)
}
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(address implementation, bytes32 salt)
internal
view
returns (address predicted)
{
return predictDeterministicAddress(implementation, salt, address(this));
}
}
/IProxyCall.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.0;
interface IProxyCall {
function proxyCallAndReturnAddress(address externalContract, bytes calldata callData)
external
returns (address payable result);
}
/IRoles.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.0;
/**
* @notice Interface for a contract which implements admin roles.
*/
interface IRoles {
function isAdmin(address account) external view returns (bool);
function isOperator(address account) external view returns (bool);
}
Compiler Settings
{"remappings":[],"optimizer":{"runs":1337,"enabled":true},"metadata":{"useLiteralContent":true,"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"london","compilationTarget":{"contracts/FNDCollectionFactory.sol":"FNDCollectionFactory"}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_proxyCallContract","internalType":"address"},{"type":"address","name":"_rolesContract","internalType":"address"}]},{"type":"event","name":"CollectionCreated","inputs":[{"type":"address","name":"collectionContract","internalType":"address","indexed":true},{"type":"address","name":"creator","internalType":"address","indexed":true},{"type":"uint256","name":"version","internalType":"uint256","indexed":true},{"type":"string","name":"name","internalType":"string","indexed":false},{"type":"string","name":"symbol","internalType":"string","indexed":false},{"type":"uint256","name":"nonce","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ImplementationUpdated","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true},{"type":"uint256","name":"version","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ProxyCallContractUpdated","inputs":[{"type":"address","name":"proxyCallContract","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RolesContractUpdated","inputs":[{"type":"address","name":"rolesContract","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"adminUpdateImplementation","inputs":[{"type":"address","name":"_implementation","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"adminUpdateProxyCallContract","inputs":[{"type":"address","name":"_proxyCallContract","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"adminUpdateRolesContract","inputs":[{"type":"address","name":"_rolesContract","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"createCollection","inputs":[{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"symbol","internalType":"string"},{"type":"uint256","name":"nonce","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"implementation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"predictCollectionAddress","inputs":[{"type":"address","name":"creator","internalType":"address"},{"type":"uint256","name":"nonce","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IProxyCall"}],"name":"proxyCallContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IRoles"}],"name":"rolesContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"version","inputs":[]}]
Contract Creation Code
0x60806040523480156200001157600080fd5b50604051620012cf380380620012cf833981016040819052620000349162000231565b6200003f8162000052565b6200004a8262000131565b505062000269565b62000071816001600160a01b03166200020e60201b6200067a1760201c565b620000e95760405162461bcd60e51b815260206004820152603560248201527f464e44436f6c6c656374696f6e466163746f72793a20526f6c6573436f6e747260448201527f616374206973206e6f74206120636f6e7472616374000000000000000000000060648201526084015b60405180910390fd5b600080546001600160a01b0319166001600160a01b038316908117825560405190917f2cff90ef548ed2e2f7b9815b7089188bc1e96989b6346ac05a58750d92607d4b91a250565b62000150816001600160a01b03166200020e60201b6200067a1760201c565b620001c45760405162461bcd60e51b815260206004820152603a60248201527f464e44436f6c6c656374696f6e466163746f72793a2050726f78792063616c6c60448201527f2061646472657373206973206e6f74206120636f6e74726163740000000000006064820152608401620000e0565b600280546001600160a01b0319166001600160a01b0383169081179091556040517f7213e3d637e4ef4968f947d5f602103307355f708bfd5bfce9d87da7c78f852190600090a250565b3b151590565b80516001600160a01b03811681146200022c57600080fd5b919050565b600080604083850312156200024557600080fd5b620002508362000214565b9150620002606020840162000214565b90509250929050565b61105680620002796000396000f3fe608060405234801561001057600080fd5b50600436106100a25760003560e01c806354fd4d5011610076578063a17bb1991161005b578063a17bb1991461013c578063bb7e36481461014f578063ca53b3911461016257600080fd5b806354fd4d50146101125780635c60da1b1461012957600080fd5b80629dfb89146100a75780631b8c9c4b146100bc5780634197ed74146100ec5780634b263865146100ff575b600080fd5b6100ba6100b5366004610c62565b610175565b005b6100cf6100ca366004610c7d565b610273565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cf6100fa366004610cf0565b6102df565b6100ba61010d366004610c62565b61048e565b61011b60035481565b6040519081526020016100e3565b6001546100cf906001600160a01b031681565b6100ba61014a366004610c62565b610584565b6002546100cf906001600160a01b031681565b6000546100cf906001600160a01b031681565b600054604051630935e01b60e21b81523360048201526001600160a01b03909116906324d7806c9060240160206040518083038186803b1580156101b857600080fd5b505afa1580156101cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101f09190610d64565b6102675760405162461bcd60e51b815260206004820152603960248201527f464e44436f6c6c656374696f6e466163746f72793a2043616c6c657220646f6560448201527f73206e6f742068617665207468652041646d696e20726f6c650000000000000060648201526084015b60405180910390fd5b61027081610680565b50565b60006102d66102c484846040516bffffffffffffffffffffffff19606084901b1660208201526034810182905260009060540160405160208183030381529060405280519060200120905092915050565b6001546001600160a01b031690610833565b90505b92915050565b6000826103545760405162461bcd60e51b815260206004820152602860248201527f464e44436f6c6c656374696f6e466163746f72793a2053796d626f6c2069732060448201527f7265717569726564000000000000000000000000000000000000000000000000606482015260840161025e565b604080513360601b6bffffffffffffffffffffffff1916602080830191909152603480830186905283518084039091018152605490920190925280519101206000906103ac906001546001600160a01b0316906108af565b6040517f906571470000000000000000000000000000000000000000000000000000000081529091506001600160a01b038216906390657147906103fc9033908b908b908b908b90600401610db6565b600060405180830381600087803b15801561041657600080fd5b505af115801561042a573d6000803e3d6000fd5b50505050600354336001600160a01b0316826001600160a01b03167fd3cbcb86b6ae20e08baf6a5fbaf0c922acff26cdc663bdf06744f5023bbcd2548a8a8a8a8a60405161047c959493929190610df8565b60405180910390a49695505050505050565b600054604051630935e01b60e21b81523360048201526001600160a01b03909116906324d7806c9060240160206040518083038186803b1580156104d157600080fd5b505afa1580156104e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105099190610d64565b61057b5760405162461bcd60e51b815260206004820152603960248201527f464e44436f6c6c656374696f6e466163746f72793a2043616c6c657220646f6560448201527f73206e6f742068617665207468652041646d696e20726f6c6500000000000000606482015260840161025e565b61027081610966565b600054604051630935e01b60e21b81523360048201526001600160a01b03909116906324d7806c9060240160206040518083038186803b1580156105c757600080fd5b505afa1580156105db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ff9190610d64565b6106715760405162461bcd60e51b815260206004820152603960248201527f464e44436f6c6c656374696f6e466163746f72793a2043616c6c657220646f6560448201527f73206e6f742068617665207468652041646d696e20726f6c6500000000000000606482015260840161025e565b61027081610a38565b3b151590565b6001600160a01b0381163b6106fd5760405162461bcd60e51b815260206004820152603660248201527f464e44436f6c6c656374696f6e466163746f72793a20496d706c656d656e746160448201527f74696f6e206973206e6f74206120636f6e747261637400000000000000000000606482015260840161025e565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556003805490600061073583610e48565b90915550506000546003546001600160a01b038084169263906571479291169061075e90610b0c565b60405160200161076e9190610e93565b604051602081830303815290604052610788600354610b0c565b6040516020016107989190610ed8565b6040516020818303038152906040526040518463ffffffff1660e01b81526004016107c593929190610f49565b600060405180830381600087803b1580156107df57600080fd5b505af11580156107f3573d6000803e3d6000fd5b50505050600354816001600160a01b03167f5678af47993f4856157dd819bee3183b87c10ee1b3575a5128fe25896c073a2860405160405180910390a350565b60006102d68383306040517f3d602d80600a3d3981f3363d3d373d3d3d363d730000000000000000000000008152606093841b60148201527f5af43d82803e903d91602b57fd5bf3ff000000000000000000000000000000006028820152921b6038830152604c8201526037808220606c830152605591012090565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528360601b60148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f59150506001600160a01b0381166102d95760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c6564000000000000000000604482015260640161025e565b6001600160a01b0381163b6109e35760405162461bcd60e51b815260206004820152603560248201527f464e44436f6c6c656374696f6e466163746f72793a20526f6c6573436f6e747260448201527f616374206973206e6f74206120636f6e74726163740000000000000000000000606482015260840161025e565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316908117825560405190917f2cff90ef548ed2e2f7b9815b7089188bc1e96989b6346ac05a58750d92607d4b91a250565b6001600160a01b0381163b610ab55760405162461bcd60e51b815260206004820152603a60248201527f464e44436f6c6c656374696f6e466163746f72793a2050726f78792063616c6c60448201527f2061646472657373206973206e6f74206120636f6e7472616374000000000000606482015260840161025e565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f7213e3d637e4ef4968f947d5f602103307355f708bfd5bfce9d87da7c78f852190600090a250565b606081610b4c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610b765780610b6081610e48565b9150610b6f9050600a83610f9d565b9150610b50565b60008167ffffffffffffffff811115610b9157610b91610fb1565b6040519080825280601f01601f191660200182016040528015610bbb576020820181803683370190505b5090505b8415610c3e57610bd0600183610fc7565b9150610bdd600a86610fde565b610be8906030610ff2565b60f81b818381518110610bfd57610bfd61100a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610c37600a86610f9d565b9450610bbf565b949350505050565b80356001600160a01b0381168114610c5d57600080fd5b919050565b600060208284031215610c7457600080fd5b6102d682610c46565b60008060408385031215610c9057600080fd5b610c9983610c46565b946020939093013593505050565b60008083601f840112610cb957600080fd5b50813567ffffffffffffffff811115610cd157600080fd5b602083019150836020828501011115610ce957600080fd5b9250929050565b600080600080600060608688031215610d0857600080fd5b853567ffffffffffffffff80821115610d2057600080fd5b610d2c89838a01610ca7565b90975095506020880135915080821115610d4557600080fd5b50610d5288828901610ca7565b96999598509660400135949350505050565b600060208284031215610d7657600080fd5b81518015158114610d8657600080fd5b9392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0386168152606060208201526000610dd9606083018688610d8d565b8281036040840152610dec818587610d8d565b98975050505050505050565b606081526000610e0c606083018789610d8d565b8281036020840152610e1f818688610d8d565b9150508260408301529695505050505050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415610e5c57610e5c610e32565b5060010190565b60005b83811015610e7e578181015183820152602001610e66565b83811115610e8d576000848401525b50505050565b7f466f756e646174696f6e20436f6c6c656374696f6e2054656d706c6174652076815260008251610ecb816020850160208701610e63565b9190910160200192915050565b7f4643547600000000000000000000000000000000000000000000000000000000815260008251610f10816004850160208701610e63565b9190910160040192915050565b60008151808452610f35816020860160208601610e63565b601f01601f19169290920160200192915050565b6001600160a01b0384168152606060208201526000610f6b6060830185610f1d565b8281036040840152610f7d8185610f1d565b9695505050505050565b634e487b7160e01b600052601260045260246000fd5b600082610fac57610fac610f87565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610fd957610fd9610e32565b500390565b600082610fed57610fed610f87565b500690565b6000821982111561100557611005610e32565b500190565b634e487b7160e01b600052603260045260246000fdfea264697066735822122089ab8df97a80645c40f65cb3d89a1a11b1d0049c0440eb6c76027b1216d1be0b64736f6c63430008090033000000000000000000000000461aa494426e04fb2449068bad5948a0d720aef200000000000000000000000067df244584b67e8c51b10ad610aaffa9a402fdb6
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100a25760003560e01c806354fd4d5011610076578063a17bb1991161005b578063a17bb1991461013c578063bb7e36481461014f578063ca53b3911461016257600080fd5b806354fd4d50146101125780635c60da1b1461012957600080fd5b80629dfb89146100a75780631b8c9c4b146100bc5780634197ed74146100ec5780634b263865146100ff575b600080fd5b6100ba6100b5366004610c62565b610175565b005b6100cf6100ca366004610c7d565b610273565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cf6100fa366004610cf0565b6102df565b6100ba61010d366004610c62565b61048e565b61011b60035481565b6040519081526020016100e3565b6001546100cf906001600160a01b031681565b6100ba61014a366004610c62565b610584565b6002546100cf906001600160a01b031681565b6000546100cf906001600160a01b031681565b600054604051630935e01b60e21b81523360048201526001600160a01b03909116906324d7806c9060240160206040518083038186803b1580156101b857600080fd5b505afa1580156101cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101f09190610d64565b6102675760405162461bcd60e51b815260206004820152603960248201527f464e44436f6c6c656374696f6e466163746f72793a2043616c6c657220646f6560448201527f73206e6f742068617665207468652041646d696e20726f6c650000000000000060648201526084015b60405180910390fd5b61027081610680565b50565b60006102d66102c484846040516bffffffffffffffffffffffff19606084901b1660208201526034810182905260009060540160405160208183030381529060405280519060200120905092915050565b6001546001600160a01b031690610833565b90505b92915050565b6000826103545760405162461bcd60e51b815260206004820152602860248201527f464e44436f6c6c656374696f6e466163746f72793a2053796d626f6c2069732060448201527f7265717569726564000000000000000000000000000000000000000000000000606482015260840161025e565b604080513360601b6bffffffffffffffffffffffff1916602080830191909152603480830186905283518084039091018152605490920190925280519101206000906103ac906001546001600160a01b0316906108af565b6040517f906571470000000000000000000000000000000000000000000000000000000081529091506001600160a01b038216906390657147906103fc9033908b908b908b908b90600401610db6565b600060405180830381600087803b15801561041657600080fd5b505af115801561042a573d6000803e3d6000fd5b50505050600354336001600160a01b0316826001600160a01b03167fd3cbcb86b6ae20e08baf6a5fbaf0c922acff26cdc663bdf06744f5023bbcd2548a8a8a8a8a60405161047c959493929190610df8565b60405180910390a49695505050505050565b600054604051630935e01b60e21b81523360048201526001600160a01b03909116906324d7806c9060240160206040518083038186803b1580156104d157600080fd5b505afa1580156104e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105099190610d64565b61057b5760405162461bcd60e51b815260206004820152603960248201527f464e44436f6c6c656374696f6e466163746f72793a2043616c6c657220646f6560448201527f73206e6f742068617665207468652041646d696e20726f6c6500000000000000606482015260840161025e565b61027081610966565b600054604051630935e01b60e21b81523360048201526001600160a01b03909116906324d7806c9060240160206040518083038186803b1580156105c757600080fd5b505afa1580156105db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ff9190610d64565b6106715760405162461bcd60e51b815260206004820152603960248201527f464e44436f6c6c656374696f6e466163746f72793a2043616c6c657220646f6560448201527f73206e6f742068617665207468652041646d696e20726f6c6500000000000000606482015260840161025e565b61027081610a38565b3b151590565b6001600160a01b0381163b6106fd5760405162461bcd60e51b815260206004820152603660248201527f464e44436f6c6c656374696f6e466163746f72793a20496d706c656d656e746160448201527f74696f6e206973206e6f74206120636f6e747261637400000000000000000000606482015260840161025e565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556003805490600061073583610e48565b90915550506000546003546001600160a01b038084169263906571479291169061075e90610b0c565b60405160200161076e9190610e93565b604051602081830303815290604052610788600354610b0c565b6040516020016107989190610ed8565b6040516020818303038152906040526040518463ffffffff1660e01b81526004016107c593929190610f49565b600060405180830381600087803b1580156107df57600080fd5b505af11580156107f3573d6000803e3d6000fd5b50505050600354816001600160a01b03167f5678af47993f4856157dd819bee3183b87c10ee1b3575a5128fe25896c073a2860405160405180910390a350565b60006102d68383306040517f3d602d80600a3d3981f3363d3d373d3d3d363d730000000000000000000000008152606093841b60148201527f5af43d82803e903d91602b57fd5bf3ff000000000000000000000000000000006028820152921b6038830152604c8201526037808220606c830152605591012090565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528360601b60148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f59150506001600160a01b0381166102d95760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c6564000000000000000000604482015260640161025e565b6001600160a01b0381163b6109e35760405162461bcd60e51b815260206004820152603560248201527f464e44436f6c6c656374696f6e466163746f72793a20526f6c6573436f6e747260448201527f616374206973206e6f74206120636f6e74726163740000000000000000000000606482015260840161025e565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316908117825560405190917f2cff90ef548ed2e2f7b9815b7089188bc1e96989b6346ac05a58750d92607d4b91a250565b6001600160a01b0381163b610ab55760405162461bcd60e51b815260206004820152603a60248201527f464e44436f6c6c656374696f6e466163746f72793a2050726f78792063616c6c60448201527f2061646472657373206973206e6f74206120636f6e7472616374000000000000606482015260840161025e565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f7213e3d637e4ef4968f947d5f602103307355f708bfd5bfce9d87da7c78f852190600090a250565b606081610b4c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610b765780610b6081610e48565b9150610b6f9050600a83610f9d565b9150610b50565b60008167ffffffffffffffff811115610b9157610b91610fb1565b6040519080825280601f01601f191660200182016040528015610bbb576020820181803683370190505b5090505b8415610c3e57610bd0600183610fc7565b9150610bdd600a86610fde565b610be8906030610ff2565b60f81b818381518110610bfd57610bfd61100a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610c37600a86610f9d565b9450610bbf565b949350505050565b80356001600160a01b0381168114610c5d57600080fd5b919050565b600060208284031215610c7457600080fd5b6102d682610c46565b60008060408385031215610c9057600080fd5b610c9983610c46565b946020939093013593505050565b60008083601f840112610cb957600080fd5b50813567ffffffffffffffff811115610cd157600080fd5b602083019150836020828501011115610ce957600080fd5b9250929050565b600080600080600060608688031215610d0857600080fd5b853567ffffffffffffffff80821115610d2057600080fd5b610d2c89838a01610ca7565b90975095506020880135915080821115610d4557600080fd5b50610d5288828901610ca7565b96999598509660400135949350505050565b600060208284031215610d7657600080fd5b81518015158114610d8657600080fd5b9392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0386168152606060208201526000610dd9606083018688610d8d565b8281036040840152610dec818587610d8d565b98975050505050505050565b606081526000610e0c606083018789610d8d565b8281036020840152610e1f818688610d8d565b9150508260408301529695505050505050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415610e5c57610e5c610e32565b5060010190565b60005b83811015610e7e578181015183820152602001610e66565b83811115610e8d576000848401525b50505050565b7f466f756e646174696f6e20436f6c6c656374696f6e2054656d706c6174652076815260008251610ecb816020850160208701610e63565b9190910160200192915050565b7f4643547600000000000000000000000000000000000000000000000000000000815260008251610f10816004850160208701610e63565b9190910160040192915050565b60008151808452610f35816020860160208601610e63565b601f01601f19169290920160200192915050565b6001600160a01b0384168152606060208201526000610f6b6060830185610f1d565b8281036040840152610f7d8185610f1d565b9695505050505050565b634e487b7160e01b600052601260045260246000fd5b600082610fac57610fac610f87565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610fd957610fd9610e32565b500390565b600082610fed57610fed610f87565b500690565b6000821982111561100557611005610e32565b500190565b634e487b7160e01b600052603260045260246000fdfea264697066735822122089ab8df97a80645c40f65cb3d89a1a11b1d0049c0440eb6c76027b1216d1be0b64736f6c63430008090033