Token $GOLD

Overview ERC20

Price
$0.00 @ 0.000000 AVAX
Fully Diluted Market Cap
Total Supply:
355,820.708372 GOLD

Holders:
482 addresses

Transfers:
-

Contract:
0x2D052048Fe7e4f59277E5E5ED5D21d35419Fe7470x2D052048Fe7e4f59277E5E5ED5D21d35419Fe747

Decimals:
18

Social Profiles:
Not Available, Update ?

Loading
[ Download CSV Export  ] 
Loading
[ Download CSV Export  ] 
Loading

Click here to update the token ICO / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
GoldV2

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-01-21
*/

// File: hardhat/console.sol


pragma solidity >= 0.4.22 <0.9.0;

library console {
	address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

	function _sendLogPayload(bytes memory payload) private view {
		uint256 payloadLength = payload.length;
		address consoleAddress = CONSOLE_ADDRESS;
		assembly {
			let payloadStart := add(payload, 32)
			let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
		}
	}

	function log() internal view {
		_sendLogPayload(abi.encodeWithSignature("log()"));
	}

	function logInt(int p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
	}

	function logUint(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function logString(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function logBool(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function logAddress(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function logBytes(bytes memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
	}

	function logBytes1(bytes1 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
	}

	function logBytes2(bytes2 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
	}

	function logBytes3(bytes3 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
	}

	function logBytes4(bytes4 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
	}

	function logBytes5(bytes5 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
	}

	function logBytes6(bytes6 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
	}

	function logBytes7(bytes7 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
	}

	function logBytes8(bytes8 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
	}

	function logBytes9(bytes9 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
	}

	function logBytes10(bytes10 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
	}

	function logBytes11(bytes11 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
	}

	function logBytes12(bytes12 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
	}

	function logBytes13(bytes13 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
	}

	function logBytes14(bytes14 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
	}

	function logBytes15(bytes15 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
	}

	function logBytes16(bytes16 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
	}

	function logBytes17(bytes17 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
	}

	function logBytes18(bytes18 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
	}

	function logBytes19(bytes19 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
	}

	function logBytes20(bytes20 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
	}

	function logBytes21(bytes21 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
	}

	function logBytes22(bytes22 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
	}

	function logBytes23(bytes23 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
	}

	function logBytes24(bytes24 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
	}

	function logBytes25(bytes25 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
	}

	function logBytes26(bytes26 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
	}

	function logBytes27(bytes27 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
	}

	function logBytes28(bytes28 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
	}

	function logBytes29(bytes29 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
	}

	function logBytes30(bytes30 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
	}

	function logBytes31(bytes31 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
	}

	function logBytes32(bytes32 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
	}

	function log(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function log(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function log(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function log(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function log(uint p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
	}

	function log(uint p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
	}

	function log(uint p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
	}

	function log(uint p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
	}

	function log(string memory p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
	}

	function log(string memory p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
	}

	function log(string memory p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
	}

	function log(string memory p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
	}

	function log(bool p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
	}

	function log(bool p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
	}

	function log(bool p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
	}

	function log(bool p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
	}

	function log(address p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
	}

	function log(address p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
	}

	function log(address p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
	}

	function log(address p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
	}

	function log(uint p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
	}

	function log(uint p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
	}

	function log(uint p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
	}

	function log(uint p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
	}

	function log(uint p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
	}

	function log(uint p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
	}

	function log(uint p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
	}

	function log(uint p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
	}

	function log(uint p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
	}

	function log(uint p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
	}

	function log(uint p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
	}

	function log(uint p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
	}

	function log(string memory p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
	}

	function log(string memory p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
	}

	function log(string memory p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
	}

	function log(string memory p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
	}

	function log(bool p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
	}

	function log(bool p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
	}

	function log(bool p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
	}

	function log(bool p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
	}

	function log(bool p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
	}

	function log(bool p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
	}

	function log(bool p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
	}

	function log(bool p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
	}

	function log(bool p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
	}

	function log(bool p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
	}

	function log(bool p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
	}

	function log(bool p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
	}

	function log(address p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
	}

	function log(address p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
	}

	function log(address p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
	}

	function log(address p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
	}

	function log(address p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
	}

	function log(address p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
	}

	function log(address p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
	}

	function log(address p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
	}

	function log(address p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
	}

	function log(address p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
	}

	function log(address p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
	}

	function log(address p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
	}

	function log(address p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
	}

	function log(address p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
	}

	function log(address p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
	}

	function log(address p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
	}

	function log(uint p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
	}

}

// File: @openzeppelin/contracts/utils/Counters.sol


// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library StringsUpgradeable {
    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);
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @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 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);
            }
        }
    }
}

// File: @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol


// OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol)

pragma solidity ^0.8.0;


/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
 * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        // If the contract is initializing we ignore whether _initialized is set in order to support multiple
        // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
        // contract may have been reentered.
        require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} modifier, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol


// 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 ContextUpgradeable is Initializable {
    function __Context_init() internal onlyInitializing {
        __Context_init_unchained();
    }

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
    uint256[50] private __gap;
}

// File: @openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721ReceiverUpgradeable {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: @openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165Upgradeable {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;



/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
    function __ERC165_init() internal onlyInitializing {
        __ERC165_init_unchained();
    }

    function __ERC165_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165Upgradeable).interfaceId;
    }
    uint256[50] private __gap;
}

// File: @openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721Upgradeable is IERC165Upgradeable {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

// File: @openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721MetadataUpgradeable is IERC721Upgradeable {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// File: @openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;









/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {
    using AddressUpgradeable for address;
    using StringsUpgradeable for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC721_init_unchained(name_, symbol_);
    }

    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {
        return
            interfaceId == type(IERC721Upgradeable).interfaceId ||
            interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721Upgradeable.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721Upgradeable.ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721Upgradeable.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits a {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
    uint256[44] private __gap;
}

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

// File: @openzeppelin/contracts/interfaces/IERC721.sol


// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721.sol)

pragma solidity ^0.8.0;


// File: @openzeppelin/contracts/utils/Context.sol


// 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;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;


/**
 * @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 Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing 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);
    }
}

// File: Authorizable.sol

pragma solidity >=0.8.0;


contract Authorizable is Ownable {

    mapping(address => bool) public authorized;

    modifier onlyAuthorized() {
        require(authorized[msg.sender] ||  owner() == msg.sender, "Not authorized");
        _;
    }

    function addAuthorized(address _toAdd) onlyOwner public {
        require(_toAdd != address(0));
        authorized[_toAdd] = true;
    }

    function removeAuthorized(address _toRemove) onlyOwner public {
        require(_toRemove != address(0));
        require(_toRemove != msg.sender);
        authorized[_toRemove] = false;
    }

}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

// File: @openzeppelin/contracts/token/ERC20/ERC20.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;




/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

// File: MinerJoe.sol
// contracts/ERC721.sol
// upgradeable contract

pragma solidity >=0.8.0;




interface splitter {
    function split(uint256 value) external payable;
}
contract MinerJoe is ERC721Upgradeable {
    // Royalty
    address private _owner;
    address private _royaltiesAddr; // royality receiver
    uint256 public royaltyPercentage; // royalty based on sales price
    mapping(address => bool) public excludedList; // list of people who dont have to pay fee

    //GB HOLDERS EARLY ACCESS TOKENS
    uint256 public constant gbHoldersMaxMint = 900;
    mapping(address => bool) public gbholders;

    address public GB_erc20_contract;

    uint256[] private _gbTokenSupply;

    // cost to mint
    uint256 public mintFeeAmount;

    // // NFT Meta data
    string public baseURL;

    uint256 public constant maxSupply = 10000;

    // enable flag for public and GB
    bool public openForGB;
    bool public openForPublic;

    // define Miner struct
    struct Miner {
        uint256 tokenId;
        // string tokenURI;
        address mintedBy;
        address currentOwner;
        uint256 previousPrice;
        uint256 price;
        uint256 numberOfTransfers;
        bool forSale;
        uint256 level;
    }

    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    // map id to Miner obj
    mapping(uint256 => Miner) public allMiners;

    //  implement the IERC721Enumerable which no longer come by default in openzeppelin 4.x
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

    //================================= Events ================================= //
    event GBERC20Checked(address indexed _holder, uint256 _bal, bool _result);

    event SaleToggle(uint256 minerNumber, bool isForSale, uint256 price);
    event PurchaseEvent(uint256 minerNumber, address from, address to, uint256 price);

    function initialize(
        address _contractOwner,
        address _royaltyReceiver,
        uint256 _royaltyPercentage,
        uint256 _mintFeeAmount,
        string memory _baseURL,
        bool _openForPublic
    ) public initializer {
        // __ERC721_init("swng", "swng");
        __ERC721_init("MinerJoe", "MinerJoe");
        royaltyPercentage = _royaltyPercentage;
        _owner = _contractOwner;
        _royaltiesAddr = _royaltyReceiver;
        mintFeeAmount = _mintFeeAmount;
        excludedList[_contractOwner] = true; // add owner to exclude list
        excludedList[_royaltyReceiver] = true; // add artist to exclude list
        baseURL = _baseURL;
        openForPublic = _openForPublic;
    }

    function mint(uint256 numberOfToken) public payable {
        // check if thic fucntion caller is not an zero address account
        require(openForPublic == true, "not open");
        require(msg.sender != address(0));
        require(
            _allTokens.length + numberOfToken <= maxSupply,
            "max supply"
        );
        require(numberOfToken > 0, "Min 1");
        require(numberOfToken <= 12, "Max 12");
        uint256 price = 0;
        // pay for minting cost
        if (excludedList[msg.sender] == false) {
            // send token's worth of ethers to the owner
            price = mintFeeAmount * numberOfToken;
            require(msg.value == price, "Not enough fee");
            payable(_royaltiesAddr).transfer(msg.value);
            splitter(_royaltiesAddr).split(msg.value);
        } else {
            // return money to sender // since its free
            payable(msg.sender).transfer(msg.value);
        }

        for (uint256 i = 1; i <= numberOfToken; i++) {
            _tokenIds.increment();
            uint256 newItemId = _tokenIds.current();
            _safeMint(msg.sender, newItemId);
            Miner memory newMiner = Miner(
                newItemId,
                msg.sender,
                msg.sender,
                0,
                price,
                0,
                false,
                100
            );
            // add the token id to the allMiners
            allMiners[newItemId] = newMiner;
        }
    }


    function changeUrl(string memory url) external {
        require(msg.sender == _owner, "Only owner");
        baseURL = url;
    }

    function totalSupply() public view returns (uint256) {
        return _allTokens.length;
    }

    // GB holder related functions
    function gbTotalSupply() public view returns (uint256) {
        return _gbTokenSupply.length;
    }


    function setPriceForSale(
        uint256 _tokenId,
        uint256 _newPrice,
        bool isForSale
    ) external {
        require(_exists(_tokenId), "token not found");
        address tokenOwner = ownerOf(_tokenId);
        require(tokenOwner == msg.sender, "not owner");
        Miner memory miner = allMiners[_tokenId];
        miner.price = _newPrice;
        miner.forSale = isForSale;
        allMiners[_tokenId] = miner;
        emit SaleToggle(_tokenId, isForSale, _newPrice);
    }

    function getAllSaleTokens() public view returns (uint256[] memory) {
        uint256 _totalSupply = totalSupply();
        uint256[] memory _tokenForSales = new uint256[](_totalSupply);
        uint256 counter = 0;
        for (uint256 i = 1; i <= _totalSupply; i++) {
            if (allMiners[i].forSale == true) {
                _tokenForSales[counter] = allMiners[i].tokenId;
                counter++;
            }
        }
        return _tokenForSales;
    }
/*

    struct Miner {
        uint256 tokenId;
        // string tokenURI;
        address mintedBy;
        address currentOwner;
        uint256 previousPrice;
        uint256 price;
        uint256 numberOfTransfers;
        bool forSale;
        uint256 level;
    }

*/
    function getAllTokensInfo(uint256[] calldata IDList) public view returns (uint256[] memory, 
    address[] memory, 
    uint256[] memory, 
    uint256[] memory, 
    bool[] memory,
    uint256[] memory) {
        uint256[] memory tokenId = new uint256[](IDList.length);
        address[] memory currentOwner = new address[](IDList.length);
        uint256[] memory previousPrice = new uint256[](IDList.length);
        uint256[] memory price = new uint256[](IDList.length);
        bool[] memory forSale = new bool[](IDList.length);
        uint256[] memory level = new uint256[](IDList.length);

        uint256 index = 0;
        for (; index < IDList.length; ++index) {
            uint256 currentIndex = IDList[index];
            tokenId[index] = allMiners[currentIndex].tokenId;
            currentOwner[index] = allMiners[currentIndex].currentOwner;
            previousPrice[index] = allMiners[currentIndex].previousPrice;
            price[index] = allMiners[currentIndex].price;
            forSale[index] = allMiners[currentIndex].forSale;
            level[index] = allMiners[currentIndex].level;
        }
        
        return (tokenId, currentOwner, previousPrice, price, forSale, level);
    }

    // by a token by passing in the token's id
    function buyToken(uint256 _tokenId) public payable {
        // check if the token id of the token being bought exists or not
        require(_exists(_tokenId));
        // get the token's owner
        address tokenOwner = ownerOf(_tokenId);
        // token's owner should not be an zero address account
        require(tokenOwner != address(0));
        // the one who wants to buy the token should not be the token's owner
        require(tokenOwner != msg.sender);
        // get that token from all Miners mapping and create a memory of it defined as (struct => Miner)
        Miner memory miner = allMiners[_tokenId];
        // price sent in to buy should be equal to or more than the token's price
        require(msg.value >= miner.price);
        // token should be for sale
        require(miner.forSale);
        uint256 amount = msg.value;
        uint256 _royaltiesAmount = (amount * royaltyPercentage) / 100;
        uint256 payOwnerAmount = amount - _royaltiesAmount;
        payable(_royaltiesAddr).transfer(_royaltiesAmount);
        splitter(_royaltiesAddr).split(_royaltiesAmount);
        payable(miner.currentOwner).transfer(payOwnerAmount);
        miner.previousPrice = miner.price;
        allMiners[_tokenId] = miner;
        _transfer(tokenOwner, msg.sender, _tokenId);
        emit PurchaseEvent(_tokenId, miner.currentOwner, msg.sender, miner.price);
    }

    function tokenOfOwnerByIndex(address owner, uint256 index)
        public
        view
        returns (uint256)
    {
        require(index < balanceOf(owner), "out of bounds");
        return _ownedTokens[owner][index];
    }

    //  URI Storage override functions
    /** Overrides ERC-721's _baseURI function */
    function _baseURI()
        internal
        view
        virtual
        override(ERC721Upgradeable)
        returns (string memory)
    {
        return baseURL;
    }

    function _burn(uint256 tokenId) internal override(ERC721Upgradeable) {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721Upgradeable)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override(ERC721Upgradeable) {
        super._beforeTokenTransfer(from, to, tokenId);
        Miner memory miner = allMiners[tokenId];
        miner.currentOwner = to;
        miner.numberOfTransfers += 1;
        miner.forSale = false;
        allMiners[tokenId] = miner;
        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = balanceOf(to);
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId)
        private
    {
        uint256 lastTokenIndex = balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }

    // upgrade contract to support authorized

    mapping(address => bool) public authorized;

    modifier onlyAuthorized() {
        require(authorized[msg.sender] ||  msg.sender == _owner , "Not authorized");
        _;
    }

    function addAuthorized(address _toAdd) public {
        require(msg.sender == _owner, 'Not owner');
        require(_toAdd != address(0));
        authorized[_toAdd] = true;
    }

    function removeAuthorized(address _toRemove) public {
        require(msg.sender == _owner, 'Not owner');
        require(_toRemove != address(0));
        require(_toRemove != msg.sender);
        authorized[_toRemove] = false;
    }

    // upgrade the contract
    function setLevel(uint256 _tokenId, uint256 _newLevel) external onlyAuthorized {
        Miner memory miner = allMiners[_tokenId];
        miner.level = _newLevel;
        // set and update that token in the mapping
        allMiners[_tokenId] = miner;
    }
}
// File: @openzeppelin/contracts/utils/math/SafeMath.sol


// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

// File: GoldV2.sol

//SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;







contract GoldV2 is ERC20, Authorizable {
    using SafeMath for uint256;
    string private TOKEN_NAME = "$GOLD";
    string private TOKEN_SYMBOL = "GOLD";

    address public MINER_CONTRACT;

    // the base number of $GOLD per miner (i.e. 0.75 $gold)
    uint256 public BASE_HOLDER_GOLD = 750000000000000000;

    // the number of $GOLD per miner per day per level (i.e. 0.25 $gold /miner /day /level)
    uint256 public GOLD_PER_DAY_PER_LEVEL = 250000000000000000;

    // how much gold it costs to skip the cooldown
    uint256 public COOLDOWN_BASE = 100000000000000000000; // base 100
    // how much additional gold it costs to skip the cooldown per level
    uint256 public COOLDOWN_BASE_FACTOR = 100000000000000000000; // additional 100 per level
    // how long to wait before skip cooldown can be re-invoked
    uint256 public COOLDOWN_CD_IN_SECS = 86400; // additional 100 per level

    uint256 public LEVELING_BASE = 25;
    uint256 public LEVELING_RATE = 2;
    uint256 public COOLDOWN_RATE = 3600; // 60 mins

    /**
     * Stores staked miner fields (=> 152 <= stored in order of size for optimal packing!)
     */
    struct StakedMinerObj {
        // the current level level (0 -> 16,777,216)
        uint24 level;
        // when to calculate gold from (max 20/02/36812, 11:36:16)
        uint32 sinceTs;
        // for the skipCooldown's cooldown (max 20/02/36812, 11:36:16)
        uint32 lastSkippedTs;
        // how much this miner has been fed (in whole numbers)
        uint48 creditsAmount;
        // cooldown time until level up is allow (per level)
        uint32 cooldownTs;
    }

    // redundant struct - can't be packed? (max totalLevel = 167,772,160,000)
    uint40 public totalLevel;
    uint16 public totalStakedMiner;

    StakedMinerObj[100001] public stakedMiner;

    // Events

    event Minted(address owner, uint256 goldAmt);
    event Burned(address owner, uint256 goldAmt);
    event Staked(uint256 tid, uint256 ts);
    event UnStaked(uint256 tid, uint256 ts);

    // Constructor

    constructor(address _minerContract) ERC20(TOKEN_NAME, TOKEN_SYMBOL) {
        MINER_CONTRACT = _minerContract;
    }

    // "READ" Functions
    // How much is required to be fed to level up per level

    function creditsLevelingRate(uint256 level) public view returns (uint256) {
        // need to divide the level by 100, and make sure the credits level is at 18 decimals
        return LEVELING_BASE * ((level / 100)**LEVELING_RATE);
    }

    // when using the value, need to add the current block timestamp as well
    function cooldownRate(uint256 level) public view returns (uint256) {
        // need to divide the level by 100

        return (level / 100) * COOLDOWN_RATE;
    }

    // Staking Functions

    // stake miner, check if is already staked, get all detail for miner such as
    function _stake(uint256 tid) internal {
        MinerJoe x = MinerJoe(MINER_CONTRACT);

        // verify user is the owner of the miner...
        require(x.ownerOf(tid) == msg.sender, "NOT OWNER");

        // get calc'd values...
        (, , , , , , , uint256 level) = x.allMiners(tid);
        // if lastSkippedTs is 0 its mean it never have a last skip timestamp
        StakedMinerObj memory c = stakedMiner[tid];
        uint32 ts = uint32(block.timestamp);
        if (stakedMiner[tid].level == 0) {
            // create staked miner...
            stakedMiner[tid] = StakedMinerObj(
                uint24(level),
                ts,
                c.lastSkippedTs > 0 ? c.lastSkippedTs :  uint32(ts - COOLDOWN_CD_IN_SECS),
                uint48(0),
                uint32(ts) + uint32(cooldownRate(level)) 
            );

            // update snapshot values...
            // N.B. could be optimised for multi-stakes - but only saves 0.5c AUD per miner - not worth it, this is a one time operation.
            totalStakedMiner += 1;
            totalLevel += uint24(level);

            // let ppl know!
            emit Staked(tid, block.timestamp);
        }
    }

    // function staking(uint256 tokenId) external {
    //     _stake(tokenId);
    // }

    function stake(uint256[] calldata tids) external {
        for (uint256 i = 0; i < tids.length; i++) {
            _stake(tids[i]);
        }
    }

    /**
     * Calculates the amount of gold that is claimable from a miner.
     */
    function claimableView(uint256 tokenId) public view returns (uint256) {
        StakedMinerObj memory c = stakedMiner[tokenId];
        if (c.level > 0) {
            uint256 goldPerDay = ((GOLD_PER_DAY_PER_LEVEL * (c.level / 100)) +
                BASE_HOLDER_GOLD);
            uint256 deltaSeconds = block.timestamp - c.sinceTs;
            return deltaSeconds * (goldPerDay / 86400);
        } else {
            return 0;
        }
    }

    function myStakedMiner() public view returns (uint256[] memory) {
        MinerJoe x = MinerJoe(MINER_CONTRACT);
        uint256 minerCount = x.balanceOf(msg.sender);
        uint256[] memory tokenIds = new uint256[](minerCount);
        uint256 counter = 0;
        for (uint256 i = 0; i < minerCount; i++) {
            uint256 tokenId = x.tokenOfOwnerByIndex(msg.sender, i);
            StakedMinerObj memory miner = stakedMiner[tokenId];
            if (miner.level > 0) {
                tokenIds[counter] = tokenId;
                counter++;
            }
        }
        return tokenIds;
    }

    /**
     * Calculates the TOTAL amount of gold that is claimable from ALL miners.
     */
    function myClaimableView() public view returns (uint256) {
        MinerJoe x = MinerJoe(MINER_CONTRACT);
        uint256 cnt = x.balanceOf(msg.sender);
        require(cnt > 0, "NO MINER");
        uint256 totalClaimable = 0;
        for (uint256 i = 0; i < cnt; i++) {
            uint256 tokenId = x.tokenOfOwnerByIndex(msg.sender, i);
            StakedMinerObj memory miner = stakedMiner[tokenId];
            // make sure that the token is staked
            if (miner.level > 0) {
                uint256 claimable = claimableView(tokenId);
                if (claimable > 0) {
                    totalClaimable = totalClaimable + claimable;
                }
            }
        }
        return totalClaimable;
    }

    /**
     * Claims gold from the provided miners.
     */
    function _claimGold(uint256[] calldata tokenIds) internal {
        MinerJoe x = MinerJoe(MINER_CONTRACT);
        uint256 totalClaimableGold = 0;
        for (uint256 i = 0; i < tokenIds.length; i++) {
            require(x.ownerOf(tokenIds[i]) == msg.sender, "NOT OWNER");
            StakedMinerObj memory miner = stakedMiner[tokenIds[i]];
            // we only care about miner that have been staked (i.e. level > 0) ...
            if (miner.level > 0) {
                uint256 claimableGold = claimableView(tokenIds[i]);
                if (claimableGold > 0) {
                    totalClaimableGold = totalClaimableGold + claimableGold;
                    // reset since, for the next calc...
                    miner.sinceTs = uint32(block.timestamp);
                    stakedMiner[tokenIds[i]] = miner;
                }
            }
        }
        if (totalClaimableGold > 0) {
            _mint(msg.sender, totalClaimableGold);
            emit Minted(msg.sender, totalClaimableGold);
        }
    }

    /**
     * Claims gold from the provided miners.
     */
    function claimGold(uint256[] calldata tokenIds) external {
        _claimGold(tokenIds);
    }

    /**
     * Unstakes a miner. Why you'd call this, I have no idea.
     */
    function _unstake(uint256 tokenId) internal {
        MinerJoe x = MinerJoe(MINER_CONTRACT);

        // verify user is the owner of the miner...
        require(x.ownerOf(tokenId) == msg.sender, "NOT OWNER");

        // update miner...
        StakedMinerObj memory c = stakedMiner[tokenId];
        if (c.level > 0) {
            // update snapshot values...
            totalLevel -= uint24(c.level);
            totalStakedMiner -= 1;

            c.level = 0;
            stakedMiner[tokenId] = c;

            // let ppl know!
            emit UnStaked(tokenId, block.timestamp);
        }
    }

    function _unstakeMultiple(uint256[] calldata tids) internal {
        for (uint256 i = 0; i < tids.length; i++) {
            _unstake(tids[i]);
        }
    }

    /**
     * Unstakes MULTIPLE miner. Why you'd call this, I have no idea.
     */
    function unstake(uint256[] calldata tids) external {
        _unstakeMultiple(tids);
    }

    /**
     * Unstakes MULTIPLE miner AND claims the gold.
     */
    function withdrawAllMinerAndClaim(uint256[] calldata tids) external {
        _claimGold(tids);
        _unstakeMultiple(tids);
    }

    /**
     * Public : update the miner's level level.
     */
     function levelUpMiner(uint256 tid) external {
        StakedMinerObj memory c = stakedMiner[tid];
        require(c.level > 0, "NOT STAKED");

        MinerJoe x = MinerJoe(MINER_CONTRACT);
        // NOTE Does it matter if sender is not owner?
        // require(x.ownerOf(minerId) == msg.sender, "NOT OWNER");

        // check: miner has eaten enough...
        require(c.creditsAmount >= creditsLevelingRate(c.level), "MORE FOOD REQD");
        // check: cooldown has passed...
        require(block.timestamp >= c.cooldownTs, "COOLDOWN NOT MET");

        // increase level, reset eaten to 0, update next credits level and cooldown time
        c.level = c.level + 100;
        c.creditsAmount = 0;
        c.cooldownTs = uint32(block.timestamp + cooldownRate(c.level));
        stakedMiner[tid] = c;

        // need to increase overall size
        totalLevel += uint24(100);

        // and update the miner contract
        x.setLevel(tid, c.level);
    }

    /**
     * Internal: burns the given amount of gold from the wallet.
     */
    function _burnGold(address sender, uint256 goldAmount) internal {
        // NOTE do we need to check this before burn?
        require(balanceOf(sender) >= goldAmount, "NOT ENOUGH GOLD");
        _burn(sender, goldAmount);
        emit Burned(sender, goldAmount);
    }

    /**
     * Burns the given amount of gold from the sender's wallet.
     */
    function burnGold(address sender, uint256 goldAmount) external onlyAuthorized {
        _burnGold(sender, goldAmount);
    }

    /**
     * Skips the "levelUp" cooling down period, in return for burning gold.
     */
     function skipCoolingOff(uint256 tokenId, uint256 goldAmount) external {
        StakedMinerObj memory miner = stakedMiner[tokenId];
        require(miner.level != 0, "NOT STAKED");

        uint32 ts = uint32(block.timestamp);

        // NOTE Does it matter if sender is not owner?
        // MinerJoe instance = MinerJoe(MINER_CONTRACT);
        // require(instance.ownerOf(minerId) == msg.sender, "NOT OWNER");

        // check: enough gold in wallet to pay
        uint256 walletBalance = balanceOf(msg.sender);
        require(walletBalance >= goldAmount, "NOT ENOUGH gold IN WALLET");

        // check: provided gold amount is enough to skip this level
        require(goldAmount >= checkSkipCoolingOffAmt(miner.level), "NOT ENOUGH gold TO SKIP");

        // check: user hasn't skipped cooldown in last 24 hrs
        require((miner.lastSkippedTs + COOLDOWN_CD_IN_SECS) <= ts, "BLOCKED BY 24HR COOLDOWN");

        // burn gold
        _burnGold(msg.sender, goldAmount);

        // disable cooldown
        miner.cooldownTs = ts;
        // track last time cooldown was skipped (i.e. now)
        miner.lastSkippedTs = ts;
        stakedMiner[tokenId] = miner;
    }

    /**
     * Calculates the cost of skipping cooldown.
     */
    function checkSkipCoolingOffAmt(uint256 level) public view returns (uint256) {
        // NOTE cannot assert level is < 100... we can have large numbers!
        return ((level / 100) * COOLDOWN_BASE_FACTOR);
    }

    /**
     *  Giving credis to miner
     */
    function equipMiner(uint256 tokenId, uint256 creditsAmount)
        external
        onlyAuthorized
    {
        StakedMinerObj memory miner = stakedMiner[tokenId];
        require(miner.level > 0, "NOT STAKED");
        require(creditsAmount > 0, "NOTHING TO EQUIP");
        // update the block time as well as claimable
        miner.creditsAmount = uint48(creditsAmount / 1e18) + miner.creditsAmount;
        stakedMiner[tokenId] = miner;
    }

    // NOTE What happens if we update the multiplier, and people have been staked for a year...?
    // We need to snapshot somehow... but we're physically unable to update 10k records!!!

    // ADMIN: to update the cost of skipping cooldown
    function updateSkipCooldownValues(
        uint256 a, 
        uint256 b, 
        uint256 c,
        uint256 d,
        uint256 e
    ) external onlyOwner {
        COOLDOWN_BASE = a;
        COOLDOWN_BASE_FACTOR = b;
        COOLDOWN_CD_IN_SECS = c;
        BASE_HOLDER_GOLD = d;
        GOLD_PER_DAY_PER_LEVEL = e;
    }

    // INTRA-CONTRACT: use this function to mint gold to users
    // this also get called by the CREDITS contract
    function mintGold(address sender, uint256 amount) external onlyAuthorized {
        _mint(sender, amount);
        emit Minted(sender, amount);
    }

    // ADMIN: drop gold to the given miner wallet owners (within the minerId range from->to).
    function airdropToExistingHolder(
        uint256 from,
        uint256 to,
        uint256 amountOfGold
    ) external onlyOwner {
        // mint 100 gold to every owners
        MinerJoe instance = MinerJoe(MINER_CONTRACT);
        for (uint256 i = from; i <= to; i++) {
            address currentOwner = instance.ownerOf(i);
            if (currentOwner != address(0)) {
                _mint(currentOwner, amountOfGold * 1e18);
            }
        }
    }

    // ADMIN: Rebalance user wallet by minting gold (within the minerId range from->to).
    // NOTE: This is use when we need to update gold production
    function rebalanceGoldClaimableToUserWallet(uint256 from, uint256 to)
        external
        onlyOwner
    {
        MinerJoe instance = MinerJoe(MINER_CONTRACT);
        for (uint256 i = from; i <= to; i++) {
            address currentOwner = instance.ownerOf(i);
            StakedMinerObj memory miner = stakedMiner[i];
            // we only care about miner that have been staked (i.e. level > 0) ...
            if (miner.level > 0) {
                _mint(currentOwner, claimableView(i));
                miner.sinceTs = uint32(block.timestamp);
                stakedMiner[i] = miner;
            }
        }
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_minerContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"goldAmt","type":"uint256"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"goldAmt","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"UnStaked","type":"event"},{"inputs":[],"name":"BASE_HOLDER_GOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COOLDOWN_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COOLDOWN_BASE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COOLDOWN_CD_IN_SECS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COOLDOWN_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOLD_PER_DAY_PER_LEVEL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEVELING_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEVELING_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINER_CONTRACT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_toAdd","type":"address"}],"name":"addAuthorized","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"uint256","name":"amountOfGold","type":"uint256"}],"name":"airdropToExistingHolder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"goldAmount","type":"uint256"}],"name":"burnGold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"name":"checkSkipCoolingOffAmt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"claimGold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"claimableView","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"name":"cooldownRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"name":"creditsLevelingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"creditsAmount","type":"uint256"}],"name":"equipMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tid","type":"uint256"}],"name":"levelUpMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintGold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"myClaimableView","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"myStakedMiner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"}],"name":"rebalanceGoldClaimableToUserWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_toRemove","type":"address"}],"name":"removeAuthorized","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"goldAmount","type":"uint256"}],"name":"skipCoolingOff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tids","type":"uint256[]"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakedMiner","outputs":[{"internalType":"uint24","name":"level","type":"uint24"},{"internalType":"uint32","name":"sinceTs","type":"uint32"},{"internalType":"uint32","name":"lastSkippedTs","type":"uint32"},{"internalType":"uint48","name":"creditsAmount","type":"uint48"},{"internalType":"uint32","name":"cooldownTs","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLevel","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedMiner","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tids","type":"uint256[]"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"uint256","name":"c","type":"uint256"},{"internalType":"uint256","name":"d","type":"uint256"},{"internalType":"uint256","name":"e","type":"uint256"}],"name":"updateSkipCooldownValues","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tids","type":"uint256[]"}],"name":"withdrawAllMinerAndClaim","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c060405260056080819052640911d3d31160da1b60a0908152620000289160079190620002ba565b506040805180820190915260048082526311d3d31160e21b60209092019182526200005691600891620002ba565b50670a688906bd8b0000600a556703782dace9d90000600b5568056bc75e2d63100000600c5568056bc75e2d63100000600d5562015180600e556019600f556002601055610e10601155348015620000ad57600080fd5b506040516200369138038062003691833981016040819052620000d09162000360565b60078054620000df9062000392565b80601f01602080910402602001604051908101604052809291908181526020018280546200010d9062000392565b80156200015e5780601f1062000132576101008083540402835291602001916200015e565b820191906000526020600020905b8154815290600101906020018083116200014057829003601f168201915b505050505060088054620001729062000392565b80601f0160208091040260200160405190810160405280929190818152602001828054620001a09062000392565b8015620001f15780601f10620001c557610100808354040283529160200191620001f1565b820191906000526020600020905b815481529060010190602001808311620001d357829003601f168201915b505084516200020b935060039250602086019150620002ba565b50805162000221906004906020840190620002ba565b5050506200023e620002386200026460201b60201c565b62000268565b600980546001600160a01b0319166001600160a01b0392909216919091179055620003cf565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b828054620002c89062000392565b90600052602060002090601f016020900481019282620002ec576000855562000337565b82601f106200030757805160ff191683800117855562000337565b8280016001018555821562000337579182015b82811115620003375782518255916020019190600101906200031a565b506200034592915062000349565b5090565b5b808211156200034557600081556001016200034a565b6000602082840312156200037357600080fd5b81516001600160a01b03811681146200038b57600080fd5b9392505050565b600181811c90821680620003a757607f821691505b60208210811415620003c957634e487b7160e01b600052602260045260246000fd5b50919050565b6132b280620003df6000396000f3fe608060405234801561001057600080fd5b50600436106102945760003560e01c806377c068f611610167578063b6671a9a116100ce578063dd62ed3e11610087578063dd62ed3e146105dc578063e449f34114610615578063edf52d1314610628578063f2fde38b1461063b578063f4d388e71461064e578063f577c1791461066157600080fd5b8063b6671a9a1461056e578063b918161114610581578063bab3384d146105a4578063c00b346e146105ad578063ce2cca74146105c0578063cf1c316a146105c957600080fd5b8063a457c2d711610120578063a457c2d714610510578063a59c8d9a14610523578063a783c27114610536578063a81b4b2c14610549578063a9059cbb14610552578063b00cbdec1461056557600080fd5b806377c068f6146104a15780638da5cb5b146104b45780638e2895e5146104c5578063902367aa146104ec57806395d89b41146104f5578063a2f34332146104fd57600080fd5b806323b872dd1161020b578063483a3476116101c4578063483a34761461040a578063485d7d941461041f5780634da8417c146104325780635ab30dee1461045d57806370a0823114610470578063715018a61461049957600080fd5b806323b872dd14610368578063313ce5671461037b578063395093511461038a5780633e1ce9dc1461039d57806340f964dd146103ef5780634791284b1461040257600080fd5b8063095ea7b31161025d578063095ea7b3146103055780630b2b60a1146103285780630fbf0a931461033b578063116be18e1461034e57806318160ddd146103575780631f6d15bd1461035f57600080fd5b8062f75f7c1461029957806303bb5f02146102bf578063060df8c4146102c857806306125cb9146102dd57806306fdde03146102f0575b600080fd5b6102ac6102a7366004612b8e565b61068b565b6040519081526020015b60405180910390f35b6102ac600e5481565b6102db6102d6366004612ba7565b6106ac565b005b6102db6102eb366004612bd3565b6107a6565b6102f8610a3b565b6040516102b69190612bf5565b610318610313366004612c5f565b610acd565b60405190151581526020016102b6565b6102db610336366004612c5f565b610ae3565b6102db610349366004612c8b565b610b44565b6102ac60105481565b6002546102ac565b6102ac600d5481565b610318610376366004612d00565b610b87565b604051601281526020016102b6565b610318610398366004612c5f565b610c31565b6103b06103ab366004612b8e565b610c6d565b6040805162ffffff909616865263ffffffff94851660208701529284169285019290925265ffffffffffff16606084015216608082015260a0016102b6565b6102ac6103fd366004612b8e565b610cbd565b6102ac610db9565b610412610fa4565b6040516102b69190612d41565b6102db61042d366004612d85565b6111a8565b600954610445906001600160a01b031681565b6040516001600160a01b0390911681526020016102b6565b6102db61046b366004612da9565b61121c565b6102ac61047e366004612d85565b6001600160a01b031660009081526020819052604090205490565b6102db61125d565b6102db6104af366004612bd3565b611293565b6005546001600160a01b0316610445565b6012546104d69064ffffffffff1681565b60405164ffffffffff90911681526020016102b6565b6102ac60115481565b6102f861149f565b6102ac61050b366004612b8e565b6114ae565b61031861051e366004612c5f565b6114d6565b6102db610531366004612b8e565b61156f565b6102db610544366004612bd3565b611858565b6102ac600a5481565b610318610560366004612c5f565b611a66565b6102ac600c5481565b6102db61057c366004612c8b565b611a73565b61031861058f366004612d85565b60066020526000908152604090205460ff1681565b6102ac600f5481565b6102ac6105bb366004612b8e565b611a87565b6102ac600b5481565b6102db6105d7366004612d85565b611a98565b6102ac6105ea366004612de4565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102db610623366004612c8b565b611a7d565b6102db610636366004612c5f565b611af9565b6102db610649366004612d85565b611b9d565b6102db61065c366004612c8b565b611c38565b6012546106789065010000000000900461ffff1681565b60405161ffff90911681526020016102b6565b600d5460009061069c606484612e49565b6106a69190612e5d565b92915050565b6005546001600160a01b031633146106df5760405162461bcd60e51b81526004016106d690612e7c565b60405180910390fd5b6009546001600160a01b0316835b83811161079f576040516331a9108f60e11b8152600481018290526000906001600160a01b03841690636352211e90602401602060405180830381865afa15801561073c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107609190612eb1565b90506001600160a01b0381161561078c5761078c8161078786670de0b6b3a7640000612e5d565b611c42565b508061079781612ece565b9150506106ed565b5050505050565b6000601383620186a181106107bd576107bd612ee9565b6040805160a081018252929091015462ffffff811680845263ffffffff6301000000830481166020860152600160381b830481169385019390935265ffffffffffff600160581b8304166060850152600160881b909104909116608083015290915061083b5760405162461bcd60e51b81526004016106d690612eff565b3360009081526020819052604090205442908381101561089d5760405162461bcd60e51b815260206004820152601960248201527f4e4f5420454e4f55474820676f6c6420494e2057414c4c45540000000000000060448201526064016106d6565b82516108ad9062ffffff1661068b565b8410156108fc5760405162461bcd60e51b815260206004820152601760248201527f4e4f5420454e4f55474820676f6c6420544f20534b495000000000000000000060448201526064016106d6565b8163ffffffff16600e54846040015163ffffffff1661091b9190612f23565b11156109695760405162461bcd60e51b815260206004820152601860248201527f424c4f434b4544204259203234485220434f4f4c444f574e000000000000000060448201526064016106d6565b6109733385611d21565b63ffffffff821660808401819052604084015282601386620186a1811061099c5761099c612ee9565b82519101805460208401516040850151606086015160809096015163ffffffff908116600160881b0263ffffffff60881b1965ffffffffffff909816600160581b0265ffffffffffff60581b19938316600160381b0293909316600160381b600160881b03199290941663010000000266ffffffffffffff1990951662ffffff9097169690961793909317929092161717929092161790555050505050565b606060038054610a4a90612f3b565b80601f0160208091040260200160405190810160405280929190818152602001828054610a7690612f3b565b8015610ac35780601f10610a9857610100808354040283529160200191610ac3565b820191906000526020600020905b815481529060010190602001808311610aa657829003601f168201915b5050505050905090565b6000610ada338484611dca565b50600192915050565b3360009081526006602052604090205460ff1680610b1a575033610b0f6005546001600160a01b031690565b6001600160a01b0316145b610b365760405162461bcd60e51b81526004016106d690612f70565b610b408282611d21565b5050565b60005b81811015610b8257610b70838383818110610b6457610b64612ee9565b90506020020135611eee565b80610b7a81612ece565b915050610b47565b505050565b6000610b9484848461228a565b6001600160a01b038416600090815260016020908152604080832033845290915290205482811015610c195760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084016106d6565b610c268533858403611dca565b506001949350505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610ada918590610c68908690612f23565b611dca565b601381620186a18110610c7f57600080fd5b015462ffffff8116915063ffffffff63010000008204811691600160381b810482169165ffffffffffff600160581b83041691600160881b90041685565b600080601383620186a18110610cd557610cd5612ee9565b6040805160a081018252929091015462ffffff811680845263ffffffff6301000000830481166020860152600160381b830481169385019390935265ffffffffffff600160581b8304166060850152600160881b909104909116608083015290915015610daa576000600a5460648360000151610d529190612f98565b62ffffff16600b54610d649190612e5d565b610d6e9190612f23565b90506000826020015163ffffffff1642610d889190612fba565b9050610d976201518083612e49565b610da19082612e5d565b95945050505050565b50600092915050565b50919050565b6009546040516370a0823160e01b81523360048201526000916001600160a01b031690829082906370a0823190602401602060405180830381865afa158015610e06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2a9190612fd1565b905060008111610e675760405162461bcd60e51b815260206004820152600860248201526727279026a4a722a960c11b60448201526064016106d6565b6000805b82811015610f9c57604051632f745c5960e01b8152336004820152602481018290526000906001600160a01b03861690632f745c5990604401602060405180830381865afa158015610ec1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee59190612fd1565b90506000601382620186a18110610efe57610efe612ee9565b6040805160a081018252929091015462ffffff811680845263ffffffff6301000000830481166020860152600160381b830481169385019390935265ffffffffffff600160581b8304166060850152600160881b909104909116608083015290915015610f87576000610f7083610cbd565b90508015610f8557610f828186612f23565b94505b505b50508080610f9490612ece565b915050610e6b565b509392505050565b6009546040516370a0823160e01b81523360048201526060916001600160a01b03169060009082906370a0823190602401602060405180830381865afa158015610ff2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110169190612fd1565b905060008167ffffffffffffffff81111561103357611033612fea565b60405190808252806020026020018201604052801561105c578160200160208202803683370190505b5090506000805b8381101561119e57604051632f745c5960e01b8152336004820152602481018290526000906001600160a01b03871690632f745c5990604401602060405180830381865afa1580156110b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dd9190612fd1565b90506000601382620186a181106110f6576110f6612ee9565b6040805160a081018252929091015462ffffff811680845263ffffffff6301000000830481166020860152600160381b830481169385019390935265ffffffffffff600160581b8304166060850152600160881b909104909116608083015290915015611189578185858151811061117057611170612ee9565b60209081029190910101528361118581612ece565b9450505b5050808061119690612ece565b915050611063565b5090949350505050565b6005546001600160a01b031633146111d25760405162461bcd60e51b81526004016106d690612e7c565b6001600160a01b0381166111e557600080fd5b6001600160a01b0381163314156111fb57600080fd5b6001600160a01b03166000908152600660205260409020805460ff19169055565b6005546001600160a01b031633146112465760405162461bcd60e51b81526004016106d690612e7c565b600c94909455600d92909255600e55600a55600b55565b6005546001600160a01b031633146112875760405162461bcd60e51b81526004016106d690612e7c565b6112916000612458565b565b3360009081526006602052604090205460ff16806112ca5750336112bf6005546001600160a01b031690565b6001600160a01b0316145b6112e65760405162461bcd60e51b81526004016106d690612f70565b6000601383620186a181106112fd576112fd612ee9565b6040805160a081018252929091015462ffffff811680845263ffffffff6301000000830481166020860152600160381b830481169385019390935265ffffffffffff600160581b8304166060850152600160881b909104909116608083015290915061137b5760405162461bcd60e51b81526004016106d690612eff565b600082116113be5760405162461bcd60e51b815260206004820152601060248201526f04e4f5448494e4720544f2045515549560841b60448201526064016106d6565b60608101516113d5670de0b6b3a764000084612e49565b6113df9190613000565b65ffffffffffff16606082015280601384620186a1811061140257611402612ee9565b82519101805460208401516040850151606086015160809096015163ffffffff908116600160881b0263ffffffff60881b1965ffffffffffff909816600160581b0265ffffffffffff60581b19938316600160381b0293909316600160381b600160881b03199290941663010000000266ffffffffffffff1990951662ffffff909716969096179390931792909216171792909216179055505050565b606060048054610a4a90612f3b565b6010546000906114bf606484612e49565b6114c9919061310e565b600f546106a69190612e5d565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156115585760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016106d6565b6115653385858403611dca565b5060019392505050565b6000601382620186a1811061158657611586612ee9565b6040805160a081018252929091015462ffffff811680845263ffffffff6301000000830481166020860152600160381b830481169385019390935265ffffffffffff600160581b8304166060850152600160881b90910490911660808301529091506116045760405162461bcd60e51b81526004016106d690612eff565b60095481516001600160a01b03909116906116239062ffffff166114ae565b826060015165ffffffffffff16101561166f5760405162461bcd60e51b815260206004820152600e60248201526d1353d491481193d3d1081491545160921b60448201526064016106d6565b816080015163ffffffff164210156116bc5760405162461bcd60e51b815260206004820152601060248201526f10d3d3d31113d5d3881393d50813515560821b60448201526064016106d6565b81516116c990606461311a565b62ffffff16808352600060608401526116e190611a87565b6116eb9042612f23565b63ffffffff16608083015281601384620186a1811061170c5761170c612ee9565b82519101805460208401516040850151606086015160809096015163ffffffff908116600160881b0263ffffffff60881b1965ffffffffffff909816600160581b0265ffffffffffff60581b19938316600160381b0293909316600160381b600160881b03199290941663010000000266ffffffffffffff1990951662ffffff90971696909617939093179290921617179290921617905560128054606491906000906117c190849064ffffffffff16613138565b92506101000a81548164ffffffffff021916908364ffffffffff160217905550806001600160a01b03166370a93b368484600001516040518363ffffffff1660e01b815260040161182192919091825262ffffff16602082015260400190565b600060405180830381600087803b15801561183b57600080fd5b505af115801561184f573d6000803e3d6000fd5b50505050505050565b6005546001600160a01b031633146118825760405162461bcd60e51b81526004016106d690612e7c565b6009546001600160a01b0316825b828111611a60576040516331a9108f60e11b8152600481018290526000906001600160a01b03841690636352211e90602401602060405180830381865afa1580156118df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119039190612eb1565b90506000601383620186a1811061191c5761191c612ee9565b6040805160a081018252929091015462ffffff811680845263ffffffff6301000000830481166020860152600160381b830481169385019390935265ffffffffffff600160581b8304166060850152600160881b909104909116608083015290915015611a4b576119908261078785610cbd565b63ffffffff4216602082015280601384620186a181106119b2576119b2612ee9565b82519101805460208401516040850151606086015160809096015163ffffffff908116600160881b0263ffffffff60881b1965ffffffffffff909816600160581b0265ffffffffffff60581b19938316600160381b0293909316600160381b600160881b03199290941663010000000266ffffffffffffff1990951662ffffff9097169690961793909317929092161717929092161790555b50508080611a5890612ece565b915050611890565b50505050565b6000610ada33848461228a565b611a7d82826124aa565b610b408282612775565b60115460009061069c606484612e49565b6005546001600160a01b03163314611ac25760405162461bcd60e51b81526004016106d690612e7c565b6001600160a01b038116611ad557600080fd5b6001600160a01b03166000908152600660205260409020805460ff19166001179055565b3360009081526006602052604090205460ff1680611b30575033611b256005546001600160a01b031690565b6001600160a01b0316145b611b4c5760405162461bcd60e51b81526004016106d690612f70565b611b568282611c42565b604080516001600160a01b0384168152602081018390527f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe91015b60405180910390a15050565b6005546001600160a01b03163314611bc75760405162461bcd60e51b81526004016106d690612e7c565b6001600160a01b038116611c2c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106d6565b611c3581612458565b50565b610b4082826124aa565b6001600160a01b038216611c985760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106d6565b8060026000828254611caa9190612f23565b90915550506001600160a01b03821660009081526020819052604081208054839290611cd7908490612f23565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b80611d41836001600160a01b031660009081526020819052604090205490565b1015611d815760405162461bcd60e51b815260206004820152600f60248201526e1393d508115393d551d20811d3d311608a1b60448201526064016106d6565b611d8b82826127b3565b604080516001600160a01b0384168152602081018390527f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79101611b91565b6001600160a01b038316611e2c5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016106d6565b6001600160a01b038216611e8d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016106d6565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6009546040516331a9108f60e11b8152600481018390526001600160a01b039091169033908290636352211e90602401602060405180830381865afa158015611f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5f9190612eb1565b6001600160a01b031614611f855760405162461bcd60e51b81526004016106d690613158565b60405163ae58201360e01b8152600481018390526000906001600160a01b0383169063ae5820139060240161010060405180830381865afa158015611fce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ff2919061317b565b9750505050505050506000601384620186a1811061201257612012612ee9565b6040805160a081018252929091015462ffffff8116835263ffffffff6301000000820481166020850152600160381b820481169284019290925265ffffffffffff600160581b8204166060840152600160881b9004166080820152905042601385620186a1811061208557612085612ee9565b015462ffffff1661079f576040518060a001604052808462ffffff1681526020018263ffffffff1681526020016000846040015163ffffffff16116120dc57600e546120d79063ffffffff8516612fba565b6120e2565b83604001515b63ffffffff168152600060208201526040016120fd85611a87565b61210790846131ff565b63ffffffff169052601386620186a1811061212457612124612ee9565b82519101805460208401516040850151606086015160809096015163ffffffff908116600160881b0263ffffffff60881b1965ffffffffffff909816600160581b0265ffffffffffff60581b19938316600160381b0293909316600160381b600160881b03199290941663010000000266ffffffffffffff1990951662ffffff90971696909617939093179290921617179290921617905560128054600191906005906121e090849061ffff650100000000009091041661321e565b92506101000a81548161ffff021916908361ffff1602179055508262ffffff16601260008282829054906101000a900464ffffffffff166122219190613138565b92506101000a81548164ffffffffff021916908364ffffffffff1602179055507f925435fa7e37e5d9555bb18ce0d62bb9627d0846942e58e5291e9a2dded462ed854260405161227b929190918252602082015260400190565b60405180910390a15050505050565b6001600160a01b0383166122ee5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016106d6565b6001600160a01b0382166123505760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016106d6565b6001600160a01b038316600090815260208190526040902054818110156123c85760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016106d6565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906123ff908490612f23565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161244b91815260200190565b60405180910390a3611a60565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6009546001600160a01b03166000805b8381101561272557336001600160a01b038416636352211e8787858181106124e4576124e4612ee9565b905060200201356040518263ffffffff1660e01b815260040161250991815260200190565b602060405180830381865afa158015612526573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254a9190612eb1565b6001600160a01b0316146125705760405162461bcd60e51b81526004016106d690613158565b6000601386868481811061258657612586612ee9565b90506020020135620186a1811061259f5761259f612ee9565b6040805160a081018252929091015462ffffff811680845263ffffffff6301000000830481166020860152600160381b830481169385019390935265ffffffffffff600160581b8304166060850152600160881b90910490911660808301529091501561271257600061262987878581811061261d5761261d612ee9565b90506020020135610cbd565b905080156127105761263b8185612f23565b63ffffffff42166020840152935081601388888681811061265e5761265e612ee9565b90506020020135620186a1811061267757612677612ee9565b82519101805460208401516040850151606086015160809096015163ffffffff908116600160881b0263ffffffff60881b1965ffffffffffff909816600160581b0265ffffffffffff60581b19938316600160381b0293909316600160381b600160881b03199290941663010000000266ffffffffffffff1990951662ffffff9097169690961793909317929092161717929092161790555b505b508061271d81612ece565b9150506124ba565b508015611a60576127363382611c42565b60408051338152602081018390527f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe910160405180910390a150505050565b60005b81811015610b82576127a183838381811061279557612795612ee9565b90506020020135612901565b806127ab81612ece565b915050612778565b6001600160a01b0382166128135760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016106d6565b6001600160a01b038216600090815260208190526040902054818110156128875760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016106d6565b6001600160a01b03831660009081526020819052604081208383039055600280548492906128b6908490612fba565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6009546040516331a9108f60e11b8152600481018390526001600160a01b039091169033908290636352211e90602401602060405180830381865afa15801561294e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129729190612eb1565b6001600160a01b0316146129985760405162461bcd60e51b81526004016106d690613158565b6000601383620186a181106129af576129af612ee9565b6040805160a081018252929091015462ffffff811680845263ffffffff6301000000830481166020860152600160381b830481169385019390935265ffffffffffff600160581b8304166060850152600160881b909104909116608083015290915015610b825780516012805462ffffff90921691600090612a3990849064ffffffffff1661323b565b92506101000a81548164ffffffffff021916908364ffffffffff1602179055506001601260058282829054906101000a900461ffff16612a799190613261565b825461ffff9182166101009390930a9283029190920219909116179055506000815280601384620186a18110612ab157612ab1612ee9565b825191018054602080850151604080870151606088015160809098015162ffffff90971666ffffffffffffff1990951694909417630100000063ffffffff9384160217600160381b600160881b031916600160381b9483169490940265ffffffffffff60581b191693909317600160581b65ffffffffffff909716969096029590951763ffffffff60881b1916600160881b9590941694909402929092179055805185815242928101929092527f69f6d6e6926b6914c628cca5ab19879a4099facaba2b44626e07d8e38ebd189b910160405180910390a1505050565b600060208284031215612ba057600080fd5b5035919050565b600080600060608486031215612bbc57600080fd5b505081359360208301359350604090920135919050565b60008060408385031215612be657600080fd5b50508035926020909101359150565b600060208083528351808285015260005b81811015612c2257858101830151858201604001528201612c06565b81811115612c34576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b0381168114611c3557600080fd5b60008060408385031215612c7257600080fd5b8235612c7d81612c4a565b946020939093013593505050565b60008060208385031215612c9e57600080fd5b823567ffffffffffffffff80821115612cb657600080fd5b818501915085601f830112612cca57600080fd5b813581811115612cd957600080fd5b8660208260051b8501011115612cee57600080fd5b60209290920196919550909350505050565b600080600060608486031215612d1557600080fd5b8335612d2081612c4a565b92506020840135612d3081612c4a565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b81811015612d7957835183529284019291840191600101612d5d565b50909695505050505050565b600060208284031215612d9757600080fd5b8135612da281612c4a565b9392505050565b600080600080600060a08688031215612dc157600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215612df757600080fd5b8235612e0281612c4a565b91506020830135612e1281612c4a565b809150509250929050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082612e5857612e58612e1d565b500490565b6000816000190483118215151615612e7757612e77612e33565b500290565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215612ec357600080fd5b8151612da281612c4a565b6000600019821415612ee257612ee2612e33565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6020808252600a90820152691393d50814d51052d15160b21b604082015260600190565b60008219821115612f3657612f36612e33565b500190565b600181811c90821680612f4f57607f821691505b60208210811415610db357634e487b7160e01b600052602260045260246000fd5b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b600062ffffff80841680612fae57612fae612e1d565b92169190910492915050565b600082821015612fcc57612fcc612e33565b500390565b600060208284031215612fe357600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600065ffffffffffff80831681851680830382111561302157613021612e33565b01949350505050565b600181815b8085111561306557816000190482111561304b5761304b612e33565b8085161561305857918102915b93841c939080029061302f565b509250929050565b60008261307c575060016106a6565b81613089575060006106a6565b816001811461309f57600281146130a9576130c5565b60019150506106a6565b60ff8411156130ba576130ba612e33565b50506001821b6106a6565b5060208310610133831016604e8410600b84101617156130e8575081810a6106a6565b6130f2838361302a565b806000190482111561310657613106612e33565b029392505050565b6000612da2838361306d565b600062ffffff80831681851680830382111561302157613021612e33565b600064ffffffffff80831681851680830382111561302157613021612e33565b6020808252600990820152682727aa1027aba722a960b91b604082015260600190565b600080600080600080600080610100898b03121561319857600080fd5b8851975060208901516131aa81612c4a565b60408a01519097506131bb81612c4a565b80965050606089015194506080890151935060a0890151925060c089015180151581146131e757600080fd5b8092505060e089015190509295985092959890939650565b600063ffffffff80831681851680830382111561302157613021612e33565b600061ffff80831681851680830382111561302157613021612e33565b600064ffffffffff8381169083168181101561325957613259612e33565b039392505050565b600061ffff8381169083168181101561325957613259612e3356fea2646970667358221220496efac85ea5c0fbde61ff553db71eabe4d06fc351b05f3a09cf24be9d7ff63a64736f6c634300080b0033000000000000000000000000be1e9103161a75ec7fa08d5ee1f97cd0784c26df

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000be1e9103161a75ec7fa08d5ee1f97cd0784c26df

-----Decoded View---------------
Arg [0] : _minerContract (address): 0xbe1e9103161a75ec7fa08d5ee1f97cd0784c26df

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000be1e9103161a75ec7fa08d5ee1f97cd0784c26df


Deployed ByteCode Sourcemap

148823:14994:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;160831:217;;;;;;:::i;:::-;;:::i;:::-;;;345:25:1;;;333:2;318:18;160831:217:0;;;;;;;;149663:42;;;;;;162535:476;;;;;;:::i;:::-;;:::i;:::-;;159551:1204;;;;;;:::i;:::-;;:::i;118031:100::-;;;:::i;:::-;;;;;;;:::i;120198:169::-;;;;;;:::i;:::-;;:::i;:::-;;;2178:14:1;;2171:22;2153:41;;2141:2;2126:18;120198:169:0;2013:187:1;159321:126:0;;;;;;:::i;:::-;;:::i;153056:151::-;;;;;;:::i;:::-;;:::i;149782:32::-;;;;;;119151:108;119239:12;;119151:108;;149505:59;;;;;;120849:492;;;;;;:::i;:::-;;:::i;118993:93::-;;;119076:2;3428:36:1;;3416:2;3401:18;118993:93:0;3286:184:1;121750:215:0;;;;;;:::i;:::-;;:::i;150631:41::-;;;;;;:::i;:::-;;:::i;:::-;;;;3754:8:1;3742:21;;;3724:40;;3783:10;3829:15;;;3824:2;3809:18;;3802:43;3881:15;;;3861:18;;;3854:43;;;;3945:14;3933:27;3928:2;3913:18;;3906:55;3998:15;3992:3;3977:19;;3970:44;3711:3;3696:19;150631:41:0;3475:545:1;153303:453:0;;;;;;:::i;:::-;;:::i;154486:745::-;;;:::i;153764:617::-;;;:::i;:::-;;;;;;;:::i;112064:196::-;;;;;;:::i;:::-;;:::i;148989:29::-;;;;;-1:-1:-1;;;;;148989:29:0;;;;;;-1:-1:-1;;;;;5078:32:1;;;5060:51;;5048:2;5033:18;148989:29:0;4914:203:1;161820:335:0;;;;;;:::i;:::-;;:::i;119322:127::-;;;;;;:::i;:::-;-1:-1:-1;;;;;119423:18:0;119396:7;119423:18;;;;;;;;;;;;119322:127;110807:103;;;:::i;161106:459::-;;;;;;:::i;:::-;;:::i;110156:87::-;110229:6;;-1:-1:-1;;;;;110229:6:0;110156:87;;150561:24;;;;;;;;;;;;5755:12:1;5743:25;;;5725:44;;5713:2;5698:18;150561:24:0;5581:194:1;149821:35:0;;;;;;118250:104;;;:::i;151128:241::-;;;;;;:::i;:::-;;:::i;122468:413::-;;;;;;:::i;:::-;;:::i;157875:988::-;;;;;;:::i;:::-;;:::i;163174:640::-;;;;;;:::i;:::-;;:::i;149088:52::-;;;;;;119662:175;;;;;;:::i;:::-;;:::i;149361:52::-;;;;;;157663:136;;;;;;:::i;:::-;;:::i;111725:42::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;149742:33;;;;;;151455:168;;;;;;:::i;:::-;;:::i;149242:58::-;;;;;;111916:140;;;;;;:::i;:::-;;:::i;119900:151::-;;;;;;:::i;:::-;-1:-1:-1;;;;;120016:18:0;;;119989:7;120016:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;119900:151;157492:92;;;;;;:::i;:::-;;:::i;162280:152::-;;;;;;:::i;:::-;;:::i;111065:201::-;;;;;;:::i;:::-;;:::i;156418:96::-;;;;;;:::i;:::-;;:::i;150592:30::-;;;;;;;;;;;;;;;6347:6:1;6335:19;;;6317:38;;6305:2;6290:18;150592:30:0;6173:188:1;160831:217:0;161019:20;;160899:7;;161004:11;161012:3;161004:5;:11;:::i;:::-;161003:36;;;;:::i;:::-;160995:45;160831:217;-1:-1:-1;;160831:217:0:o;162535:476::-;110229:6;;-1:-1:-1;;;;;110229:6:0;108960:10;110376:23;110368:68;;;;-1:-1:-1;;;110368:68:0;;;;;;;:::i;:::-;;;;;;;;;162751:14:::1;::::0;-1:-1:-1;;;;;162751:14:0::1;162794:4:::0;162777:227:::1;162805:2;162800:1;:7;162777:227;;162852:19;::::0;-1:-1:-1;;;162852:19:0;;::::1;::::0;::::1;345:25:1::0;;;162829:20:0::1;::::0;-1:-1:-1;;;;;162852:16:0;::::1;::::0;::::1;::::0;318:18:1;;162852:19:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;162829:42:::0;-1:-1:-1;;;;;;162890:26:0;::::1;::::0;162886:107:::1;;162937:40;162943:12:::0;162957:19:::1;:12:::0;162972:4:::1;162957:19;:::i;:::-;162937:5;:40::i;:::-;-1:-1:-1::0;162809:3:0;::::1;::::0;::::1;:::i;:::-;;;;162777:227;;;;162669:342;162535:476:::0;;;:::o;159551:1204::-;159632:27;159662:11;159674:7;159662:20;;;;;;;:::i;:::-;159632:50;;;;;;;;159662:20;;;;159632:50;;;;;;;;;;;;;;;;;-1:-1:-1;;;159632:50:0;;;;;;;;;;;;-1:-1:-1;;;159632:50:0;;;;;;;-1:-1:-1;;;159632:50:0;;;;;;;;;;;;-1:-1:-1;159693:39:0;;;;-1:-1:-1;;;159693:39:0;;;;;;;:::i;:::-;160066:10;159745:9;119423:18;;;;;;;;;;;159764:15;;160096:27;;;;160088:65;;;;-1:-1:-1;;;160088:65:0;;8358:2:1;160088:65:0;;;8340:21:1;8397:2;8377:18;;;8370:30;8436:27;8416:18;;;8409:55;8481:18;;160088:65:0;8156:349:1;160088:65:0;160280:11;;160257:35;;;;:22;:35::i;:::-;160243:10;:49;;160235:85;;;;-1:-1:-1;;;160235:85:0;;8712:2:1;160235:85:0;;;8694:21:1;8751:2;8731:18;;;8724:30;8790:25;8770:18;;;8763:53;8833:18;;160235:85:0;8510:347:1;160235:85:0;160451:2;160404:49;;160427:19;;160405:5;:19;;;:41;;;;;;:::i;:::-;160404:49;;160396:86;;;;-1:-1:-1;;;160396:86:0;;9197:2:1;160396:86:0;;;9179:21:1;9236:2;9216:18;;;9209:30;9275:26;9255:18;;;9248:54;9319:18;;160396:86:0;8995:348:1;160396:86:0;160517:33;160527:10;160539;160517:9;:33::i;:::-;160592:21;;;:16;;;:21;;;160684:19;;;:24;160592:5;160719:11;160731:7;160719:20;;;;;;;:::i;:::-;:28;;:20;;:28;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;160719:28:0;-1:-1:-1;;;;160719:28:0;;;;-1:-1:-1;;;160719:28:0;-1:-1:-1;;;;160719:28:0;;;-1:-1:-1;;;160719:28:0;;;;;-1:-1:-1;;;;;;;;160719:28:0;;;;;;-1:-1:-1;;160719:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;159551:1204:0:o;118031:100::-;118085:13;118118:5;118111:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;118031:100;:::o;120198:169::-;120281:4;120298:39;108960:10;120321:7;120330:6;120298:8;:39::i;:::-;-1:-1:-1;120355:4:0;120198:169;;;;:::o;159321:126::-;111832:10;111821:22;;;;:10;:22;;;;;;;;;:48;;-1:-1:-1;111859:10:0;111848:7;110229:6;;-1:-1:-1;;;;;110229:6:0;;110156:87;111848:7;-1:-1:-1;;;;;111848:21:0;;111821:48;111813:75;;;;-1:-1:-1;;;111813:75:0;;;;;;;:::i;:::-;159410:29:::1;159420:6;159428:10;159410:9;:29::i;:::-;159321:126:::0;;:::o;153056:151::-;153121:9;153116:84;153136:15;;;153116:84;;;153173:15;153180:4;;153185:1;153180:7;;;;;;;:::i;:::-;;;;;;;153173:6;:15::i;:::-;153153:3;;;;:::i;:::-;;;;153116:84;;;;153056:151;;:::o;120849:492::-;120989:4;121006:36;121016:6;121024:9;121035:6;121006:9;:36::i;:::-;-1:-1:-1;;;;;121082:19:0;;121055:24;121082:19;;;:11;:19;;;;;;;;108960:10;121082:33;;;;;;;;121134:26;;;;121126:79;;;;-1:-1:-1;;;121126:79:0;;10278:2:1;121126:79:0;;;10260:21:1;10317:2;10297:18;;;10290:30;10356:34;10336:18;;;10329:62;-1:-1:-1;;;10407:18:1;;;10400:38;10455:19;;121126:79:0;10076:404:1;121126:79:0;121241:57;121250:6;108960:10;121291:6;121272:16;:25;121241:8;:57::i;:::-;-1:-1:-1;121329:4:0;;120849:492;-1:-1:-1;;;;120849:492:0:o;121750:215::-;108960:10;121838:4;121887:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;121887:34:0;;;;;;;;;;121838:4;;121855:80;;121878:7;;121887:47;;121924:10;;121887:47;:::i;:::-;121855:8;:80::i;150631:41::-;;;;;;;;;;;;;;;;;;-1:-1:-1;150631:41:0;;;;;;;-1:-1:-1;;;150631:41:0;;;;;;-1:-1:-1;;;150631:41:0;;;;-1:-1:-1;;;150631:41:0;;;;:::o;153303:453::-;153364:7;153384:23;153410:11;153422:7;153410:20;;;;;;;:::i;:::-;153384:46;;;;;;;;153410:20;;;;153384:46;;;;;;;;;;;;;;;;;-1:-1:-1;;;153384:46:0;;;;;;;;;;;;-1:-1:-1;;;153384:46:0;;;;;;;-1:-1:-1;;;153384:46:0;;;;;;;;;;;;-1:-1:-1;153445:11:0;153441:308;;153473:18;153557:16;;153532:3;153522:1;:7;;;:13;;;;:::i;:::-;153496:40;;:22;;:40;;;;:::i;:::-;153495:78;;;;:::i;:::-;153473:101;;153589:20;153630:1;:9;;;153612:27;;:15;:27;;;;:::i;:::-;153589:50;-1:-1:-1;153677:18:0;153690:5;153677:10;:18;:::i;:::-;153661:35;;:12;:35;:::i;:::-;153654:42;153303:453;-1:-1:-1;;;;;153303:453:0:o;153441:308::-;-1:-1:-1;153736:1:0;;153303:453;-1:-1:-1;;153303:453:0:o;153441:308::-;153373:383;153303:453;;;:::o;154486:745::-;154576:14;;154616:23;;-1:-1:-1;;;154616:23:0;;154628:10;154616:23;;;5060:51:1;154534:7:0;;-1:-1:-1;;;;;154576:14:0;;154534:7;;154576:14;;154616:11;;5033:18:1;;154616:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154602:37;;154664:1;154658:3;:7;154650:28;;;;-1:-1:-1;;;154650:28:0;;11200:2:1;154650:28:0;;;11182:21:1;11239:1;11219:18;;;11212:29;-1:-1:-1;;;11257:18:1;;;11250:38;11305:18;;154650:28:0;10998:331:1;154650:28:0;154689:22;154731:9;154726:466;154750:3;154746:1;:7;154726:466;;;154793:36;;-1:-1:-1;;;154793:36:0;;154815:10;154793:36;;;11508:51:1;11575:18;;;11568:34;;;154775:15:0;;-1:-1:-1;;;;;154793:21:0;;;;;11481:18:1;;154793:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154775:54;;154844:27;154874:11;154886:7;154874:20;;;;;;;:::i;:::-;154844:50;;;;;;;;154874:20;;;;154844:50;;;;;;;;;;;;;;;;;-1:-1:-1;;;154844:50:0;;;;;;;;;;;;-1:-1:-1;;;154844:50:0;;;;;;;-1:-1:-1;;;154844:50:0;;;;;;;;;;;;-1:-1:-1;154964:15:0;154960:221;;155000:17;155020:22;155034:7;155020:13;:22::i;:::-;155000:42;-1:-1:-1;155065:13:0;;155061:105;;155120:26;155137:9;155120:14;:26;:::i;:::-;155103:43;;155061:105;154981:200;154960:221;154760:432;;154755:3;;;;;:::i;:::-;;;;154726:466;;;-1:-1:-1;155209:14:0;154486:745;-1:-1:-1;;;154486:745:0:o;153764:617::-;153861:14;;153908:23;;-1:-1:-1;;;153908:23:0;;153920:10;153908:23;;;5060:51:1;153810:16:0;;-1:-1:-1;;;;;153861:14:0;;153839:10;;153861:14;;153908:11;;5033:18:1;;153908:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;153887:44;;153942:25;153984:10;153970:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;153970:25:0;;153942:53;;154006:15;154041:9;154036:312;154060:10;154056:1;:14;154036:312;;;154110:36;;-1:-1:-1;;;154110:36:0;;154132:10;154110:36;;;11508:51:1;11575:18;;;11568:34;;;154092:15:0;;-1:-1:-1;;;;;154110:21:0;;;;;11481:18:1;;154110:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154092:54;;154161:27;154191:11;154203:7;154191:20;;;;;;;:::i;:::-;154161:50;;;;;;;;154191:20;;;;154161:50;;;;;;;;;;;;;;;;;-1:-1:-1;;;154161:50:0;;;;;;;;;;;;-1:-1:-1;;;154161:50:0;;;;;;;-1:-1:-1;;;154161:50:0;;;;;;;;;;;;-1:-1:-1;154230:15:0;154226:111;;154286:7;154266:8;154275:7;154266:17;;;;;;;;:::i;:::-;;;;;;;;;;:27;154312:9;;;;:::i;:::-;;;;154226:111;154077:271;;154072:3;;;;;:::i;:::-;;;;154036:312;;;-1:-1:-1;154365:8:0;;153764:617;-1:-1:-1;;;;153764:617:0:o;112064:196::-;110229:6;;-1:-1:-1;;;;;110229:6:0;108960:10;110376:23;110368:68;;;;-1:-1:-1;;;110368:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;112145:23:0;::::1;112137:32;;;::::0;::::1;;-1:-1:-1::0;;;;;112188:23:0;::::1;112201:10;112188:23;;112180:32;;;::::0;::::1;;-1:-1:-1::0;;;;;112223:21:0::1;112247:5;112223:21:::0;;;:10:::1;:21;::::0;;;;:29;;-1:-1:-1;;112223:29:0::1;::::0;;112064:196::o;161820:335::-;110229:6;;-1:-1:-1;;;;;110229:6:0;108960:10;110376:23;110368:68;;;;-1:-1:-1;;;110368:68:0;;;;;;;:::i;:::-;161993:13:::1;:17:::0;;;;162021:20:::1;:24:::0;;;;162056:19:::1;:23:::0;162090:16:::1;:20:::0;162121:22:::1;:26:::0;161820:335::o;110807:103::-;110229:6;;-1:-1:-1;;;;;110229:6:0;108960:10;110376:23;110368:68;;;;-1:-1:-1;;;110368:68:0;;;;;;;:::i;:::-;110872:30:::1;110899:1;110872:18;:30::i;:::-;110807:103::o:0;161106:459::-;111832:10;111821:22;;;;:10;:22;;;;;;;;;:48;;-1:-1:-1;111859:10:0;111848:7;110229:6;;-1:-1:-1;;;;;110229:6:0;;110156:87;111848:7;-1:-1:-1;;;;;111848:21:0;;111821:48;111813:75;;;;-1:-1:-1;;;111813:75:0;;;;;;;:::i;:::-;161224:27:::1;161254:11;161266:7;161254:20;;;;;;;:::i;:::-;161224:50;::::0;;::::1;::::0;::::1;::::0;;161254:20;;;::::1;161224:50:::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;;::::0;::::1;::::0;-1:-1:-1;;;161224:50:0;::::1;::::0;::::1;::::0;;;;;;;::::1;-1:-1:-1::0;;;161224:50:0;::::1;;::::0;;;;-1:-1:-1;;;161224:50:0;;::::1;::::0;;::::1;::::0;;;;;;-1:-1:-1;161285:38:0::1;;;;-1:-1:-1::0;;;161285:38:0::1;;;;;;;:::i;:::-;161358:1;161342:13;:17;161334:46;;;::::0;-1:-1:-1;;;161334:46:0;;11947:2:1;161334:46:0::1;::::0;::::1;11929:21:1::0;11986:2;11966:18;;;11959:30;-1:-1:-1;;;12005:18:1;;;11998:46;12061:18;;161334:46:0::1;11745:340:1::0;161334:46:0::1;161499:19;::::0;::::1;::::0;161475:20:::1;161491:4;161475:13:::0;:20:::1;:::i;:::-;161468:50;;;;:::i;:::-;161446:72;;:19;::::0;::::1;:72:::0;:5;161529:11:::1;161541:7:::0;161529:20:::1;::::0;::::1;;;;;:::i;:::-;:28:::0;;:20;::::1;:28:::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;-1:-1:-1::0;;;161529:28:0::1;-1:-1:-1::0;;;;161529:28:0::1;::::0;;::::1;-1:-1:-1::0;;;161529:28:0::1;-1:-1:-1::0;;;;161529:28:0;;::::1;-1:-1:-1::0;;;161529:28:0::1;::::0;;;;-1:-1:-1;;;;;;;;161529:28:0;;;::::1;::::0;::::1;-1:-1:-1::0;;161529:28:0;;;::::1;::::0;;::::1;::::0;;;;;;;::::1;::::0;;;;;::::1;::::0;;;::::1;;::::0;;-1:-1:-1;;;161106:459:0:o;118250:104::-;118306:13;118339:7;118332:14;;;;;:::i;151128:241::-;151347:13;;151193:7;;151333:11;151341:3;151333:5;:11;:::i;:::-;151332:28;;;;:::i;:::-;151315:13;;:46;;;;:::i;122468:413::-;108960:10;122561:4;122605:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;122605:34:0;;;;;;;;;;122658:35;;;;122650:85;;;;-1:-1:-1;;;122650:85:0;;13903:2:1;122650:85:0;;;13885:21:1;13942:2;13922:18;;;13915:30;13981:34;13961:18;;;13954:62;-1:-1:-1;;;14032:18:1;;;14025:35;14077:19;;122650:85:0;13701:401:1;122650:85:0;122771:67;108960:10;122794:7;122822:15;122803:16;:34;122771:8;:67::i;:::-;-1:-1:-1;122869:4:0;;122468:413;-1:-1:-1;;;122468:413:0:o;157875:988::-;157930:23;157956:11;157968:3;157956:16;;;;;;;:::i;:::-;157930:42;;;;;;;;157956:16;;;;157930:42;;;;;;;;;;;;;;;;;-1:-1:-1;;;157930:42:0;;;;;;;;;;;;-1:-1:-1;;;157930:42:0;;;;;;;-1:-1:-1;;;157930:42:0;;;;;;;;;;;;-1:-1:-1;157983:34:0;;;;-1:-1:-1;;;157983:34:0;;;;;;;:::i;:::-;158052:14;;158296:7;;-1:-1:-1;;;;;158052:14:0;;;;158276:28;;;;:19;:28::i;:::-;158257:1;:15;;;:47;;;;158249:74;;;;-1:-1:-1;;;158249:74:0;;14309:2:1;158249:74:0;;;14291:21:1;14348:2;14328:18;;;14321:30;-1:-1:-1;;;14367:18:1;;;14360:44;14421:18;;158249:74:0;14107:338:1;158249:74:0;158403:1;:12;;;158384:31;;:15;:31;;158376:60;;;;-1:-1:-1;;;158376:60:0;;14652:2:1;158376:60:0;;;14634:21:1;14691:2;14671:18;;;14664:30;-1:-1:-1;;;14710:18:1;;;14703:46;14766:18;;158376:60:0;14450:340:1;158376:60:0;158549:7;;:13;;158559:3;158549:13;:::i;:::-;158539:23;;;;;:7;158573:15;;;:19;158643:21;;:12;:21::i;:::-;158625:39;;:15;:39;:::i;:::-;158603:62;;:12;;;:62;:1;158676:11;158688:3;158676:16;;;;;;;:::i;:::-;:20;;:16;;:20;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;158676:20:0;-1:-1:-1;;;;158676:20:0;;;;-1:-1:-1;;;158676:20:0;-1:-1:-1;;;;158676:20:0;;;-1:-1:-1;;;158676:20:0;;;;;-1:-1:-1;;;;;;;;158676:20:0;;;;;;-1:-1:-1;;158676:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;158751:10;:25;;158772:3;;158751:10;158676:20;;158751:25;;158772:3;;158751:25;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;158831:1;-1:-1:-1;;;;;158831:10:0;;158842:3;158847:1;:7;;;158831:24;;;;;;;;;;;;;;;15434:25:1;;;15507:8;15495:21;15490:2;15475:18;;15468:49;15422:2;15407:18;;15261:262;158831:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;157919:944;;157875:988;:::o;163174:640::-;110229:6;;-1:-1:-1;;;;;110229:6:0;108960:10;110376:23;110368:68;;;;-1:-1:-1;;;110368:68:0;;;;;;;:::i;:::-;163326:14:::1;::::0;-1:-1:-1;;;;;163326:14:0::1;163369:4:::0;163352:455:::1;163380:2;163375:1;:7;163352:455;;163427:19;::::0;-1:-1:-1;;;163427:19:0;;::::1;::::0;::::1;345:25:1::0;;;163404:20:0::1;::::0;-1:-1:-1;;;;;163427:16:0;::::1;::::0;::::1;::::0;318:18:1;;163427:19:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;163404:42;;163461:27;163491:11;163503:1;163491:14;;;;;;;:::i;:::-;163461:44;::::0;;::::1;::::0;::::1;::::0;;163491:14;;;::::1;163461:44:::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;;::::0;::::1;::::0;-1:-1:-1;;;163461:44:0;::::1;::::0;::::1;::::0;;;;;;;::::1;-1:-1:-1::0;;;163461:44:0;::::1;;::::0;;;;-1:-1:-1;;;163461:44:0;;::::1;::::0;;::::1;::::0;;;;;;-1:-1:-1;163608:15:0;163604:192:::1;;163644:37;163650:12;163664:16;163678:1;163664:13;:16::i;163644:37::-;163700:39;163723:15;163700:39;:13;::::0;::::1;:39:::0;:5;163758:11:::1;163770:1:::0;163758:14:::1;::::0;::::1;;;;;:::i;:::-;:22:::0;;:14;::::1;:22:::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;-1:-1:-1::0;;;163758:22:0::1;-1:-1:-1::0;;;;163758:22:0::1;::::0;;::::1;-1:-1:-1::0;;;163758:22:0::1;-1:-1:-1::0;;;;163758:22:0;;::::1;-1:-1:-1::0;;;163758:22:0::1;::::0;;;;-1:-1:-1;;;;;;;;163758:22:0;;;::::1;::::0;::::1;-1:-1:-1::0;;163758:22:0;;;::::1;::::0;;::::1;::::0;;;;;;;::::1;::::0;;;;;::::1;::::0;;;::::1;;::::0;;163604:192:::1;163389:418;;163384:3;;;;;:::i;:::-;;;;163352:455;;;;163286:528;163174:640:::0;;:::o;119662:175::-;119748:4;119765:42;108960:10;119789:9;119800:6;119765:9;:42::i;157663:136::-;157742:16;157753:4;;157742:10;:16::i;:::-;157769:22;157786:4;;157769:16;:22::i;151455:168::-;151602:13;;151513:7;;151587:11;151595:3;151587:5;:11;:::i;111916:140::-;110229:6;;-1:-1:-1;;;;;110229:6:0;108960:10;110376:23;110368:68;;;;-1:-1:-1;;;110368:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;111991:20:0;::::1;111983:29;;;::::0;::::1;;-1:-1:-1::0;;;;;112023:18:0::1;;::::0;;;:10:::1;:18;::::0;;;;:25;;-1:-1:-1;;112023:25:0::1;112044:4;112023:25;::::0;;111916:140::o;162280:152::-;111832:10;111821:22;;;;:10;:22;;;;;;;;;:48;;-1:-1:-1;111859:10:0;111848:7;110229:6;;-1:-1:-1;;;;;110229:6:0;;110156:87;111848:7;-1:-1:-1;;;;;111848:21:0;;111821:48;111813:75;;;;-1:-1:-1;;;111813:75:0;;;;;;;:::i;:::-;162365:21:::1;162371:6;162379;162365:5;:21::i;:::-;162402:22;::::0;;-1:-1:-1;;;;;11526:32:1;;11508:51;;11590:2;11575:18;;11568:34;;;162402:22:0::1;::::0;11481:18:1;162402:22:0::1;;;;;;;;162280:152:::0;;:::o;111065:201::-;110229:6;;-1:-1:-1;;;;;110229:6:0;108960:10;110376:23;110368:68;;;;-1:-1:-1;;;110368:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;111154:22:0;::::1;111146:73;;;::::0;-1:-1:-1;;;111146:73:0;;15730:2:1;111146:73:0::1;::::0;::::1;15712:21:1::0;15769:2;15749:18;;;15742:30;15808:34;15788:18;;;15781:62;-1:-1:-1;;;15859:18:1;;;15852:36;15905:19;;111146:73:0::1;15528:402:1::0;111146:73:0::1;111230:28;111249:8;111230:18;:28::i;:::-;111065:201:::0;:::o;156418:96::-;156486:20;156497:8;;156486:10;:20::i;124391:399::-;-1:-1:-1;;;;;124475:21:0;;124467:65;;;;-1:-1:-1;;;124467:65:0;;16137:2:1;124467:65:0;;;16119:21:1;16176:2;16156:18;;;16149:30;16215:33;16195:18;;;16188:61;16266:18;;124467:65:0;15935:355:1;124467:65:0;124623:6;124607:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;124640:18:0;;:9;:18;;;;;;;;;;:28;;124662:6;;124640:9;:28;;124662:6;;124640:28;:::i;:::-;;;;-1:-1:-1;;124684:37:0;;345:25:1;;;-1:-1:-1;;;;;124684:37:0;;;124701:1;;124684:37;;333:2:1;318:18;124684:37:0;;;;;;;159321:126;;:::o;158955:275::-;159114:10;159093:17;159103:6;-1:-1:-1;;;;;119423:18:0;119396:7;119423:18;;;;;;;;;;;;119322:127;159093:17;:31;;159085:59;;;;-1:-1:-1;;;159085:59:0;;16497:2:1;159085:59:0;;;16479:21:1;16536:2;16516:18;;;16509:30;-1:-1:-1;;;16555:18:1;;;16548:45;16610:18;;159085:59:0;16295:339:1;159085:59:0;159155:25;159161:6;159169:10;159155:5;:25::i;:::-;159196:26;;;-1:-1:-1;;;;;11526:32:1;;11508:51;;11590:2;11575:18;;11568:34;;;159196:26:0;;11481:18:1;159196:26:0;11334:274:1;126152:380:0;-1:-1:-1;;;;;126288:19:0;;126280:68;;;;-1:-1:-1;;;126280:68:0;;16841:2:1;126280:68:0;;;16823:21:1;16880:2;16860:18;;;16853:30;16919:34;16899:18;;;16892:62;-1:-1:-1;;;16970:18:1;;;16963:34;17014:19;;126280:68:0;16639:400:1;126280:68:0;-1:-1:-1;;;;;126367:21:0;;126359:68;;;;-1:-1:-1;;;126359:68:0;;17246:2:1;126359:68:0;;;17228:21:1;17285:2;17265:18;;;17258:30;17324:34;17304:18;;;17297:62;-1:-1:-1;;;17375:18:1;;;17368:32;17417:19;;126359:68:0;17044:398:1;126359:68:0;-1:-1:-1;;;;;126440:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;126492:32;;345:25:1;;;126492:32:0;;318:18:1;126492:32:0;;;;;;;126152:380;;;:::o;151741:1213::-;151812:14;;151901;;-1:-1:-1;;;151901:14:0;;;;;345:25:1;;;-1:-1:-1;;;;;151812:14:0;;;;151919:10;;151812:14;;151901:9;;318:18:1;;151901:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;151901:28:0;;151893:50;;;;-1:-1:-1;;;151893:50:0;;;;;;;:::i;:::-;152021:16;;-1:-1:-1;;;152021:16:0;;;;;345:25:1;;;152004:13:0;;-1:-1:-1;;;;;152021:11:0;;;;;318:18:1;;152021:16:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;151989:48;;;;;;;;;152127:23;152153:11;152165:3;152153:16;;;;;;;:::i;:::-;152127:42;;;;;;;;152153:16;;;;152127:42;;;;;;;;;;;;;;;;-1:-1:-1;;;152127:42:0;;;;;;;;;;;;-1:-1:-1;;;152127:42:0;;;;;;;-1:-1:-1;;;152127:42:0;;;;;;;;-1:-1:-1;152199:15:0;152230:11;152242:3;152230:16;;;;;;;:::i;:::-;;:22;;;152226:721;;152332:262;;;;;;;;152372:5;152332:262;;;;;;152397:2;152332:262;;;;;;152436:1;152418;:15;;;:19;;;:73;;152471:19;;152466:24;;;;;;:::i;:::-;152418:73;;;152440:1;:15;;;152418:73;152332:262;;;;152517:1;152332:262;;;;;;152558:19;152571:5;152558:12;:19::i;:::-;152538:40;;152545:2;152538:40;:::i;:::-;152332:262;;;;152313:11;152325:3;152313:16;;;;;;;:::i;:::-;:281;;:16;;:281;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;152313:281:0;-1:-1:-1;;;;152313:281:0;;;;-1:-1:-1;;;152313:281:0;-1:-1:-1;;;;152313:281:0;;;-1:-1:-1;;;152313:281:0;;;;;-1:-1:-1;;;;;;;;152313:281:0;;;;;;-1:-1:-1;;152313:281:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;152792:16;:21;;152313:281;;152792:16;;;:21;;152313:281;;152792:21;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;152849:5;152828:27;;:10;;:27;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;152907:28;152914:3;152919:15;152907:28;;;;;;19282:25:1;;;19338:2;19323:18;;19316:34;19270:2;19255:18;;19108:248;152907:28:0;;;;;;;;151779:1175;;;;151741:1213;:::o;123371:733::-;-1:-1:-1;;;;;123511:20:0;;123503:70;;;;-1:-1:-1;;;123503:70:0;;19563:2:1;123503:70:0;;;19545:21:1;19602:2;19582:18;;;19575:30;19641:34;19621:18;;;19614:62;-1:-1:-1;;;19692:18:1;;;19685:35;19737:19;;123503:70:0;19361:401:1;123503:70:0;-1:-1:-1;;;;;123592:23:0;;123584:71;;;;-1:-1:-1;;;123584:71:0;;19969:2:1;123584:71:0;;;19951:21:1;20008:2;19988:18;;;19981:30;20047:34;20027:18;;;20020:62;-1:-1:-1;;;20098:18:1;;;20091:33;20141:19;;123584:71:0;19767:399:1;123584:71:0;-1:-1:-1;;;;;123752:17:0;;123728:21;123752:17;;;;;;;;;;;123788:23;;;;123780:74;;;;-1:-1:-1;;;123780:74:0;;20373:2:1;123780:74:0;;;20355:21:1;20412:2;20392:18;;;20385:30;20451:34;20431:18;;;20424:62;-1:-1:-1;;;20502:18:1;;;20495:36;20548:19;;123780:74:0;20171:402:1;123780:74:0;-1:-1:-1;;;;;123890:17:0;;;:9;:17;;;;;;;;;;;123910:22;;;123890:42;;123954:20;;;;;;;;:30;;123926:6;;123890:9;123954:30;;123926:6;;123954:30;:::i;:::-;;;;;;;;124019:9;-1:-1:-1;;;;;124002:35:0;124011:6;-1:-1:-1;;;;;124002:35:0;;124030:6;124002:35;;;;345:25:1;;333:2;318:18;;199:177;124002:35:0;;;;;;;;124050:46;153056:151;111426:191;111519:6;;;-1:-1:-1;;;;;111536:17:0;;;-1:-1:-1;;;;;;111536:17:0;;;;;;;111569:40;;111519:6;;;111536:17;111519:6;;111569:40;;111500:16;;111569:40;111489:128;111426:191;:::o;155303:1043::-;155394:14;;-1:-1:-1;;;;;155394:14:0;155372:10;;155461:718;155481:19;;;155461:718;;;155556:10;-1:-1:-1;;;;;155530:9:0;;;155540:8;;155549:1;155540:11;;;;;;;:::i;:::-;;;;;;;155530:22;;;;;;;;;;;;;345:25:1;;333:2;318:18;;199:177;155530:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;155530:36:0;;155522:58;;;;-1:-1:-1;;;155522:58:0;;;;;;;:::i;:::-;155595:27;155625:11;155637:8;;155646:1;155637:11;;;;;;;:::i;:::-;;;;;;;155625:24;;;;;;;:::i;:::-;155595:54;;;;;;;;155625:24;;;;155595:54;;;;;;;;;;;;;;;;;-1:-1:-1;;;155595:54:0;;;;;;;;;;;;-1:-1:-1;;;155595:54:0;;;;;;;-1:-1:-1;;;155595:54:0;;;;;;;;;;;;-1:-1:-1;155752:15:0;155748:420;;155788:21;155812:26;155826:8;;155835:1;155826:11;;;;;;;:::i;:::-;;;;;;;155812:13;:26::i;:::-;155788:50;-1:-1:-1;155861:17:0;;155857:296;;155924:34;155945:13;155924:18;:34;:::i;:::-;156039:39;156062:15;156039:39;:13;;;:39;155903:55;-1:-1:-1;156039:5:0;156101:11;156113:8;;156122:1;156113:11;;;;;;;:::i;:::-;;;;;;;156101:24;;;;;;;:::i;:::-;:32;;:24;;:32;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;156101:32:0;-1:-1:-1;;;;156101:32:0;;;;-1:-1:-1;;;156101:32:0;-1:-1:-1;;;;156101:32:0;;;-1:-1:-1;;;156101:32:0;;;;;-1:-1:-1;;;;;;;;156101:32:0;;;;;;-1:-1:-1;;156101:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;155857:296;155769:399;155748:420;-1:-1:-1;155502:3:0;;;;:::i;:::-;;;;155461:718;;;-1:-1:-1;156193:22:0;;156189:150;;156232:37;156238:10;156250:18;156232:5;:37::i;:::-;156289:38;;;156296:10;11508:51:1;;11590:2;11575:18;;11568:34;;;156289:38:0;;11481:18:1;156289:38:0;;;;;;;155361:985;;155303:1043;;:::o;157232:164::-;157308:9;157303:86;157323:15;;;157303:86;;;157360:17;157369:4;;157374:1;157369:7;;;;;;;:::i;:::-;;;;;;;157360:8;:17::i;:::-;157340:3;;;;:::i;:::-;;;;157303:86;;125123:591;-1:-1:-1;;;;;125207:21:0;;125199:67;;;;-1:-1:-1;;;125199:67:0;;20780:2:1;125199:67:0;;;20762:21:1;20819:2;20799:18;;;20792:30;20858:34;20838:18;;;20831:62;-1:-1:-1;;;20909:18:1;;;20902:31;20950:19;;125199:67:0;20578:397:1;125199:67:0;-1:-1:-1;;;;;125366:18:0;;125341:22;125366:18;;;;;;;;;;;125403:24;;;;125395:71;;;;-1:-1:-1;;;125395:71:0;;21182:2:1;125395:71:0;;;21164:21:1;21221:2;21201:18;;;21194:30;21260:34;21240:18;;;21233:62;-1:-1:-1;;;21311:18:1;;;21304:32;21353:19;;125395:71:0;20980:398:1;125395:71:0;-1:-1:-1;;;;;125502:18:0;;:9;:18;;;;;;;;;;125523:23;;;125502:44;;125568:12;:22;;125540:6;;125502:9;125568:22;;125540:6;;125568:22;:::i;:::-;;;;-1:-1:-1;;125608:37:0;;345:25:1;;;125634:1:0;;-1:-1:-1;;;;;125608:37:0;;;;;333:2:1;318:18;125608:37:0;;;;;;;153116:84;153056:151;;:::o;156603:621::-;156680:14;;156769:18;;-1:-1:-1;;;156769:18:0;;;;;345:25:1;;;-1:-1:-1;;;;;156680:14:0;;;;156791:10;;156680:14;;156769:9;;318:18:1;;156769::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;156769:32:0;;156761:54;;;;-1:-1:-1;;;156761:54:0;;;;;;;:::i;:::-;156856:23;156882:11;156894:7;156882:20;;;;;;;:::i;:::-;156856:46;;;;;;;;156882:20;;;;156856:46;;;;;;;;;;;;;;;;;-1:-1:-1;;;156856:46:0;;;;;;;;;;;;-1:-1:-1;;;156856:46:0;;;;;;;-1:-1:-1;;;156856:46:0;;;;;;;;;;;;-1:-1:-1;156917:11:0;156913:304;;157008:7;;156987:10;:29;;;;;;;157008:7;;156987:29;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;157051:1;157031:16;;:21;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;157069:11:0;;:1;157095:11;157107:7;157095:20;;;;;;;:::i;:::-;:24;;:20;;:24;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;157095:24:0;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;157095:24:0;-1:-1:-1;;;157095:24:0;;;;;;;-1:-1:-1;;;;157095:24:0;;;;;-1:-1:-1;;;157095:24:0;;;;;;;;;;;;-1:-1:-1;;;;157095:24:0;-1:-1:-1;;;157095:24:0;;;;;;;;;;;;;;157171:34;;19282:25:1;;;157189:15:0;19323:18:1;;;19316:34;;;;157171::0;;19255:18:1;157171:34:0;;;;;;;156647:577;;156603:621;:::o;14:180:1:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:1;;14:180;-1:-1:-1;14:180:1:o;381:316::-;458:6;466;474;527:2;515:9;506:7;502:23;498:32;495:52;;;543:1;540;533:12;495:52;-1:-1:-1;;566:23:1;;;636:2;621:18;;608:32;;-1:-1:-1;687:2:1;672:18;;;659:32;;381:316;-1:-1:-1;381:316:1:o;702:248::-;770:6;778;831:2;819:9;810:7;806:23;802:32;799:52;;;847:1;844;837:12;799:52;-1:-1:-1;;870:23:1;;;940:2;925:18;;;912:32;;-1:-1:-1;702:248:1:o;955:597::-;1067:4;1096:2;1125;1114:9;1107:21;1157:6;1151:13;1200:6;1195:2;1184:9;1180:18;1173:34;1225:1;1235:140;1249:6;1246:1;1243:13;1235:140;;;1344:14;;;1340:23;;1334:30;1310:17;;;1329:2;1306:26;1299:66;1264:10;;1235:140;;;1393:6;1390:1;1387:13;1384:91;;;1463:1;1458:2;1449:6;1438:9;1434:22;1430:31;1423:42;1384:91;-1:-1:-1;1536:2:1;1515:15;-1:-1:-1;;1511:29:1;1496:45;;;;1543:2;1492:54;;955:597;-1:-1:-1;;;955:597:1:o;1557:131::-;-1:-1:-1;;;;;1632:31:1;;1622:42;;1612:70;;1678:1;1675;1668:12;1693:315;1761:6;1769;1822:2;1810:9;1801:7;1797:23;1793:32;1790:52;;;1838:1;1835;1828:12;1790:52;1877:9;1864:23;1896:31;1921:5;1896:31;:::i;:::-;1946:5;1998:2;1983:18;;;;1970:32;;-1:-1:-1;;;1693:315:1:o;2205:615::-;2291:6;2299;2352:2;2340:9;2331:7;2327:23;2323:32;2320:52;;;2368:1;2365;2358:12;2320:52;2408:9;2395:23;2437:18;2478:2;2470:6;2467:14;2464:34;;;2494:1;2491;2484:12;2464:34;2532:6;2521:9;2517:22;2507:32;;2577:7;2570:4;2566:2;2562:13;2558:27;2548:55;;2599:1;2596;2589:12;2548:55;2639:2;2626:16;2665:2;2657:6;2654:14;2651:34;;;2681:1;2678;2671:12;2651:34;2734:7;2729:2;2719:6;2716:1;2712:14;2708:2;2704:23;2700:32;2697:45;2694:65;;;2755:1;2752;2745:12;2694:65;2786:2;2778:11;;;;;2808:6;;-1:-1:-1;2205:615:1;;-1:-1:-1;;;;2205:615:1:o;2825:456::-;2902:6;2910;2918;2971:2;2959:9;2950:7;2946:23;2942:32;2939:52;;;2987:1;2984;2977:12;2939:52;3026:9;3013:23;3045:31;3070:5;3045:31;:::i;:::-;3095:5;-1:-1:-1;3152:2:1;3137:18;;3124:32;3165:33;3124:32;3165:33;:::i;:::-;2825:456;;3217:7;;-1:-1:-1;;;3271:2:1;3256:18;;;;3243:32;;2825:456::o;4025:632::-;4196:2;4248:21;;;4318:13;;4221:18;;;4340:22;;;4167:4;;4196:2;4419:15;;;;4393:2;4378:18;;;4167:4;4462:169;4476:6;4473:1;4470:13;4462:169;;;4537:13;;4525:26;;4606:15;;;;4571:12;;;;4498:1;4491:9;4462:169;;;-1:-1:-1;4648:3:1;;4025:632;-1:-1:-1;;;;;;4025:632:1:o;4662:247::-;4721:6;4774:2;4762:9;4753:7;4749:23;4745:32;4742:52;;;4790:1;4787;4780:12;4742:52;4829:9;4816:23;4848:31;4873:5;4848:31;:::i;:::-;4898:5;4662:247;-1:-1:-1;;;4662:247:1:o;5122:454::-;5217:6;5225;5233;5241;5249;5302:3;5290:9;5281:7;5277:23;5273:33;5270:53;;;5319:1;5316;5309:12;5270:53;-1:-1:-1;;5342:23:1;;;5412:2;5397:18;;5384:32;;-1:-1:-1;5463:2:1;5448:18;;5435:32;;5514:2;5499:18;;5486:32;;-1:-1:-1;5565:3:1;5550:19;5537:33;;-1:-1:-1;5122:454:1;-1:-1:-1;5122:454:1:o;5780:388::-;5848:6;5856;5909:2;5897:9;5888:7;5884:23;5880:32;5877:52;;;5925:1;5922;5915:12;5877:52;5964:9;5951:23;5983:31;6008:5;5983:31;:::i;:::-;6033:5;-1:-1:-1;6090:2:1;6075:18;;6062:32;6103:33;6062:32;6103:33;:::i;:::-;6155:7;6145:17;;;5780:388;;;;;:::o;6366:127::-;6427:10;6422:3;6418:20;6415:1;6408:31;6458:4;6455:1;6448:15;6482:4;6479:1;6472:15;6498:127;6559:10;6554:3;6550:20;6547:1;6540:31;6590:4;6587:1;6580:15;6614:4;6611:1;6604:15;6630:120;6670:1;6696;6686:35;;6701:18;;:::i;:::-;-1:-1:-1;6735:9:1;;6630:120::o;6755:168::-;6795:7;6861:1;6857;6853:6;6849:14;6846:1;6843:21;6838:1;6831:9;6824:17;6820:45;6817:71;;;6868:18;;:::i;:::-;-1:-1:-1;6908:9:1;;6755:168::o;6928:356::-;7130:2;7112:21;;;7149:18;;;7142:30;7208:34;7203:2;7188:18;;7181:62;7275:2;7260:18;;6928:356::o;7289:251::-;7359:6;7412:2;7400:9;7391:7;7387:23;7383:32;7380:52;;;7428:1;7425;7418:12;7380:52;7460:9;7454:16;7479:31;7504:5;7479:31;:::i;7545:135::-;7584:3;-1:-1:-1;;7605:17:1;;7602:43;;;7625:18;;:::i;:::-;-1:-1:-1;7672:1:1;7661:13;;7545:135::o;7685:127::-;7746:10;7741:3;7737:20;7734:1;7727:31;7777:4;7774:1;7767:15;7801:4;7798:1;7791:15;7817:334;8019:2;8001:21;;;8058:2;8038:18;;;8031:30;-1:-1:-1;;;8092:2:1;8077:18;;8070:40;8142:2;8127:18;;7817:334::o;8862:128::-;8902:3;8933:1;8929:6;8926:1;8923:13;8920:39;;;8939:18;;:::i;:::-;-1:-1:-1;8975:9:1;;8862:128::o;9348:380::-;9427:1;9423:12;;;;9470;;;9491:61;;9545:4;9537:6;9533:17;9523:27;;9491:61;9598:2;9590:6;9587:14;9567:18;9564:38;9561:161;;;9644:10;9639:3;9635:20;9632:1;9625:31;9679:4;9676:1;9669:15;9707:4;9704:1;9697:15;9733:338;9935:2;9917:21;;;9974:2;9954:18;;;9947:30;-1:-1:-1;;;10008:2:1;9993:18;;9986:44;10062:2;10047:18;;9733:338::o;10485:189::-;10524:1;10550:8;10585:2;10582:1;10578:10;10607:3;10597:37;;10614:18;;:::i;:::-;10652:10;;10648:20;;;;;10485:189;-1:-1:-1;;10485:189:1:o;10679:125::-;10719:4;10747:1;10744;10741:8;10738:34;;;10752:18;;:::i;:::-;-1:-1:-1;10789:9:1;;10679:125::o;10809:184::-;10879:6;10932:2;10920:9;10911:7;10907:23;10903:32;10900:52;;;10948:1;10945;10938:12;10900:52;-1:-1:-1;10971:16:1;;10809:184;-1:-1:-1;10809:184:1:o;11613:127::-;11674:10;11669:3;11665:20;11662:1;11655:31;11705:4;11702:1;11695:15;11729:4;11726:1;11719:15;12090:232;12129:3;12157:14;12198:2;12195:1;12191:10;12228:2;12225:1;12221:10;12259:3;12255:2;12251:12;12246:3;12243:21;12240:47;;;12267:18;;:::i;:::-;12303:13;;12090:232;-1:-1:-1;;;;12090:232:1:o;12327:422::-;12416:1;12459:5;12416:1;12473:270;12494:7;12484:8;12481:21;12473:270;;;12553:4;12549:1;12545:6;12541:17;12535:4;12532:27;12529:53;;;12562:18;;:::i;:::-;12612:7;12602:8;12598:22;12595:55;;;12632:16;;;;12595:55;12711:22;;;;12671:15;;;;12473:270;;;12477:3;12327:422;;;;;:::o;12754:806::-;12803:5;12833:8;12823:80;;-1:-1:-1;12874:1:1;12888:5;;12823:80;12922:4;12912:76;;-1:-1:-1;12959:1:1;12973:5;;12912:76;13004:4;13022:1;13017:59;;;;13090:1;13085:130;;;;12997:218;;13017:59;13047:1;13038:10;;13061:5;;;13085:130;13122:3;13112:8;13109:17;13106:43;;;13129:18;;:::i;:::-;-1:-1:-1;;13185:1:1;13171:16;;13200:5;;12997:218;;13299:2;13289:8;13286:16;13280:3;13274:4;13271:13;13267:36;13261:2;13251:8;13248:16;13243:2;13237:4;13234:12;13230:35;13227:77;13224:159;;;-1:-1:-1;13336:19:1;;;13368:5;;13224:159;13415:34;13440:8;13434:4;13415:34;:::i;:::-;13485:6;13481:1;13477:6;13473:19;13464:7;13461:32;13458:58;;;13496:18;;:::i;:::-;13534:20;;12754:806;-1:-1:-1;;;12754:806:1:o;13565:131::-;13625:5;13654:36;13681:8;13675:4;13654:36;:::i;14795:226::-;14834:3;14862:8;14897:2;14894:1;14890:10;14927:2;14924:1;14920:10;14958:3;14954:2;14950:12;14945:3;14942:21;14939:47;;;14966:18;;:::i;15026:230::-;15065:3;15093:12;15132:2;15129:1;15125:10;15162:2;15159:1;15155:10;15193:3;15189:2;15185:12;15180:3;15177:21;15174:47;;;15201:18;;:::i;17447:332::-;17649:2;17631:21;;;17688:1;17668:18;;;17661:29;-1:-1:-1;;;17721:2:1;17706:18;;17699:39;17770:2;17755:18;;17447:332::o;17784:857::-;17914:6;17922;17930;17938;17946;17954;17962;17970;18023:3;18011:9;18002:7;17998:23;17994:33;17991:53;;;18040:1;18037;18030:12;17991:53;18069:9;18063:16;18053:26;;18122:2;18111:9;18107:18;18101:25;18135:31;18160:5;18135:31;:::i;:::-;18235:2;18220:18;;18214:25;18185:5;;-1:-1:-1;18248:33:1;18214:25;18248:33;:::i;:::-;18300:7;18290:17;;;18347:2;18336:9;18332:18;18326:25;18316:35;;18391:3;18380:9;18376:19;18370:26;18360:36;;18436:3;18425:9;18421:19;18415:26;18405:36;;18486:3;18475:9;18471:19;18465:26;18536:7;18529:15;18522:23;18513:7;18510:36;18500:64;;18560:1;18557;18550:12;18500:64;18583:7;18573:17;;;18630:3;18619:9;18615:19;18609:26;18599:36;;17784:857;;;;;;;;;;;:::o;18646:228::-;18685:3;18713:10;18750:2;18747:1;18743:10;18780:2;18777:1;18773:10;18811:3;18807:2;18803:12;18798:3;18795:21;18792:47;;;18819:18;;:::i;18879:224::-;18918:3;18946:6;18979:2;18976:1;18972:10;19009:2;19006:1;19002:10;19040:3;19036:2;19032:12;19027:3;19024:21;19021:47;;;19048:18;;:::i;21383:223::-;21422:4;21451:12;21513:10;;;;21483;;21535:12;;;21532:38;;;21550:18;;:::i;:::-;21587:13;;21383:223;-1:-1:-1;;;21383:223:1:o;21611:217::-;21650:4;21679:6;21735:10;;;;21705;;21757:12;;;21754:38;;;21772:18;;:::i

Swarm Source

ipfs://496efac85ea5c0fbde61ff553db71eabe4d06fc351b05f3a09cf24be9d7ff63a
Loading