Source Code
Overview
ETH Balance
0.267973165563852716 ETH
Token Holdings
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 4,656 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Mint Tokens Same... | 34108439 | 15 days ago | IN | 0.000055 ETH | 0.00000005 | ||||
| Mint Tokens Same... | 34106679 | 15 days ago | IN | 0.00001575 ETH | 0.00000005 | ||||
| Mint Tokens Same... | 34106601 | 15 days ago | IN | 0.00001218 ETH | 0.00000005 | ||||
| Mint Tokens Same... | 34106433 | 15 days ago | IN | 0.00001683 ETH | 0.00000005 | ||||
| Mint Tokens Same... | 34106333 | 15 days ago | IN | 0.000055 ETH | 0.00000017 | ||||
| Mint Tokens Same... | 34076138 | 16 days ago | IN | 0.00001507 ETH | 0.00000016 | ||||
| Mint Tokens Same... | 34076045 | 16 days ago | IN | 0.00001066 ETH | 0.00000011 | ||||
| Mint Tokens Same... | 34075953 | 16 days ago | IN | 0.00000847 ETH | 0.00000005 | ||||
| Mint Tokens Same... | 34075936 | 16 days ago | IN | 0.00000931 ETH | 0.00000005 | ||||
| Mint Tokens Same... | 34075773 | 16 days ago | IN | 0.00001562 ETH | 0.00000016 | ||||
| Mint Tokens Same... | 34075674 | 16 days ago | IN | 0.00001578 ETH | 0.00000015 | ||||
| Mint Tokens Same... | 34075576 | 16 days ago | IN | 0.00000866 ETH | 0.00000016 | ||||
| Mint Tokens Same... | 34075572 | 16 days ago | IN | 0.0000085 ETH | 0.00000005 | ||||
| Mint Tokens Same... | 34075366 | 16 days ago | IN | 0.00001562 ETH | 0.00000015 | ||||
| Mint Tokens Same... | 34075244 | 16 days ago | IN | 0.00002 ETH | 0.00000016 | ||||
| Mint Tokens Same... | 34075243 | 16 days ago | IN | 0.00002 ETH | 0.00000015 | ||||
| Mint Tokens Same... | 34075210 | 16 days ago | IN | 0.00002 ETH | 0.00000016 | ||||
| Mint Tokens Same... | 34075182 | 16 days ago | IN | 0.00002 ETH | 0.00000015 | ||||
| Mint Tokens Same... | 34075164 | 16 days ago | IN | 0.00005 ETH | 0.00000017 | ||||
| Mint Tokens Same... | 34065442 | 16 days ago | IN | 0.00001012 ETH | 0.00038925 | ||||
| Mint Tokens Same... | 34065196 | 16 days ago | IN | 0.000014 ETH | 0.00036404 | ||||
| Mint Tokens Same... | 34064852 | 16 days ago | IN | 0.00001162 ETH | 0.00018269 | ||||
| Mint Tokens Same... | 34064721 | 16 days ago | IN | 0.00001562 ETH | 0.00013289 | ||||
| Mint Tokens Same... | 34064623 | 16 days ago | IN | 0.00001578 ETH | 0.00009428 | ||||
| Mint Tokens Same... | 34064527 | 16 days ago | IN | 0.00001562 ETH | 0.00007022 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | Amount | ||
|---|---|---|---|---|---|---|
| 34106333 | 15 days ago | 0.00005568 ETH | ||||
| 34076138 | 16 days ago | 0.00000024 ETH | ||||
| 34075773 | 16 days ago | 0.00000054 ETH | ||||
| 34075674 | 16 days ago | 0.00000054 ETH | ||||
| 34075576 | 16 days ago | 0.00000008 ETH | ||||
| 34075366 | 16 days ago | 0.00000341 ETH | ||||
| 34075244 | 16 days ago | 0 ETH | ||||
| 34075243 | 16 days ago | 0.00000001 ETH | ||||
| 34075210 | 16 days ago | 0.00000001 ETH | ||||
| 34075182 | 16 days ago | 0 ETH | ||||
| 34075164 | 16 days ago | 0.00005068 ETH | ||||
| 34065442 | 16 days ago | 0.00000008 ETH | ||||
| 34065196 | 16 days ago | 0.00000001 ETH | ||||
| 34064852 | 16 days ago | 0.00000026 ETH | ||||
| 34064721 | 16 days ago | 0.00000038 ETH | ||||
| 34064623 | 16 days ago | 0.00000022 ETH | ||||
| 34064527 | 16 days ago | 0.00000038 ETH | ||||
| 34064429 | 16 days ago | 0.00005068 ETH | ||||
| 34032900 | 17 days ago | 0.00000011 ETH | ||||
| 34032707 | 17 days ago | 0.00000019 ETH | ||||
| 34032592 | 17 days ago | 0.00000021 ETH | ||||
| 34032494 | 17 days ago | 0.00000018 ETH | ||||
| 34032326 | 17 days ago | 0.00000037 ETH | ||||
| 34032227 | 17 days ago | 0.00005068 ETH | ||||
| 34025297 | 17 days ago | 0.00000018 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
B0x_Mining_Proof_of_Work
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
//CHANGES NEEDED FOR MAINNET//
// uint public immutable startTime = block.timestamp; //1738771200; //Date and time (GMT): Wednesday, Feb 5, 2025 4:00:00 PM GMT Unix Epoch: 1738771200
// uint public immutable startTime = block.timestamp-24*60*60*2; //1738771200; //Date and time (GMT): Wednesday, Feb 5, 2025 4:00:00 PM GMT Unix Epoch: 1738771200
//Must make correct startTime
// uint public immutable startTime = block.timestamp-24*60*60*2; //1738771200; //Date and time (GMT): Wednesday, Feb 5, 2025 4:00:00 PM GMT Unix Epoch: 1738771200
// MUST REMOVE THE STATIC PRICE IN getETHPricePrecise please!
// Returns price multiplied by 10^22 (10^12 for USDC decimals + 10^10 for full precision)
// function getETHPricePrecise() public view returns (uint256 price) {
// return 3744799707501163;
//Fix return for now until mainnet then remove!
// MUST REMOVE THE STATIC PRICE IN getETHPricePrecise please!
// blocks = 1; //Use for testing NFT minting
//MUST make normal for blocks = 1 and
// uint public slowBlocks = 2048; //Number of slow blocks (12+ minutes)
//slow blocks should be 0
//
//in openMining miningTarget = (2**252); SHOULD BE 2**234!!!! //0xBTCs starting difficulty of 1 //change it to 2**234 for launch please
//in openMining miningTarget = (2**252); SHOULD BE 2**234!!!! //0xBTCs starting difficulty of 1 //change it to 2**234 for launch please
//
// miningTarget = 2**234; in readjustDifficulty
//for now to check stuff
//Make sure to change startTime to ur actual startTime
// address public B0x_Mining_TOKEN_ADDRESS = address(0x677F124CD209489F6621eebDFdA1E32c625214d4); MAKE IMMUTABLE TO CURRENT TOKEN WHEN LAUNCHING
// address public B0x_Mining_TOKEN_ADDRESS = address(0x677F124CD209489F6621eebDFdA1E32c625214d4); MAKE IMMUTABLE TO CURRENT TOKEN WHEN LAUNCHING
//SHOULD BE Base Network and BASED WORK TOKEN PLEASE ADJUST BEFORE REAL LAUNCH
//address constant public B0x_Mining_TOKEN_ADDRESS = address(0x677F124CD209489F6621eebDFdA1E32c625214d4); //SHOULD BE Base Network and BASED WORK TOKEN
//should be constant when deployed
//SHOULD BE Base Network and BASED WORK TOKEN PLEASE ADJUST BEFORE REAL LAUNCH
//address constant public B0x_Mining_TOKEN_ADDRESS = address(0x677F124CD209489F6621eebDFdA1E32c625214d4); //SHOULD BE Base Network and BASED WORK TOKEN
// address public B0x_Mining_TOKEN_ADDRESS = address(0x677F124CD209489F6621eebDFdA1E32c625214d4); MAKE IMMUTABLE TO CURRENT TOKEN WHEN LAUNCHING
// address public B0x_Mining_TOKEN_ADDRESS = address(0x677F124CD209489F6621eebDFdA1E32c625214d4); MAKE IMMUTABLE TO CURRENT TOKEN WHEN LAUNCHING
///**
//**MUST REMOVE THIS FUNCTION BEFORE WE LAUNCH setDifficultyOnlyTestnet must be removed before mainnet launches, this is just for extra help testnet stuff
//function setDifficultyOnlyTestnet(uint _newDifficulty) public onlyOwner returns (bool) {
// **////**
//**MUST REMOVE THIS FUNCTION BEFORE WE LAUNCH setDifficultyOnlyTestnet must be removed before mainnet launches, this is just for extra help testnet stuff
//function setDifficultyOnlyTestnet(uint _newDifficulty) public onlyOwner returns (bool) {
// **/
//Remove Ownable2 we dont need it for mainnet only for testnet to reset difficulty
//Remove Ownable2 we dont need it for mainnet only for testnet to reset difficulty
//Remove Ownable2 we dont need it for mainnet only for testnet to reset difficulty
/*
MUST HAVE BASE MAINNET TOKEN ADDRESS HERE Uniswap v3 USDC/ETH pool here test this function seperatly on mainnet first before launch
/// @notice USDC/ETH pool address on Base for price reference
/// @dev Used for sqrtPricex96 calculations, Uniswap V3 pool on Base mainnet
address constant POOL_ADDRESS = 0xd0b53D9277642d899DF5C87A3966A349A798F224;
*/
// B ZERO X Token - B0x Token Proof of Work Mining Contract
//
// Website: https://bzerox.com/
// Github: https://github.com/B0x-Token/
// Discord: https://discord.gg/K89uF2C8vJ
// Twitter: https://x.com/B0x_Token/
//
//
// Distrubtion of B ZERO X Tokens - B0x Token is as follows:
//
// B0x Token is distributed to users by using Proof of work and is considered a Version 2 & Layer 2 of 0xBitcoin. Our contract allows all 0xBitcoin to be converted to B0x Tokens.
// Computers solve a complicated problem to gain tokens!
// 100% of 0xBitcoin accepted for B0x Tokens
// 100% Of the Token is distributed to the users! No dev fee!
// Token Mining will take place on Base Blockchain, while having the token reside on Mainnet Ethereum for maximum security.
//
// Symbol: B0x
// Decimals: 18
//
// Total supply: 31,165,100.000000000000000000
// =
// 10,835,900 0xBitcoin Tokens able to transfered to B0x Tokens.
// +
// 10,164,100 Mined over 100+ years using Bitcoins Distrubtion halvings every ~4 years. Uses Proof-oF-Work to distribute the tokens. Public Miner is available see https://bzerox.com/
// +
// 10,164,100 sent to Liquidity Providers of the 0xBTC/B0x liquidity pool. Distributes 1 token to the Staking contract for every 1 token minted by Proof-of-Work miners
//
//
// No dev cut, or advantage taken at launch. Public miner available at launch. 100% of the token is given away fairly over 100+ years using Bitcoins model!
//
// Mint 2016 answers per challenge in this cost savings Bitcoin!! Less failed transactions as the challenge only changes every 2016 answers instead of every answer.
//
// Credits: 0xBitcoin
//
// startTime = 1738771200; //Date and time (GMT): Wednesday, Feb 5, 2025 4:00:00 PM GMT then openMining functioncan then be called and mining will have rewards, until then all rewards will be 0.
pragma solidity ^0.8.11;
/// @title Ownable2
/// @notice Basic ownership contract providing access control functionality
/// @dev Implements ownership transfer with event logging for transparency
contract Ownable2 {
/// @notice Address of the current contract owner with administrative privileges
/// @dev Set to deployer initially, can be transferred to another address
address public owner;
/// @notice Emitted when ownership is transferred from one address to another
/// @param from The previous owner address (address(0) for initial assignment)
/// @param to The new owner address receiving ownership privileges
event TransferOwnership(address from, address to);
/// @notice Initializes the contract and sets the deployer as the initial owner
/// @dev Emits TransferOwnership event with address(0) as the from address
constructor() {
owner = msg.sender;
emit TransferOwnership(address(0), msg.sender);
}
/// @notice Restricts function access to only the current contract owner
/// @dev Reverts with "Only Owner" message if called by non-owner address
modifier onlyOwner() {
require(msg.sender == owner, "Only Owner");
_;
}
/// @notice Internal function to transfer ownership to a new address
/// @dev Can only be called by the current owner, emits TransferOwnership event
/// @param _owner The address to transfer ownership to
function setOwner(address _owner) internal onlyOwner {
emit TransferOwnership(owner, _owner);
owner = _owner;
}
}
// File: contracts/utils/SafeMath.sol
library SafeMath2 {
function add(uint256 x, uint256 y) internal pure returns (uint256) {
uint256 z = x + y;
require(z >= x);
return z;
}
function sub(uint256 x, uint256 y) internal pure returns (uint256) {
require(x >= y);
return x - y;
}
function mult(uint256 x, uint256 y) internal pure returns (uint256) {
if (x == 0) {
return 0;
}
uint256 z = x * y;
require(z / x == y);
return z;
}
function div(uint256 x, uint256 y) internal pure returns (uint256) {
require(y != 0);
return x / y;
}
function divRound(uint256 x, uint256 y) internal pure returns (uint256) {
require(y != 0);
uint256 r = x / y;
if (x % y != 0) {
r = r + 1;
}
return r;
}
}
interface IERC721 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must 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 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 the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
//Recieve NFTs
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
//Main contract
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);
}
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC
5MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
interface IUniswapV3Pool {
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
}
interface IPoolFactory {
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address pool);
}
interface IETHConverter {
/**
* @notice Convert ETH to WETH
* @dev Converts all ETH sent with the transaction to WETH
*/
function convertETHtoWETH() external payable;
}
// File: contracts/interfaces/IERC20.sol
interface IERC20 {
function transfer(address _to, uint _value) external returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
function balanceOf(address _owner) external view returns (uint256 balance);
}
// File: contracts/B0x_Mining_Proof_Of_Work.sol
// B ZERO X Token - B0x Token Proof of Work Mining Contract.
//
// Website: https://bzerox.com/
// Github: https://github.com/B0x-Token/
// Discord: https://discord.gg/K89uF2C8vJ
// Twitter: https://x.com/B0x_Token/
//
//
// Distrubtion of B ZERO X Tokens - B0x Token is as follows:
//
// B0x Token is distributed to users by using Proof of work and is considered a Version 2 & Layer 2 of 0xBitcoin. Our contract allows all 0xBitcoin to be converted to B0x Tokens.
// Computers solve a complicated problem to gain tokens!
// 100% of 0xBitcoin accepted for B0x Tokens
// 100% Of the Token is distributed to the users! No dev fee!
// Token Mining will take place on Base Blockchain, while having the token reside on Mainnet Ethereum for maximum security.
//
// Symbol: B0x
// Decimals: 18
//
// Total supply: 31,165,100.000000000000000000
// =
// 10,835,900 0xBitcoin Tokens able to transfered to B0x Tokens.
// +
// 10,164,100 Mined over 100+ years using Bitcoins Distrubtion halvings every ~4 years. Uses Proof-oF-Work to distribute the tokens. Public Miner is available see https://bzerox.com/
// +
// 10,164,100 sent to Liquidity Providers of the 0xBTC/B0x liquidity pool. Distributes 1 token to the Staking contract for every 1 token minted by Proof-of-Work miners
//
//
// No dev cut, or advantage taken at launch. Public miner available at launch. 100% of the token is given away fairly over 100+ years using Bitcoins model!
//
// Mint 2016 answers per challenge in this cost savings Bitcoin!! Less failed transactions as the challenge only changes every 2016 answers instead of every answer.
//
// Credits: 0xBitcoin
//
// startTime = 1738771200; //Date and time (GMT): Wednesday, Feb 5, 2025 4:00:00 PM GMT then openMining functioncan then be called and mining will have rewards, until then all rewards will be 0.
//Remove the Ownable2 for mainnet release
/// @title B0x Mining Proof of Work
/// @notice Proof of Work mining contract for B0x tokens on Base network
/// @dev Implements Bitcoin-style mining with difficulty adjustments and reward halvings
contract B0x_Mining_Proof_of_Work is Ownable2 {
////
// Based Work Token Mining Initializations
////
/// @notice Address of the B0x token contract on Base network
/// @dev Should be made immutable for mainnet deployment to prevent changes
address public B0x_Mining_TOKEN_ADDRESS = address(0x677F124CD209489F6621eebDFdA1E32c625214d4);
/// @notice USDC/ETH pool address on Base for price reference
/// @dev Used for sqrtPricex96 calculations, Uniswap V3 pool on Base mainnet
address constant POOL_ADDRESS = 0xd0b53D9277642d899DF5C87A3966A349A798F224;
/// @notice Target time between blocks in seconds (10 minutes)
/// @dev Used for difficulty adjustments to maintain consistent block times
uint public targetTime = 60 * 10;
/// @notice Immutable start time for mining operations
/// @dev Set to 2 days before deployment for initial calculations
uint public immutable startTime = block.timestamp - 24 * 60 * 60 * 2;
using SafeMath2 for uint256;
/// @notice Emitted when a standard mining reward is claimed
/// @param from Address of the miner who found the solution
/// @param reward_amount Amount of tokens minted as reward
/// @param epochCount Current epoch number when mined
/// @param newChallengeNumber The new challenge for the next block
event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber);
/// @notice Emitted when a mega mining reward is claimed with multiplier
/// @param from Address of the miner who found the solution
/// @param epochCount Current epoch number when mined
/// @param newChallengeNumber The new challenge for the next block
/// @param NumberOfTokensMinted Total number of tokens minted
/// @param TokenMultipler Multiplier applied to the base reward
event MegaMint(address indexed from, uint epochCount, bytes32 newChallengeNumber, uint NumberOfTokensMinted, uint256 TokenMultipler);
/// @notice Prevents reuse of challenge-digest combinations
/// @dev Maps challenge hash to digest hash to boolean (used/unused)
mapping(bytes32 => mapping(bytes32 => bool)) public usedCombinations;
/// @notice Prevents the same challenge from being used multiple times
/// @dev Maps challenge hash to boolean (used/unused)
mapping(bytes32 => bool) public usedChallenges;
/// @notice Maps used challenges to their sequential number
/// @dev Tracks the order in which challenges were used
mapping(bytes32 => uint) public usedChallengesNumber;
/// @notice Number of blocks between difficulty adjustments (Bitcoin-style)
/// @dev Should be 2016 blocks to align with Bitcoin's adjustment period
uint public constant _BLOCKS_PER_READJUSTMENT = 2016;
/// @notice Maximum mining target to prevent difficulty from becoming too easy
/// @dev Large number at least 5x smaller than max to prevent overflow (max 4x increases)
uint public constant _MAXIMUM_TARGET = 2**253;
/// @notice Minimum mining target to prevent difficulty from becoming impossible
/// @dev Small number ensuring mining remains feasible
uint public constant _MINIMUM_TARGET = 2**16;
/// @notice Current mining target for difficulty calculation
/// @dev Normalized to 0xBitcoin's starting difficulty (2**234)
uint public miningTarget = 2**234;
/// @notice Maximum total supply of tokens (21 million, Bitcoin-style)
/// @dev Hard cap on total token creation
uint public constant _maxTotalSupply = 21000000000000000000000000;
/// @notice Timestamp of the last difficulty adjustment
/// @dev Used for calculating time-based difficulty adjustments
uint public latestDifficultyPeriodStarted2 = block.timestamp;
/// @notice Block number of the last difficulty adjustment
/// @dev Used for block-based difficulty adjustments
uint public latestDifficultyPeriodStarted = block.number;
/// @notice Number of blocks mined (epochs completed)
/// @dev Incremented with each successful mine
uint public epochCount = 0;
/// @notice Current challenge that miners must solve
/// @dev Based on previous block hash, changes with each successful mine
bytes32 public challengeNumber = blockhash(block.number - 1);
/// @notice Current reward era for halving calculations
/// @dev Determines the current reward amount based on total supply
uint public rewardEra = 1;
/// @notice Maximum supply allowed for the current reward era
/// @dev Calculated based on reward era for halving mechanics
uint public maxSupplyForEra = (_maxTotalSupply - _maxTotalSupply.div(2**(rewardEra + 1)));
/// @notice Current reward amount per successful mine
/// @dev Calculated based on current era and supply
uint public reward_amount = 0;
/// @notice Minimum ETH amount for price calculations
/// @dev 0.0000005 ETH * $4500/ETH = $0.00225 minimum price per token
uint constant minAmountETH = 0.0000005 ether;
/// @notice Total tokens minted so far
/// @dev Starts at 10,835,900 tokens (matching 0xBitcoin's mined amount)
uint public tokensMinted = 10_835_900 * 10**18;
/// @notice Total ETH distributed to miners
/// @dev Tracks cumulative ETH rewards paid out
uint public totalETH_MintedToMiners = 0;
/// @notice Last recorded token count for calculations
/// @dev Used in reward distribution calculations
uint lastRunB0x = tokensMinted;
/// @notice Last recorded ETH amount for calculations
/// @dev Used in reward distribution calculations
uint lastRunETH = 0;
/// @notice Epoch count at the last readjustment
/// @dev Used for tracking adjustment periods
uint public epochOld = 0;
/// @notice Startup lock to prevent premature operations
/// @dev Security mechanism for controlled contract initialization
bool public locked = false;
/// @notice Handles safe receipt of ERC721 tokens
/// @dev Required for receiving NFTs sent to this contract
/// @return bytes4 The function selector to confirm receipt
function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
return IERC721Receiver.onERC721Received.selector;
}
/// @notice Handles safe receipt of ERC1155 tokens
/// @dev Required for receiving ERC1155 tokens sent to this contract
/// @return bytes4 The function selector to confirm receipt
function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) {
return IERC1155Receiver.onERC1155Received.selector;
}
/// @notice Handles safe batch receipt of ERC1155 tokens
/// @dev Required for receiving batch ERC1155 transfers
/// @return bytes4 The function selector to confirm receipt
function onERC1155BatchReceived(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) {
return IERC1155Receiver.onERC1155Received.selector;
}
// SUPPORTING CONTRACTS
/// @notice Address of the LP reward distribution contract
/// @dev Contract responsible for distributing rewards to liquidity providers
address public AddressLPReward;
/// @notice Total B0x tokens sent to LP reward pool
/// @dev Tracks cumulative tokens allocated to liquidity providers
uint public sentToLP = 0;
/// @notice Multiplier based on held Ethereum amount
/// @dev Higher ETH holdings reduce the percentage distributed (inverse relationship)
uint public multipler = 0;
/// @notice Previous epoch count for reward calculations
/// @dev Used in ArewardSender function for tracking changes
uint public oldecount = 0;
/// @notice Previous block timestamp for time calculations
/// @dev Used for measuring time intervals between operations
uint public previousBlockTime = block.timestamp;
/// @notice Amount of ETH distributed per mint operation
/// @dev Tracks ETH distribution rate per successful mine
uint public Token2Per = 0;
/// @notice Number of slow blocks (taking 12+ minutes to mine)
/// @dev Tracks mining performance and difficulty appropriateness
uint public slowBlocks = 0;
/// @notice Amount of 0x tokens to give (legacy reference)
/// @dev May be related to 0xBitcoin compatibility or rewards
uint public give0x = 0;
/// @notice Timestamp of the last function execution
/// @dev Used for rate limiting and timing calculations
uint256 public lastrun = block.timestamp;
//**MUST REMOVE THIS FUNCTION BEFORE WE LAUNCH setDifficultyOnlyTestnet must be removed before mainnet launches, this is just for extra help testnet stuff */
//**MUST REMOVE THIS FUNCTION BEFORE WE LAUNCH setDifficultyOnlyTestnet must be removed before mainnet launches, this is just for extra help testnet stuff */
//**MUST REMOVE THIS FUNCTION BEFORE WE LAUNCH setDifficultyOnlyTestnet must be removed before mainnet launches, this is just for extra help testnet stuff */
/// @notice TESTNET ONLY: Manually sets mining difficulty for testing purposes
/// @dev ⚠️ CRITICAL: This function MUST be removed before mainnet deployment
/// @dev Allows owner to override difficulty calculations for easier testnet mining
/// @dev Uses 0xBTC difficulty scale with 524,288 normalization factor
/// @param _newDifficulty The difficulty level to set (must be below 10,000)
/// @return bool True if difficulty was successfully updated
/// @custom:security-note This function bypasses normal difficulty adjustment mechanisms
/// @custom:mainnet-warning REMOVE THIS FUNCTION BEFORE PRODUCTION DEPLOYMENT
function setDifficultyOnlyTestnet(uint _newDifficulty) public onlyOwner returns (bool) {
require(_newDifficulty < 10000, "New difficulty must be at least below 10000 0xBTC difficulty not higher");
miningTarget = _MAXIMUM_TARGET.div(_newDifficulty * 524_288);
return true;
}
/// @notice Initializes the B0x mining contract with token and LP reward addresses
/// @dev Sets up initial mining parameters and marks the first challenge as used
/// @param token Address of the B0x token contract to be mined
/// @param lp Address of the LP reward distribution contract
constructor(address token, address lp) {
B0x_Mining_TOKEN_ADDRESS = token;
AddressLPReward = lp;
latestDifficultyPeriodStarted2 = block.timestamp;
latestDifficultyPeriodStarted = block.number;
challengeNumber = blockhash(block.number - 1); //generate a new one so we can start with a fresh
usedChallenges[blockhash(block.number - 1)] = true;
}
/// @notice Activates mining operations with initial parameters and safety checks
/// @dev Can only be called once within a 7-day window after startTime, requires proper token funding
/// @dev Initializes mining with Feb 5th 2025 @ 4PM GMT target launch (epochTime = 1738771200)
/// @return success True if mining was successfully activated
/// @custom:timing Must be called between startTime and startTime + 7 days
/// @custom:funding Requires contract to hold at least 20,328,200 B0x tokens (2*10,164,100)
function openMining() public returns (bool success) {
require(tokensMinted <= 10_835_900 * 10**18, "Cant mint tokens before launch");
require(IERC20(B0x_Mining_TOKEN_ADDRESS).balanceOf(address(this)) >= 2*10_164_100 * 10 ** 18, "Must supply 2*10_164_100 min tokens");
require(reward_amount == 0, "reward must be zero");
require(!locked, "Only allowed to run once");
locked = true;
require(block.timestamp >= startTime && block.timestamp <= startTime + 60* 60 * 24* 7, "7 Day window to activate StartTime");
challengeNumber = blockhash(block.number - 1); //generate a new one so we can start fresh
reward_amount = (50 * 10**18) / (2**(rewardEra));
maxSupplyForEra = (_maxTotalSupply - _maxTotalSupply.div(2**(rewardEra + 1)));
miningTarget = (2**234); //0xBTCs starting difficulty of 1 //change it to 2**234 for launch please
latestDifficultyPeriodStarted2 = block.timestamp;
latestDifficultyPeriodStarted = block.number;
epochOld = 0;
epochCount = 0;//number of 'blocks' mined
require(usedChallenges[challengeNumber] == false);
usedChallenges[challengeNumber] = true;
return true;
}
/// @notice Calculates Token2Per_return given a multiplier
/// @dev Returns Token2Per_return to scale base reward amounts
/// @dev Higher multipliers progressively reduce ETH distribution rewards
/// @param multiplier The multiplier value to determine scaling tier
/// @return Token2Per_return The amount of Token to be distributed
/// @custom:scaling-tiers
function getToken2Per(uint multiplier) internal pure returns (uint Token2Per_return) {
if (multiplier < 200) {
Token2Per_return = 0.00000180 ether * multiplier / 200;
} else if (multiplier < 400) {
Token2Per_return = 0.00000300 ether * multiplier / 400;
} else if (multiplier < 800) {
Token2Per_return = 0.00000500 ether * multiplier / 800;
} else if (multiplier < 1600) {
Token2Per_return = 0.00000800 ether * multiplier / 1600;
} else if (multiplier < 3000) {
Token2Per_return = 0.00001200 ether * multiplier / 3000;
} else if (multiplier < 5000) {
Token2Per_return = 0.00001500 ether * multiplier / 5000;
} else if (multiplier < 10000) {
Token2Per_return = 0.00002000 ether * multiplier / 10000;
} else if (multiplier < 20000) {
Token2Per_return = 0.00003000 ether * multiplier / 20000;
} else if (multiplier < 40000) {
Token2Per_return = 0.00005000 ether * multiplier / 40000;
} else if (multiplier < 100000) {
Token2Per_return = 0.00010000 ether * multiplier / 100000;
} else if (multiplier < 200000) {
Token2Per_return = 0.00015000 ether * multiplier / 200000;
} else if (multiplier < 500000) {
Token2Per_return = 0.00025000 ether * multiplier / 500000;
} else if (multiplier < 1000000) {
Token2Per_return = 0.00050000 ether * multiplier / 1000000;
} else {
Token2Per_return = (0.00050000 ether * multiplier) / 1000000;
}
}
/// @notice Distributes accumulated rewards to liquidity providers when adjustment threshold is met
/// @dev Executes every BLOCKS_PER_READJUSTMENT / 4 blocks to manage LP reward distribution
/// @dev Calculates multiplier based on contract balance vs 0.15 ETH adjustment threshold
/// @dev Determines scaling factor for Token2Per using the calculated multiplier
/// @dev Transfers accumulated B0x tokens to LP reward address
/// @dev Conditionally sends ETH to LP reward address if balance is sufficient
/// @dev Updates tracking variables for next execution cycle
/// @custom:requirements Contract must have sufficient balance for ETH transfers
/// @custom:requirements B0x mining token contract must be valid and have sufficient balance
/// @custom:requirements LP reward address must be set and valid
/// @custom:state-changes Updates multipler, Token2Per, sentToLP, give0x flag, lastRunB0x, lastRunETH
function ARewardSender() public {
//runs every _BLOCKS_PER_READJUSTMENT / 4
uint256 ADJUSTMENT_THRESHOLD = 0.1499999999999 ether;
multipler = (address(this).balance*100) / ADJUSTMENT_THRESHOLD; //Adjust every 0.15 eth or 700$
// Use a more compact approach to determine the scaling factor
Token2Per = getToken2Per(multipler);
uint B0x_To_LPERS = tokensMinted - lastRunB0x;
uint ETH_To_LPERs = totalETH_MintedToMiners - lastRunETH;
IERC20(B0x_Mining_TOKEN_ADDRESS).transfer(AddressLPReward, B0x_To_LPERS);
sentToLP = sentToLP.add(B0x_To_LPERS);
if(address(this).balance > (80 * (Token2Per * _BLOCKS_PER_READJUSTMENT/2))) { // at least enough blocks to rerun this function for both LPRewards and Users
address payable to = payable(AddressLPReward);
(bool success, ) = to.call{value: ETH_To_LPERs}("");
require(success, "ETH transfer failed");
give0x = 1;
IETHConverter(AddressLPReward).convertETHtoWETH();
} else {
give0x = 0;
}
lastRunB0x = tokensMinted;
lastRunETH = totalETH_MintedToMiners;
}
///
// Based Work Token Minting
///
/// @notice Legacy compatibility function for single nonce mining operations
/// @dev Wrapper that converts single nonce to array format for multi_MintTo function
/// @dev Maintains backward compatibility with standard mining interfaces
/// @param nonce The nonce value that solves the current mining challenge
/// @param challenge_digest The digest parameter (unused but kept for interface compatibility)
/// @return success True if mining operation resulted in token reward (> 0 tokens minted)
/// @custom:compatibility Provides standard mining function interface for miners
/// @custom:delegation Internally delegates to multi_MintTo with single-element nonce array
function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success) {
uint256[] memory nonceArray = new uint256[](1);
nonceArray[0] = nonce;
return multi_MintTo(msg.sender, nonceArray, _BLOCKS_PER_READJUSTMENT, 0) > 0;
}
/// @notice Advanced mining function that processes multiple solutions in a single transaction
/// @dev Allows miners to submit multiple valid nonces at once for improved efficiency and gas optimization
/// @dev Supports batch mining with configurable limits and timing requirements
/// @param mintToAddress The address that will receive the mined tokens (can be different from msg.sender)
/// @param nonce Array of nonce values that solve the current mining challenge
/// @param maxAnswers Maximum number of solutions to process from the nonce array
/// @param minPreviousBlockTimeDifference Minimum time difference required from previous block (timing constraint)
/// @return NumberOfMintsDone The actual number of successful mining operations completed
/// @custom:efficiency Processes multiple solutions in one transaction to reduce gas costs
/// @custom:flexibility Supports delegation by allowing different mint recipient address
/// @custom:batching Can process up to maxAnswers solutions or entire array if maxAnswers is 0
/// @custom:timing May include timing constraints via minPreviousBlockTimeDifference parameter
function multi_MintTo(address mintToAddress, uint256[] memory nonce, uint maxAnswers, uint minPreviousBlockTimeDifference) public payable returns (uint NumberOfMintsDone) {
uint blocktimestampsLocal = block.timestamp;
uint NextEpochCount = blocksToReadjust();
uint xLoop = 0;
uint GoodLoops = 0;
uint prevBlockTime = previousBlockTime;
uint targetTimez = targetTime;
bytes32 localChallengeNumber = challengeNumber;
uint localMiningTarget = miningTarget;
uint miningTargetCloseToAdjustment = localMiningTarget;
for (xLoop = 0; xLoop < nonce.length; xLoop++) {
bytes32 digest = keccak256(abi.encodePacked(localChallengeNumber, msg.sender, nonce[xLoop]));
uint localDigestINT = uint(digest);
uint multiplier_local = localMiningTarget / localDigestINT;
uint compensation = calculateCompensation(multiplier_local);
if(GoodLoops + compensation > maxAnswers) {
compensation = maxAnswers - GoodLoops;
}
if(GoodLoops + compensation >= NextEpochCount) {
compensation = NextEpochCount - GoodLoops;
uint SecPer1Compensation = (blocktimestampsLocal - prevBlockTime) / (NextEpochCount);
if(targetTimez < SecPer1Compensation) {
uint timeMultiplier = SecPer1Compensation / (targetTimez / 2);
uint targetDivisor = targetTimez / (targetTimez / 2);
// First check if result would exceed 2^253
uint MAX_SAFE_VALUE = 1 << 253; // 2^253
// Check if miningTarget * timeMultiplier would overflow
if (timeMultiplier > MAX_SAFE_VALUE / miningTarget) {
// Would overflow, use maximum safe value
miningTargetCloseToAdjustment = MAX_SAFE_VALUE / targetDivisor;
} else {
// Safe to calculate
uint256 product = miningTarget * timeMultiplier;
miningTargetCloseToAdjustment = product / targetDivisor;
}
if(usedCombinations[localChallengeNumber][digest] || localDigestINT >= miningTargetCloseToAdjustment) {
continue;
}
} else if (usedCombinations[localChallengeNumber][digest] || localDigestINT >= localMiningTarget) {
continue;
}
} else if (usedCombinations[localChallengeNumber][digest] || localDigestINT >= localMiningTarget) {
continue;
}
GoodLoops = GoodLoops.add(compensation);
usedCombinations[localChallengeNumber][digest] = true;
if(GoodLoops >= maxAnswers) {
GoodLoops = maxAnswers;
break;
}
if (GoodLoops >= NextEpochCount) {
GoodLoops = NextEpochCount;
break;
}
}
require(GoodLoops > 0, "Must have valid solve in the answers");
uint dif = (blocktimestampsLocal - prevBlockTime) / GoodLoops;
require(minPreviousBlockTimeDifference <= dif, "Not enough Difference in prevBlockTime / GoodLoops, compared to minPreviousBlockTimeDifference function variable");
uint miningDifficultyz = getMiningDifficulty();
uint256 x = ((blocktimestampsLocal - prevBlockTime) / GoodLoops * 888) / targetTimez;
uint ratio = x * 100 / 888;
if(ratio > 100) {
slowBlocks = slowBlocks.add(GoodLoops);
}
( uint B0x_To_Send_User, uint totalETH_To_Send_User, uint totalETH_For_Contract ) = TotalForContract(GoodLoops, NextEpochCount);
totalETH_MintedToMiners = totalETH_MintedToMiners + totalETH_To_Send_User;
if (totalETH_To_Send_User >= totalETH_For_Contract) {
// Case 1: User is net receiving ETH
uint payout = totalETH_To_Send_User - totalETH_For_Contract;
// User gets payout, contract keeps nothing extra
totalETH_To_Send_User = msg.value + payout; // if msg.value > 0, it's just extra refund
} else {
// Case 2: User must contribute ETH
uint required = totalETH_For_Contract - totalETH_To_Send_User;
if (msg.value < required) {
revert(
string(
abi.encodePacked(
"Need to send required ETH. Required: ",
toString(required),
" wei, Sent: ",
toString(msg.value),
" wei"
)
)
);
}
// Contract is satisfied, user might still receive excess if msg.value > required
totalETH_To_Send_User = msg.value - required;
}
_startNewMiningEpoch(NextEpochCount, GoodLoops);
// If max supply for the era will be exceeded next reward round then enter the new era before that happens
// 59 is the final reward era, almost all tokens minted
if(tokensMinted.add(B0x_To_Send_User) > maxSupplyForEra && rewardEra < 59) {
rewardEra = rewardEra + 1;
maxSupplyForEra = _maxTotalSupply - _maxTotalSupply.div(2**(rewardEra + 1));
reward_amount = (50 * 10**18) / (2**(rewardEra));
B0x_To_Send_User = B0x_To_Send_User.div(2);
}
IERC20(B0x_Mining_TOKEN_ADDRESS).transfer(mintToAddress, B0x_To_Send_User);
tokensMinted = tokensMinted.add(B0x_To_Send_User);
previousBlockTime = blocktimestampsLocal;
address payable to = payable(mintToAddress);
to.call{value: totalETH_To_Send_User}("");
emit Mint(msg.sender, B0x_To_Send_User, epochCount, localChallengeNumber);
return GoodLoops;
}
//Remember we are special not like Bitcoin or 0xBitcoin we use 2**253 so it may seem large divide by 2**19 to fix
//Also this only works on last block of the challenge/2016 blocks.
function calcReduceDifficulty(uint prevBlockTime, uint NumberOfCompensation)public view returns (uint miningDifficultyReduced){
uint miningTargetz = calcReduceTarget(prevBlockTime, NumberOfCompensation);
miningDifficultyReduced = _MAXIMUM_TARGET.div(miningTargetz);
return miningDifficultyReduced;
}
//Remember we are special not like Bitcoin or 0xBitcoin we use 2**253 so it may seem large divide by 2**19 to fix
//Also this only works on last block of the challenge/2016 blocks.
function calcReduceTarget(uint prevBlockTime, uint NumberOfCompensation)public view returns (uint miningTargetReduced){
uint targetTimez=targetTime;
uint blockTimestampz = block.timestamp;
uint SecPer1Compensation = (blockTimestampz - prevBlockTime)/(NumberOfCompensation);
if(targetTimez < SecPer1Compensation){
uint timeMultiplier = SecPer1Compensation/(targetTimez/2);
uint targetDivisor = targetTime/(targetTimez/2);
uint MAX_SAFE_VALUE = 1 << 253; // 2^255
// Check if miningTarget * timeMultiplier would overflow
if (timeMultiplier > MAX_SAFE_VALUE / miningTarget) {
// Would overflow, use maximum safe value
return MAX_SAFE_VALUE;
}
// Safe to calculate
uint256 product = miningTarget * timeMultiplier;
return product / targetDivisor;
}
}
///
///// NFT Minting ////
///
/// @notice Mints B0x tokens through standard mining while also transferring NFTs as bonus rewards
/// @dev Performs normal multi_MintTo mining operation and additionally transfers specific NFTs to the miner
/// @dev Can only be called during specific network conditions: near difficulty adjustment with slow block performance
/// @param nftAddresses Array of NFT contract addresses that this contract holds
/// @param nftNumbers Array of specific token IDs that this contract owns and will transfer
/// @param nonces Array of nonce values that solve the current mining challenge
/// @param maxNumberOfAnswersInMint Maximum number of solutions to process in this transaction
/// @return success True if both mining and NFT transfer operations completed successfully
/// @custom:timing-requirements Only available when blocksToReadjust() == 1 (near adjustment)
/// @custom:performance-gate Requires blocksFromReadjust() < 5 and significant slow blocks
/// @custom:slow-block-threshold Needs slowBlocks > _BLOCKS_PER_READJUSTMENT / 8 (poor network performance)
/// @custom:dual-rewards Provides both B0x token mining rewards and NFT bonus rewards
/// @custom:array-validation Requires nftAddresses and nftNumbers arrays to have matching lengths
/// @custom:mining-validation Must successfully complete multi_MintTo operation before NFT transfer
function mintNFT(
address[] memory nftAddresses,
uint[] memory nftNumbers,
uint256[] memory nonces,
uint maxNumberOfAnswersInMint
) public payable returns (bool success) {
require(blocksToReadjust() == 1 && blocksFromReadjust() < 5 && slowBlocks > _BLOCKS_PER_READJUSTMENT / 8, "NFT Adjust Bad");
require(nftAddresses.length == nftNumbers.length, "Array length mismatch");
require(multi_MintTo(msg.sender, nonces, maxNumberOfAnswersInMint, 0) > 0, "mintfailed nft");
// Try each NFT until one succeeds
for (uint i = 0; i < nftAddresses.length; i++) {
address nftaddy = nftAddresses[i];
uint nftNumber = nftNumbers[i];
try IERC165(nftaddy).supportsInterface(0xd9b67a26) returns (bool isERC1155) {
if (isERC1155) {
// Try ERC-1155 transfer
try IERC1155(nftaddy).safeTransferFrom(address(this), msg.sender, nftNumber, 1, "") {
slowBlocks = 0;
return true; // Success!
} catch {
// Continue to next NFT
continue;
}
}
} catch {
// Interface check failed, continue
}
try IERC165(nftaddy).supportsInterface(0x80ac58cd) returns (bool isERC721) {
if (isERC721) {
// Try ERC-721 transfer
try IERC721(nftaddy).safeTransferFrom(address(this), msg.sender, nftNumber, "") {
slowBlocks = 0;
return true; // Success!
} catch {
// Continue to next NFT
continue;
}
}
} catch {
// Interface check failed, continue
}
}
//Allow bad NFT users
return true;
}
/// @notice Calculates the base-2 logarithm of a given number
/// @dev Simple bit-shifting implementation for logarithm calculation
/// @dev Used in compensation calculations for mining difficulty scaling
/// @param x The input value to calculate log2 for
/// @return uint256 The floor of log2(x), returns 0 for x <= 1
function log2(uint256 x) public pure returns (uint256) {
uint256 n = 0;
while (x > 1) {
x >>= 1;
n++;
}
return n;
}
/// @notice Calculates mining compensation based on solution difficulty multiplier
/// @dev Higher multipliers (better solutions) receive exponentially more compensation
/// @dev Uses logarithmic scaling to reward significantly better solutions
/// @param multiplier The difficulty multiplier from the mining solution quality
/// @return uint256 The compensation amount (number of blocks/solutions this counts as)
/// @custom:scaling Returns 1 for multiplier < 4, then log2(multiplier/2) + 1 for higher values
/// @custom:example multiplier=8 gives log2(4)+1=3, multiplier=16 gives log2(8)+1=4
function calculateCompensation(uint256 multiplier) public pure returns (uint256) {
if(multiplier < 4) {
return 1;
}
return log2(multiplier/2) + 1;
}
/// @notice Returns the total amount owed based on current time since last mint
/// @dev Convenience wrapper that calculates owed amount using current block timestamp
/// @return totalOwed The total amount owed based on time elapsed since previousBlockTime
function totalOwedAtCurrentTime() public view returns (uint totalOwed) {
return totalOwedAtTime(block.timestamp - previousBlockTime);
}
/// @notice Calculates total amount owed based on time elapsed since previous mint
/// @dev Uses piecewise function with different formulas for different time ratios
/// @dev Optimized for ratio around 3000 where totalOwed/100000000 ≈ 71.6
/// @param secondsFromPreviousMint Time in seconds since the last successful mint operation
/// @return totalOwed The calculated total amount owed based on elapsed time
/// @custom:formula-low For ratio < 3000: quadratic formula (508606*(15*x²)/888² + 9943920*x/888)
/// @custom:formula-high For ratio >= 3000: linear formula (24*x*5086060/888 + 3456750000)
/// @custom:scaling Uses 888 as scaling factor related to targetTime normalization
function totalOwedAtTime(uint secondsFromPreviousMint) public view returns (uint totalOwed) {
totalOwed = 0;
uint256 x = ((secondsFromPreviousMint) * 888) / targetTime;
uint ratio = x * 100 / 888;
//best @ 3000 ratio totalOwed / 100000000 = 71.6
if(ratio < 3000) {
totalOwed = (508606*(15*x**2)).div(888 ** 2) + (9943920 * (x)).div(888);
} else {
totalOwed = (24*x*5086060).div(888) + 3456750000;
}
return totalOwed;
}
/// @notice Returns the ETH amount to send to user based on current time since last mint
/// @dev Convenience wrapper that calculates ETH distribution using current block timestamp
/// @return totalETHToSendToUser The ETH amount to distribute based on elapsed time since previousBlockTime
function totalETHtoSendUserAtCurrentTime() public view returns (uint totalETHToSendToUser) {
return totalETHtoSendUserAtTime(block.timestamp - previousBlockTime);
}
/// @notice Calculates ETH distribution amount based on time elapsed and system state
/// @dev Uses piecewise calculation similar to totalOwedAtTime with additional ETH-specific scaling
/// @dev ETH distribution depends on give0x flag and uses Token2Per as scaling factor
/// @param secondsFromPreviousMint Time in seconds since the last successful mint operation
/// @return totalETHToSendToUser The calculated ETH amount to distribute to the user
/// @custom:gating Only distributes ETH when give0x > 0 (sufficient contract reserves)
/// @custom:ratio-scaling Different formulas for ratio < 2000 vs >= 2000 (more conservative at high ratios)
/// @custom:scaling-factors Uses Token2Per and totalOwed/100000000 for amount calculations
/// @custom:reserve-dependent Distribution amount scales with give0x multiplier for reserve management
function totalETHtoSendUserAtTime(uint secondsFromPreviousMint) public view returns (uint totalETHToSendToUser) {
uint totalOwed = 0;
uint totalETHtoSendUser = 0;
uint256 x = ((secondsFromPreviousMint) * 888) / targetTime;
uint ratio = x * 100 / 888;
//best @ 3000 ratio totalOwed / 100000000 = 71.6
if(ratio < 3000) {
totalOwed = (508606*(15*x**2)).div(888 ** 2) + (9943920 * (x)).div(888);
} else {
totalOwed = (24*x*5086060).div(888) + 3456750000;
}
if(give0x > 0) {
if(ratio < 2000) {
totalETHtoSendUser = ((totalOwed * Token2Per * give0x).div(100000000));
} else {
totalETHtoSendUser = ((320 * Token2Per * give0x).div(10));
}
}
return totalETHtoSendUser;
}
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2**256 + prod0
uint256 prod0 = a * b; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
require(denominator > prod1);
// Handle non-overflow cases, 256 by 256 division
if (prod1 == 0) {
assembly ("memory-safe") {
result := div(prod0, denominator)
}
return result;
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0]
// Compute remainder using mulmod
uint256 remainder;
assembly ("memory-safe") {
remainder := mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit number
assembly ("memory-safe") {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
uint256 twos = (0 - denominator) & denominator;
// Divide denominator by power of two
assembly ("memory-safe") {
denominator := div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of two
assembly ("memory-safe") {
prod0 := div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need
// to flip `twos` such that it is 2**256 / twos.
// If twos is zero, then it becomes one
assembly ("memory-safe") {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
// Invert denominator mod 2**256
// Now that denominator is an odd number, it has an inverse
// modulo 2**256 such that denominator * inv = 1 mod 2**256.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, denominator * inv = 1 mod 2**4
uint256 inv = (3 * denominator) ^ 2;
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv *= 2 - denominator * inv; // inverse mod 2**8
inv *= 2 - denominator * inv; // inverse mod 2**16
inv *= 2 - denominator * inv; // inverse mod 2**32
inv *= 2 - denominator * inv; // inverse mod 2**64
inv *= 2 - denominator * inv; // inverse mod 2**128
inv *= 2 - denominator * inv; // inverse mod 2**256
// Because the division is now exact we can divide by multiplying
// with the modular inverse of denominator. This will give us the
// correct result modulo 2**256. Since the preconditions guarantee
// that the outcome is less than 2**256, this is the final result.
// We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inv;
return result;
}
}
/// @notice Retrieves the current ETH price with maximum precision using FullMath library
/// @dev Most precise method for ETH price calculation, recommended for accurate price feeds
/// @dev Uses Uniswap V3 pool data to calculate current ETH/USDC price with full precision
/// @return price ETH price multiplied by 10^22 for maximum precision (10^12 for USDC decimals + 10^10 for precision)
/// @custom:precision Returns price scaled by 10^22 to maintain full decimal precision
/// @custom:decimals Accounts for USDC's 6 decimal places with additional 10^16 scaling for precision
/// @custom:library Uses FullMath library for overflow-safe arithmetic operations
/// @custom:source Queries live Uniswap V3 ETH/USDC pool for real-time pricing data
function getETHPricePrecise() public view returns (uint256 price) {
return 4498799707501163;
//Fix return for now until mainnet then remove!
IUniswapV3Pool pool = IUniswapV3Pool(POOL_ADDRESS);
(uint160 sqrtPriceX96, , , , , , ) = pool.slot0();
// Calculate price = (sqrtPriceX96)^2 * 10^22 / 2^192
// Using mulDiv to handle large numbers safely
if (sqrtPriceX96 <= type(uint128).max) {
// Safe to square without overflow
uint256 priceX192 = uint256(sqrtPriceX96) * sqrtPriceX96;
return (priceX192 * 1e24) >> 192;
} else {
// Use FullMath.mulDiv for large numbers
// You'll need to import @uniswap/v3-core/contracts/libraries/FullMath.sol
uint256 priceX128 = mulDiv(sqrtPriceX96, sqrtPriceX96, 1 << 64);
return mulDiv(priceX128, 1e24, 1 << 128);
}
}
/// @notice Calculates comprehensive mining results including B0x tokens, ETH flows, and current ETH price
/// @dev Simulates mining operation results without executing the actual mining transaction, at current previousblockTime
/// @dev Handles both regular mining and difficulty adjustment scenarios with different calculations
/// @param compensation The mining compensation multiplier based on solution quality
/// @return B0xYouGet Amount of B0x tokens the miner would receive
/// @return ETHYouGet Amount of ETH the miner would receive (if any)
/// @return ETHyouSpend Amount of ETH the miner would need to send (if any)
/// @return ETHPrice Current ETH price with maximum precision (scaled by 10^22)
/// @return secondsFromPreviousMintreturn Time elapsed since last mint operation
/// @custom:simulation Provides preview of mining results without state changes
/// @custom:difficulty-aware Adjusts calculations based on proximity to difficulty adjustment
/// @custom:price-floor Enforces minimum ETH price per token (minAmountETH)
/// @custom:overflow-safe Uses safe arithmetic to prevent overflow in difficulty calculations
function TotalTotalsAndETHpriceAndCurrentMintTime(uint compensation)
public
view
returns (
uint B0xYouGet,
uint ETHYouGet,
uint ETHyouSpend,
uint ETHPrice,
uint secondsFromPreviousMintreturn
) {
uint secondsFromPreviousMint = block.timestamp - previousBlockTime;
secondsFromPreviousMintreturn = secondsFromPreviousMint;
ETHPrice = getETHPricePrecise();
( B0xYouGet, ETHYouGet, ETHyouSpend) = TotalForContract(compensation, blocksToReadjust());
}
/// @notice Calculates comprehensive mining results including B0x tokens, ETH flows, and current ETH price
/// @dev Simulates mining operation results without executing the actual mining transaction, at current previousblockTime
/// @dev Handles both regular mining and difficulty adjustment scenarios with different calculations
/// @param compensation The mining compensation multiplier based on solution quality
/// @param blocksToReadjustMENT BlocksToReadjustment
/// @return B0xYouGet Amount of B0x tokens the miner would receive
/// @return ETHYouGet Amount of ETH the miner would receive (if any)
/// @return ETHyouSpend Amount of ETH the miner would need to send (if any)
/// @custom:simulation Provides preview of mining results without state changes
/// @custom:difficulty-aware Adjusts calculations based on proximity to difficulty adjustment
/// @custom:price-floor Enforces minimum ETH price per token (minAmountETH)
/// @custom:overflow-safe Uses safe arithmetic to prevent overflow in difficulty calculations
function TotalForContract(uint compensation, uint blocksToReadjustMENT)
public
view
returns (
uint B0xYouGet,
uint ETHYouGet,
uint ETHyouSpend
) {
uint miningDiffz = getMiningDifficulty();
uint blkzToAdjustment = blocksToReadjustMENT;
uint secondsFromPreviousMint = block.timestamp - previousBlockTime;
// Prevent division by zero
require(compensation > 0, "Compensation must be greater than 0");
uint totalETH_To_Send_User = compensation * totalETHtoSendUserAtTime(secondsFromPreviousMint / compensation);
uint miningTargetCloseToAdjustment = miningTarget;
if (compensation >= blkzToAdjustment) {
uint SecPer1Compensation = (block.timestamp - previousBlockTime) / (blkzToAdjustment);
if(targetTime < SecPer1Compensation) {
uint timeMultiplier = SecPer1Compensation / (targetTime / 2);
uint targetDivisor = targetTime / (targetTime / 2);
// First check if result would exceed 2^253
uint MAX_SAFE_VALUE = 1 << 253; // 2^253
miningTargetCloseToAdjustment = 0;
// Check if miningTarget * timeMultiplier would overflow
if (timeMultiplier > MAX_SAFE_VALUE / miningTarget) {
// Would overflow, use maximum safe value
miningTargetCloseToAdjustment = MAX_SAFE_VALUE;
} else {
// Safe to calculate
uint256 product = miningTarget * timeMultiplier;
miningTargetCloseToAdjustment = product / targetDivisor;
}
}
uint miningDiffForAdjustment = _MAXIMUM_TARGET.div(miningTargetCloseToAdjustment);
B0xYouGet = totalB0xToSendAtTime(secondsFromPreviousMint / blkzToAdjustment, 1);
ETHyouSpend = totalETHowedAtTime(secondsFromPreviousMint / blkzToAdjustment, miningDiffForAdjustment, 1);
B0xYouGet = B0xYouGet + (blkzToAdjustment - 1) * totalB0xToSendAtTime(secondsFromPreviousMint / blkzToAdjustment, blkzToAdjustment);
ETHyouSpend = ETHyouSpend + (blkzToAdjustment - 1) * totalETHowedAtTime(secondsFromPreviousMint / blkzToAdjustment, miningDiffz, blkzToAdjustment);
if (B0xYouGet != 0) {
uint local_minAmountETH = (ETHyouSpend * 1e18) / B0xYouGet;
if (local_minAmountETH < minAmountETH) {
ETHyouSpend = (minAmountETH * B0xYouGet) / 1e18;
}
}
} else {
B0xYouGet = compensation * totalB0xToSendAtTime(secondsFromPreviousMint / compensation, compensation);
ETHYouGet = compensation * totalETHtoSendUserAtTime(secondsFromPreviousMint / compensation);
ETHyouSpend = compensation * totalETHowedAtTime(secondsFromPreviousMint / compensation, miningDiffz, compensation);
if (B0xYouGet != 0) {
uint local_minAmountETH = (ETHyouSpend * 1e18) / B0xYouGet;
if (local_minAmountETH < minAmountETH) {
ETHyouSpend = (minAmountETH * B0xYouGet) / 1e18;
}
}
}
}
/// @notice Calculates the total B0x tokens to reward a miner based on timing and adjustment context
/// @dev Determines token reward amount using current reward era and timing-based scaling
/// @dev Provides the core token reward calculation for successful mining operations
/// @param secondsFromPreviousMint Time elapsed since last mining operation in seconds
/// @param blocksToAdjust Number of blocks remaining until next difficulty adjustment
/// @return totalB0xToSendToUser The amount of B0x tokens to reward the miner
/// @custom:reward-era Uses current rewardEra to determine base reward amount (50 / 2^rewardEra)
/// @custom:timing-based Reward amount may scale based on time elapsed since previous mint
/// @custom:adjustment-context Uses blocksToAdjust for reward calculation context
/// @custom:halving-compatible Works with Bitcoin-style reward halving mechanism
function totalB0xToSendAtTime(uint secondsFromPreviousMint, uint blocksToAdjust) public view returns (uint totalB0xToSendToUser) {
totalB0xToSendToUser = reward_amount;
// Calculate adjustment factor (using 1000 as fixed point multiplier)
uint256 adjustmentFactor = (secondsFromPreviousMint * 1000) / targetTime;
if (blocksToAdjust != 1 && adjustmentFactor > 1000) {
adjustmentFactor = 1000; // Cap at at 1x normal fees
}else if (adjustmentFactor < 250){
adjustmentFactor = 250;
}else if ( blocksToAdjust == 1 && adjustmentFactor > 2000){ //max 2x unless targertTimezMulti =>4 then up to 16x
uint TimeSinceLastDifficultyPeriod2 = block.timestamp - latestDifficultyPeriodStarted2 + 1;
uint epochTotal = (epochCount) - epochOld; //calculated after startNewMiningEpoch
if(epochTotal == 0){
epochTotal = epochTotal + 1;
}
uint totalTimePerEpoch = TimeSinceLastDifficultyPeriod2 / epochTotal;
uint targetTimezMulti = totalTimePerEpoch / targetTime;
if(targetTimezMulti < 4){
adjustmentFactor = 2000;
}else if(adjustmentFactor > 4000 && targetTimezMulti >= 4){
adjustmentFactor = 4000;
}
}
totalB0xToSendToUser = (totalB0xToSendToUser*adjustmentFactor )/ 1000;
}
/// @notice Adjusts ETH payment required from miners based on mining difficulty
/// @dev Uses 0xBTC difficulty standards with 524,288 normalization factor
/// @dev Implements anti-FPGA measures by requiring higher ETH payments at higher difficulties
/// @param reward The base ETH payment amount that needs adjustment
/// @param difficulty The current mining difficulty (0xBTC standard)
/// @return uint256 The adjusted ETH amount that miners must send
/// @custom:scaling Uses bit shifting for gas-efficient multiplication/division operations
/// @custom:anti-fpga Higher ETH payments required at higher difficulties to discourage FPGA farming
/// @custom:difficulty-tiers Progressive scaling from reduced payments at low difficulty to high payments at extreme difficulty
/// @custom:economic-barrier Higher difficulties require more ETH payment, lower difficulties require less
function adjustETHtoSendByDifficulty(uint256 reward, uint256 difficulty) internal pure returns (uint256) {
// 524_288 divide by this because we are using 0xBTC difficulty standards
// 3.2 Million = 31 Gh/s
// 3 million = 1 FPGA so make it best since we dont want FPGA make this the best era
if (difficulty < 1) return reward >> 8; // divide by 256 (much less payment required)
if (difficulty < 2) return reward >> 7; // divide by 128 (less payment required)
if (difficulty < 10) return reward >> 6; // divide by 64 (less payment required)
if (difficulty < 100) return reward >> 5; // divide by 32 (less payment required)
if (difficulty < 1000) return reward >> 4; // divide by 16 (less payment required)
if (difficulty < 25_000) return reward >> 3; // divide by 8 (less payment required)
if (difficulty < 50_000) return reward >> 2; // divide by 4 (less payment required)
if (difficulty < 125_000) return reward >> 1; // divide by 2 (less payment required)
if (difficulty < 250_000) return reward * 1/2; // multiply by 1/2 (less payment required)
if (difficulty < 500_000) return (reward * 2) / 3; // multiply by 2/3 (less payment required)
if (difficulty < 1_000_000) return reward; // base payment amount
if (difficulty < 3_000_000) return (reward * 3) / 2; // multiply by 3/2 (50% more payment required)
if (difficulty < 10_000_000) return reward << 1; // multiply by 2 (2x more payment required)
if (difficulty < 20_000_000) return reward << 2; // multiply by 4 (4x more payment required)
if (difficulty < 50_000_000) return reward << 3; // multiply by 8 (8x more payment required)
if (difficulty < 100_000_000) return reward << 4; // multiply by 16 (16x more payment required)
if (difficulty < 250_000_000) return reward << 5; // multiply by 32 (32x more payment required)
if (difficulty < 500_000_000) return reward << 6; // multiply by 64 (64x more payment required)
if (difficulty < 1_000_000_000) return reward << 7; // multiply by 128 (128x more payment required) // 8.65 Th/s or 8650 Gh/s or 330 FPGAs or at 5000$ 6.4$ for rewardAmount minimum or 6.4*4 = 25.6$ for rewardAmount/4
if (difficulty < 2_000_000_000) return reward << 8; // multiply by 256 (256x more payment required)
if (difficulty < 3_000_000_000) return reward << 9; // multiply by 512 (512x more payment required)
if (difficulty < 5_000_000_000) return reward << 10; // multiply by 1024 (1024x more payment required)
return reward * (difficulty / 5_000_000); // dynamic multiplier for extreme difficulties
}
/// @notice Calculates the total ETH amount a miner must send based on mining parameters
/// @dev Combines time-based calculation with difficulty-based adjustment to determine ETH payment
/// @dev Uses both timing penalties and difficulty scaling to calculate required ETH payment
/// @param secondsFromPreviousMint Time elapsed since last mining operation in seconds
/// @param miningDiff Current mining difficulty (0xBTC standard, ~difficulty/524,288)
/// @param blocksToAdjust Number of blocks remaining until next difficulty adjustment
/// @return totalETHNeeded The total ETH amount the miner must send with their transaction
/// @custom:time-based Uses secondsFromPreviousMint to calculate base ETH amount owed
/// @custom:difficulty-scaling Applies adjustETHtoSendByDifficulty() to scale payment by mining difficulty
/// @custom:economic-balance Higher difficulty = higher payment, longer time = higher payment
/// @custom:anti-fpga Higher difficulties require exponentially more ETH to discourage industrial mining
function totalETHowedAtTime(uint secondsFromPreviousMint, uint miningDiff, uint blocksToAdjust) public view returns (uint totalETHNeeded) {
uint ETHtoSendContract = 0.00001 ether; //0.00001 ETH = 0.045$ the avg expected cost of Layer 2 tx in the future.
//524_288 difference between uint public MAXIMUMTARGET = 2**234; and my new maximum target is uint public constant _MAXIMUM_TARGET = 2**253; 2^19 = 524288
uint ETHuserMUSTsendContract = adjustETHtoSendByDifficulty(ETHtoSendContract, miningDiff / 524_288);
// Calculate adjustment factor (using 1000 as fixed point multiplier)
uint256 adjustmentFactor = 4000;
if(secondsFromPreviousMint != 0){
adjustmentFactor = (targetTime * 1000) / secondsFromPreviousMint;
}
if (adjustmentFactor > 4000 ) {
adjustmentFactor = 4000; // Cap at 4x as much ETH
}
//zkBTC terms of difficulty must adjust by dividing by 524_288
if(adjustmentFactor < 1000 && blocksToAdjust != 1) {
adjustmentFactor = 1000; // Cap at 4x less eth (1000/4 = 250)
}else if( blocksToAdjust == 1 && adjustmentFactor < 500){// cap at 2x unless Target Time >= 4x
uint TimeSinceLastDifficultyPeriod2 = block.timestamp - latestDifficultyPeriodStarted2 + 1;
uint epochTotal = epochCount - epochOld;
if(epochTotal == 0){
epochTotal = 1;
}
uint totalTimePerEpoch = TimeSinceLastDifficultyPeriod2 / epochTotal;
uint targetTimezMulti = totalTimePerEpoch / targetTime;
if(targetTimezMulti < 4 && adjustmentFactor < 500){
adjustmentFactor = 500; // 1000/2= 125 so 8x less ETH needed max if not adjustment factored
}else if(adjustmentFactor < 250 && targetTimezMulti >= 4){
adjustmentFactor = 250; // 1000/33.30= 30 so 33.3x less ETH needed max
}
}
//If Its 4x Faster charge 4x More, if its 4x Slower charge 4x less
totalETHNeeded = (ETHuserMUSTsendContract * adjustmentFactor) / 1000;
return totalETHNeeded;
}
/// @notice Advanced mining function that distributes multiple token types based on epoch-based unlock system
/// @dev Performs standard mining while also distributing accumulated tokens from contract's inventory
/// @dev Uses epoch-based power-of-2 unlocking system (epoch 2=1 token, epoch 4=2 tokens, epoch 8=3 tokens, etc.)
/// @param nonce Array of valid nonces for mining solutions
/// @param ExtraFunds Array of token contract addresses to distribute (must not include main B0x token)
/// @param MintTo Array of recipient addresses (length must be ExtraFunds.length + 1, first is for main rewards)
/// @param maxNumberOfSolutions Maximum number of mining solutions to process
/// @param minBlockTimeDifferencePerSolve Minimum time difference required per solution
/// @return owed The total amount owed based on mining time calculations
/// @custom:epoch-unlocking Tokens unlock based on epoch count divisibility by powers of 2
/// @custom:distribution-logic epoch % 2^(n+1) == 0 determines which tokens get distributed
/// @custom:array-relationship MintTo.length must equal ExtraFunds.length + 1 (first address gets main rewards)
/// @custom:token-validation Prevents minting of the main B0x token through ExtraFunds array
/// @custom:batch-transfers Accumulates all transfers and executes them at once for gas efficiency
function mintTokensArrayTo(
uint256[] memory nonce,
address[] memory ExtraFunds,
address[] memory MintTo,
uint maxNumberOfSolutions,
uint minBlockTimeDifferencePerSolve
) public payable returns (uint256 owed) {
// MintTo is 1+ExtraFunds.length so always 1 more than ExtraFunds is MintTo, because first mintTo is for the main rewards.
// Nonce is an array of uint256 nonces that are valid, it will try all
uint prevBlockTimez = previousBlockTime;
uint NumberofMints = multi_MintTo(MintTo[0], nonce, maxNumberOfSolutions, minBlockTimeDifferencePerSolve);
uint totalOd = totalOwedAtTime(((block.timestamp - prevBlockTimez) / NumberofMints));
uint local_epochCount = epochCount;
uint MAXmaxMax = 0;
if(totalOd == 0) {
return 0;
}
require(MintTo.length == ExtraFunds.length + 1, "MintTo has to have an extra address compared to ExtraFunds");
address B0x = B0x_Mining_TOKEN_ADDRESS;
uint xy = 0;
uint256[] memory balances = new uint256[](ExtraFunds.length);
// Validate that ExtraFunds doesn't contain the main B0x token
for(uint z = 0; z < ExtraFunds.length; z++) {
require(ExtraFunds[z] != B0x, "Not allowed to ERC20 mint Main Token");
}
// Process each mint and calculate token distributions
for(uint xzzzz = 0; xzzzz < NumberofMints; xzzzz++) {
// Determine how many tokens are unlocked for this epoch
for(xy = 0; xy < ExtraFunds.length; xy++) {
if(local_epochCount % (2**(xy + 1)) != 0) {
break;
}
// Validate no duplicate tokens in the array
for(uint y = xy + 1; y < ExtraFunds.length; y++) {
require(ExtraFunds[y] != ExtraFunds[xy], "No printing The same tokens");
}
}
if(xy == 0) {
continue;
}
if(MAXmaxMax < xy) {
MAXmaxMax = xy;
}
uint256 totalOwed = 0;
uint256 TotalOwned = 0;
// Calculate and accumulate token distributions
for(uint x = 0; x < xy && x < ExtraFunds.length; x++) {
// Epoch count must be evenly divisible by 2^n in order to get extra mints
// ex. epoch 2 = 1 extramint, epoch 4 = 2 extra, epoch 8 = 3 extra mints, ..., epoch 32 = 5 extra mints
if(local_epochCount % (2**(x + 1)) == 0) {
address tokenAddress = ExtraFunds[x];
// Use low-level call to get token balance
(bool success, bytes memory data) = tokenAddress.staticcall(
abi.encodeWithSignature("balanceOf(address)", address(this))
);
if (success && data.length >= 32) {
TotalOwned = abi.decode(data, (uint256));
} else {
TotalOwned = 0;
}
if(TotalOwned != 0) {
// Special rounding for certain conditions
if(x % 3 == 0 && x != 0 && totalOd > 17600000) {
totalOwed = (TotalOwned * totalOd).divRound(2**x * 100000000 * 20000);
} else {
totalOwed = (TotalOwned * totalOd).div(2**x * 100000000 * 20000);
}
balances[x] = balances[x] + totalOwed;
}
}
}
local_epochCount = local_epochCount - 1;
}
// Execute all accumulated transfers at once
for(uint i = 0; i < MAXmaxMax && i < ExtraFunds.length; i++) {
address tokenAddress = ExtraFunds[i];
uint256 amount = balances[i];
if(amount > 0) {
IERC20(tokenAddress).transfer(AddressLPReward, amount);
IERC20(tokenAddress).transfer(MintTo[i + 1], amount);
}
}
emit MegaMint(msg.sender, epochCount, challengeNumber, MAXmaxMax, totalOd);
return totalOd;
}
/// @notice Convenience wrapper for mintTokensArrayTo that sends all tokens to the same recipient
/// @dev Creates an array of identical addresses and delegates to mintTokensArrayTo for processing
/// @dev Simplifies multi-token mining when all rewards should go to a single address
/// @param nonce Array of valid nonces for mining solutions
/// @param ExtraFunds Array of token contract addresses to distribute (including main B0x token)
/// @param MintTo Single recipient address that will receive all token rewards
/// @param MaxAnswersInOneSubmit Maximum number of mining solutions to process
/// @param minBlockTimeDifferencePerSolve Minimum time difference required per solution
/// @return success Always returns true if the operation completes without reverting
/// @custom:convenience-wrapper Eliminates need to manually create recipient address arrays
/// @custom:single-recipient All token rewards (main + extra) go to the same address
/// @custom:array-creation Dynamically creates MintTo array with length ExtraFunds.length + 1
/// @custom:delegation Forwards all actual processing to mintTokensArrayTo function
function mintTokensSameAddress(
uint256[] memory nonce,
address[] memory ExtraFunds,
address MintTo,
uint MaxAnswersInOneSubmit,
uint minBlockTimeDifferencePerSolve
) public payable returns (bool success) {
// MintTo is 1+ExtraFunds.length so always 1 more than ExtraFunds is MintTo, because first mintTo is for the main rewards.
address[] memory dd = new address[](ExtraFunds.length + 1);
for(uint x = 0; x < (ExtraFunds.length + 1); x++) {
dd[x] = MintTo;
}
mintTokensArrayTo(nonce, ExtraFunds, dd, MaxAnswersInOneSubmit, minBlockTimeDifferencePerSolve);
return true;
}
/// @notice Returns the time elapsed since the last successful mining operation
/// @dev Simple utility function for calculating time differences in mining operations
/// @return time Time in seconds since previousBlockTime
function timeFromLastSolve() public view returns (uint256 time) {
time = block.timestamp - previousBlockTime;
return time;
}
function rewardAtTimeERC20(uint256 timeDifference, address[] memory tokens, uint epochCountStart, uint epochCountEnd) public view returns (uint256[] memory) {
uint numberOfMints = epochCountEnd - epochCountStart;
uint totalOwed = totalOwedAtTime(((timeDifference) / numberOfMints));
uint256 TotalOwned;
uint256[] memory balances = new uint256[](tokens.length);
// Validate no duplicate tokens
for(uint xy =0; xy< tokens.length; xy++){
for(uint y = xy + 1; y < tokens.length; y++) {
require(tokens[y] != tokens[xy], "No same tokens");
}
}
// Process each mint operation
for(uint f = 0; f < numberOfMints; f++) {
for(uint z = 0; z < tokens.length; z++) {
uint totalToSend = 0;
// Epoch count must be evenly divisible by 2^n in order to get extra mints
// ex. epoch 2 = 1 extramint, epoch 4 = 2 extra, epoch 8 = 3 extra mints, epoch 16 = 4 extra mints
if((epochCountEnd - f) % (2**(z + 1)) == 0) {
TotalOwned = IERC20(tokens[z]).balanceOf(address(this));
if(TotalOwned != 0) {
// Special rounding for certain conditions (every 3rd token with high totalOwed)
if(z % 3 == 0 && z != 0 && totalOwed > 17600000) {
totalToSend = ((2** rewardEra) * TotalOwned * totalOwed).divRound(2**z * 100000000 * 20000);
} else {
totalToSend = ((2** rewardEra) * TotalOwned * totalOwed).div(2**z * 100000000 * 20000);
}
balances[z] = balances[z] + totalToSend;
}
}
}
}
return balances;
}
/// @notice Returns the number of blocks mined since the last difficulty adjustment
/// @dev Simple calculation of blocks completed in current difficulty period
/// @return blocks Number of epochs mined since last difficulty readjustment
function blocksFromReadjust() public view returns (uint256 blocks) {
blocks = (epochCount - epochOld);
return blocks;
}
/// @notice Calculates how many blocks remain until the next difficulty adjustment
/// @dev Complex logic that can trigger early adjustments based on timing and block count conditions
/// @dev Uses multiple factors: time elapsed, blocks mined, and performance thresholds
/// @return blocks Number of blocks remaining until difficulty adjustment (1 if conditions met for immediate adjustment)
/// @custom:early-adjustment Can return 1 block when timing/performance conditions are met
/// @custom:timing-based Uses 4x target time threshold and minimum block count for early adjustment
/// @custom:performance-gate Requires at least _BLOCKS_PER_READJUSTMENT/8 blocks for early adjustment
/// @custom:standard-calculation Returns normal remainder calculation when early conditions not met
function blocksToReadjust() public view returns (uint blocks) {
uint256 blktimestamp = block.timestamp;
uint local_BLOCKS_PER_READJUSTMENT = _BLOCKS_PER_READJUSTMENT;
uint localEpochCount = epochCount;
uint localEpochOld = epochOld;
uint TimeSinceLastDifficultyPeriod2 = blktimestamp - latestDifficultyPeriodStarted2;
uint adjusDiffTargetTime = targetTime * (localEpochCount - localEpochOld);
uint adjusDiffTime = targetTime * local_BLOCKS_PER_READJUSTMENT;
uint adjustFinal = 4 * adjusDiffTargetTime;
uint epochCOUNTS = localEpochCount - localEpochOld;
// If we are 256 blocks (2016/(4*2) = 256) AND at least average 1.5x slowtime on blocks adjust
// OR if we are past our Difficulty period (aka slow mining)
if((TimeSinceLastDifficultyPeriod2 > adjustFinal && epochCOUNTS > local_BLOCKS_PER_READJUSTMENT / (8)) ||
(adjusDiffTime < TimeSinceLastDifficultyPeriod2)) {
// Complicated math not needed if only moving 1 block
blocks = 1;
return (blocks);
} else {
blocks = local_BLOCKS_PER_READJUSTMENT - ((localEpochCount - localEpochOld) % local_BLOCKS_PER_READJUSTMENT);
return (blocks);
}
}
/// @notice Calculates the time in seconds until difficulty adjustment conditions will be met
/// @dev Mirrors the logic from blocksToReadjust() to determine when adjustment switch will occur
/// @dev Returns 0 if adjustment conditions are already met (blocksToReadjust() would return 1)
/// @return secs Time in seconds until adjustment conditions trigger, or 0 if already triggered
/// @custom:condition-matching Exactly mirrors the dual condition logic from blocksbToReadjust()
/// @custom:timing-prediction Calculates when either slow mining or 4x time conditions will be met
/// @custom:block-threshold Considers minimum block requirement (252 blocks) for timing-based adjustment
/// @custom:immediate-check Returns 0 if adjustment conditions are already satisfied
function seconds_Until_adjustmentSwitch() public view returns (uint secs) {
uint256 blktimestamp = block.timestamp;
uint256 local_BLOCKS_PER_READJUSTMENT = _BLOCKS_PER_READJUSTMENT;
uint256 localEpochCount = epochCount;
uint256 localEpochOld = epochOld;
uint256 TimeSinceLastDifficultyPeriod2 = blktimestamp - latestDifficultyPeriodStarted2;
uint256 epochCOUNTS = localEpochCount - localEpochOld;
uint256 adjusDiffTime = targetTime * local_BLOCKS_PER_READJUSTMENT;
// Make this calculation match blocksToReadjust() exactly
uint256 adjusDiffTargetTime = targetTime * epochCOUNTS;
uint256 adjustFinal = 4 * adjusDiffTargetTime;
uint256 minBlocksRequired = local_BLOCKS_PER_READJUSTMENT / (8);
// Check if we're already in adjustment mode (blocks = 1)
if ((TimeSinceLastDifficultyPeriod2 > adjustFinal && epochCOUNTS > minBlocksRequired) ||
(adjusDiffTime < TimeSinceLastDifficultyPeriod2)) {
return 0; // Already in adjustment mode
}
// Calculate time until we hit the adjustment conditions
// Time until we hit the "slow mining" condition
int timeUntilSlowCondition = int(latestDifficultyPeriodStarted2) + int(adjusDiffTime) - int(blktimestamp);
// Time until we hit the "1.5x slow time" condition - only relevant if we have enough blocks
int minTime = timeUntilSlowCondition;
if (epochCOUNTS > minBlocksRequired) {
int timeUntilSlowTimeCondition = int(latestDifficultyPeriodStarted2) + int(adjustFinal) - int(blktimestamp);
// Only consider this condition if we have enough blocks
if (timeUntilSlowTimeCondition > 0 && (timeUntilSlowTimeCondition < minTime || minTime <= 0)) {
minTime = timeUntilSlowTimeCondition;
}
}
// If epochCOUNTS <= minBlocksRequired, we only care about timeUntilSlowCondition
if (minTime <= 0) {
return 0;
}
return uint(minTime);
}
/// @notice Initiates a new mining epoch and handles difficulty adjustments when conditions are met
/// @dev Internal function that manages epoch transitions, reward distribution, and challenge generation
/// @dev Triggers difficulty adjustment and reward distribution when full epoch completed
/// @param blocksToAdjust Number of blocks remaining until next difficulty adjustment
/// @param blocksMined Number of blocks successfully mined in this operation
/// @custom:epoch-completion Triggers full adjustment cycle when blocksMined >= blocksToAdjust
/// @custom:quarter-milestones Sends rewards to Liquidity Providers at 25%, 50%, and 75% completion points of difficulty period
/// @custom:challenge-generation Creates new challenges using previous block hash and current challenge
/// @custom:usage-limits Prevents challenge reuse with maximum 3 uses per base challenge
function _startNewMiningEpoch(uint blocksToAdjust, uint blocksMined) internal {
uint local_BLOCKS_PER_READJUSTMENT = _BLOCKS_PER_READJUSTMENT;
uint nextEpoch = blocksToAdjust;
uint epochsz = blocksMined;
uint localEpochCount = epochCount;
uint blocksToReadjust_local = nextEpoch;
if(epochsz >= blocksToReadjust_local) {
epochsz = blocksToReadjust_local;
epochCount = localEpochCount.add(epochsz);
if(_maxTotalSupply < tokensMinted) {
reward_amount = 0;
}
ARewardSender();
_reAdjustDifficulty();
bytes32 localChallenge2 = blockhash(block.number - 1);
bytes32 localChallenge_advanced = bytes32(keccak256(abi.encodePacked(localChallenge2, challengeNumber)));
require(usedChallenges[localChallenge_advanced] == false, "used Chal before");
usedChallenges[localChallenge_advanced] = true;
challengeNumber = localChallenge_advanced;
uint maxAmountOfChallengeUses = usedChallengesNumber[localChallenge2] + 1;
usedChallengesNumber[localChallenge2] = maxAmountOfChallengeUses;
require(maxAmountOfChallengeUses <= 3, "Max 3 times");
} else {
// Check if we've crossed a quarter milestone
// Calculate how many blocks we've mined so far in this readjustment period
uint blocksSoFar = local_BLOCKS_PER_READJUSTMENT - blocksToReadjust_local + epochsz;
// Calculate quarter milestones
uint quarter1 = local_BLOCKS_PER_READJUSTMENT / 4;
uint quarter2 = local_BLOCKS_PER_READJUSTMENT / 2;
uint quarter3 = (local_BLOCKS_PER_READJUSTMENT * 3) / 4;
// Check if we've just crossed a quarter milestone
uint blocksBeforeThisMining = blocksSoFar - epochsz;
epochCount = localEpochCount.add(epochsz);
if ((blocksBeforeThisMining < quarter1 && blocksSoFar >= quarter1) ||
(blocksBeforeThisMining < quarter2 && blocksSoFar >= quarter2) ||
(blocksBeforeThisMining < quarter3 && blocksSoFar >= quarter3)) {
ARewardSender();
}
}
}
/// @notice Adjusts mining difficulty based on time taken to mine recent blocks
/// @dev Internal function that implements Bitcoin-style difficulty adjustment with 4x caps
/// @dev Uses actual time elapsed vs target time to calculate adjustment factor
/// @custom:bitcoin-style Implements 4x maximum adjustment in either direction per period
/// @custom:time-based Uses elapsed time vs target time to determine if mining is too fast/slow
/// @custom:overflow-protection Uses mulDiv for safe arithmetic and prevents target overflow
/// @custom:bounds-enforcement Ensures mining target stays within _MINIMUM_TARGET and _MAXIMUM_TARGET
function _reAdjustDifficulty() internal {
uint256 blktimestamp = block.timestamp;
uint TimeSinceLastDifficultyPeriod2 = blktimestamp - latestDifficultyPeriodStarted2+1;
uint epochTotal = epochCount - epochOld;
uint adjusDiffTargetTime = targetTime * epochTotal;
epochOld = epochCount;
// Calculate adjustment factor (using 1000 as fixed point multiplier)
uint256 adjustmentFactor = (TimeSinceLastDifficultyPeriod2 * 1000) / adjusDiffTargetTime;
// Apply Bitcoin's 4x cap in both directions
if (adjustmentFactor > 4000) {
adjustmentFactor = 4000; // Cap at 4x easier
}
if (adjustmentFactor < 250) {
adjustmentFactor = 250; // Cap at 4x harder (1000/4 = 250)
}
// Check if the result would exceed uint256 max
// Rearrange: (miningTarget * adjustmentFactor) / 1000 <= type(uint256).max
// To: miningTarget * adjustmentFactor <= type(uint256).max * 1000
// To: miningTarget <= (type(uint256).max * 1000) / adjustmentFactor
uint256 maxAllowedMiningTarget = mulDiv(_MAXIMUM_TARGET, 1000, adjustmentFactor);
if (miningTarget > maxAllowedMiningTarget) {
miningTarget = _MAXIMUM_TARGET; // Handle overflow by using maximum target
} else {
miningTarget = mulDiv(miningTarget, adjustmentFactor, 1000);
}
// Apply the adjustment to the target
// If blocks are coming in 4x slower (adjustmentFactor = 4000), make it 4x easier
// If blocks are coming in 4x faster (adjustmentFactor = 250), make it 4x harder
require(latestDifficultyPeriodStarted2 != blktimestamp, "No same block");
latestDifficultyPeriodStarted2 = blktimestamp;
latestDifficultyPeriodStarted = block.number;
if(miningTarget < _MINIMUM_TARGET) { // Very difficult
miningTarget = _MINIMUM_TARGET;
}
if(miningTarget > _MAXIMUM_TARGET) { // Very easy
miningTarget = _MAXIMUM_TARGET;
}
}
/// @notice Calculates what the mining difficulty would be after the next adjustment
/// @dev Simulates the difficulty adjustment calculation without actually changing state
/// @dev Uses current time + 1 second and epochCount + 1 to predict next adjustment
/// @return newDifficulty The predicted difficulty value after next adjustment
/// @custom:prediction-logic Simulates _reAdjustDifficulty() calculation with incremented values
/// @custom:bitcoin-caps Applies same 4x maximum adjustment limits as actual adjustment
/// @custom:time-simulation Adds 1 second to current time and 1 to epoch count for prediction
/// @custom:bounds-checking Enforces same minimum and maximum target limits
function readjustsToWhatDifficulty() public view returns (uint newDifficulty) {
uint256 blktimestamp = block.timestamp;
uint TimeSinceLastDifficultyPeriod2 = blktimestamp - latestDifficultyPeriodStarted2 + 1;
uint epochTotal = epochCount - epochOld;
if(epochTotal == 0){
epochTotal = 1;
}
uint adjusDiffTargetTime = targetTime * epochTotal;
// Calculate adjustment factor (using 1000 as fixed point multiplier)
uint256 adjustmentFactor = (TimeSinceLastDifficultyPeriod2 * 1000) / adjusDiffTargetTime;
uint miningTarget2 = miningTarget;
// Apply Bitcoin's 4x cap in both directions
if (adjustmentFactor > 4000) {
adjustmentFactor = 4000; // Cap at 4x easier
}
if (adjustmentFactor < 250) {
adjustmentFactor = 250; // Cap at 4x harder (1000/4 = 250)
}
// Check if the result would exceed uint256 max
// Rearrange: (miningTarget * adjustmentFactor) / 1000 <= type(uint256).max
// To: miningTarget * adjustmentFactor <= type(uint256).max * 1000
// To: miningTarget <= (type(uint256).max * 1000) / adjustmentFactor
uint256 maxAllowedMiningTarget = mulDiv(_MAXIMUM_TARGET, 1000, adjustmentFactor);
if (miningTarget2 > maxAllowedMiningTarget) {
miningTarget2 = _MAXIMUM_TARGET; // Handle overflow by using maximum target
} else {
miningTarget2 = mulDiv(miningTarget, adjustmentFactor, 1000);
}
if(miningTarget2 < _MINIMUM_TARGET) { // Very difficult
miningTarget2 = _MINIMUM_TARGET;
}
if(miningTarget2 > _MAXIMUM_TARGET) { // Very easy
miningTarget2 = _MAXIMUM_TARGET;
}
return _MAXIMUM_TARGET.div(miningTarget2);
}
/// @notice Returns comprehensive block and adjustment timing information for easy one call in miner
/// @dev Convenience function that aggregates key mining statistics in one call
/// @return slowBlockz Number of blocks that took longer than expected to mine
/// @return secondsUntilAdjustmentz Time in seconds until next difficulty adjustment
/// @return blocksFromReadjustz Number of blocks mined since last difficulty adjustment
/// @return blocksToReadjustz Number of blocks remaining until next difficulty adjustment
/// @custom:aggregation Combines multiple view functions for efficient data retrieval
/// @custom:monitoring Provides complete picture of current mining performance and timing
/// @custom:ui-friendly Single call returns all key metrics for dashboard displays
function getBlockInfo() public view returns (
uint slowBlockz,
uint secondsUntilAdjustmentz,
uint blocksFromReadjustz,
uint blocksToReadjustz
) {
return (
slowBlocks,
seconds_Until_adjustmentSwitch(),
blocksFromReadjust(),
blocksToReadjust()
);
}
///
// Statistical Analysis Functions
///
/// @notice Calculates current mining inflation metrics based on recent performance
/// @dev Analyzes recent mining data to project yearly inflation and mining statistics
/// @dev Returns zero values if no blocks have been mined since last adjustment
/// @return YearlyInflation Projected total B0x tokens to be mined per year at current rate
/// @return EpochsPerYear Projected number of epochs that would be mined in one year
/// @return RewardsAtTime Current reward amount per epoch at current mining speed
/// @return TimePerEpoch Average time in seconds per epoch based on recent performance
/// @custom:performance-based Uses actual mining time data for realistic projections
/// @custom:zero-division-safe Returns zeros if no progress made since last adjustment
/// @custom:yearly-projection Extrapolates current performance to annual estimates
function inflationMined() public view returns (
uint YearlyInflation,
uint EpochsPerYear,
uint RewardsAtTime,
uint TimePerEpoch
) {
if(epochCount - epochOld == 0) {
return (0, 0, 0, 0);
}
uint256 blktimestamp = block.timestamp;
uint TimeSinceLastDifficultyPeriod2 = blktimestamp - latestDifficultyPeriodStarted2;
TimePerEpoch = (TimeSinceLastDifficultyPeriod2 / blocksFromReadjust());
if(TimePerEpoch ==0){
TimePerEpoch = TimePerEpoch + 1;
}
RewardsAtTime = totalB0xToSendAtTime(TimePerEpoch, 2);
uint year = 365 * 24 * 60 * 60;
EpochsPerYear = year / TimePerEpoch;
YearlyInflation = RewardsAtTime * EpochsPerYear;
return (YearlyInflation, EpochsPerYear, RewardsAtTime, TimePerEpoch);
}
/// @notice Calculates time remaining until next reward era and daily mining metrics
/// @dev Uses current inflation rate to project when supply cap for current era will be reached
/// @dev Returns zero values if daily mining amount is zero (no active mining)
/// @return daysToNextEra Number of days until current reward era ends
/// @return maxSupplyForEraTotal Maximum token supply allowed for current reward era
/// @return tokensMintedTotal Total tokens mined so far across all eras
/// @return amtDaily Projected daily token mining amount at current rate
/// @custom:era-progression Tracks progress toward reward halving events
/// @custom:supply-cap-tracking Uses maxSupplyForEra to determine era transition timing
/// @custom:daily-projection Converts yearly inflation to daily mining estimates
function toNextEraDays() public view returns (
uint daysToNextEra,
uint maxSupplyForEraTotal,
uint tokensMintedTotal,
uint amtDaily
) {
(uint totalamt,,,) = inflationMined();
(amtDaily) = totalamt / 365;
if(amtDaily == 0) {
return(0, 0, 0, 0);
}
maxSupplyForEraTotal = maxSupplyForEra;
tokensMintedTotal = tokensMinted;
daysToNextEra = (maxSupplyForEraTotal - tokensMintedTotal) / amtDaily;
return (daysToNextEra, maxSupplyForEraTotal, tokensMintedTotal, amtDaily);
}
/// @notice Calculates epochs remaining until next reward era based on current mining performance
/// @dev Converts daily era progression into epoch-based timeline using current epoch duration
/// @dev Returns zero values if no mining progress has been made
/// @return epochs Number of epochs remaining until next reward era
/// @return epochTime Average time per epoch in seconds based on recent performance
/// @return daysToNextEra Number of days until next reward era (from toNextEraDays)
/// @custom:epoch-timeline Provides epoch-based perspective on era progression
/// @custom:time-conversion Converts days to epochs using current mining performance
/// @custom:performance-dependent Calculations based on actual recent mining speed
function toNextEraEpochs() public view returns (
uint epochs,
uint epochTime,
uint daysToNextEra
) {
if(blocksFromReadjust() == 0) {
return (0, 0, 0);
}
uint256 blktimestamp = block.timestamp;
uint TimeSinceLastDifficultyPeriod2 = blktimestamp - latestDifficultyPeriodStarted2;
uint timePerEpoch = TimeSinceLastDifficultyPeriod2 / blocksFromReadjust();
(uint daysz,,,) = toNextEraDays();
if(timePerEpoch ==0){
timePerEpoch = timePerEpoch + 1;
}
uint amt = daysz * (60 * 60 * 24) / timePerEpoch;
return (amt, timePerEpoch, daysz);
}
/// @notice Validates a mining solution for debugging mining software
/// @dev Checks if provided nonce and digest are valid for the given challenge and target
/// @param nonce The nonce value to test
/// @param challenge_digest The expected digest result
/// @param challenge_number The challenge to solve
/// @param testTarget The difficulty target to test against
/// @return success True if the digest matches and meets the target difficulty
/// @custom:debugging Helps miners verify their solutions before submitting transactions
/// @custom:validation Performs same hash calculation as actual mining functions
function checkMintSolution(uint256 nonce, bytes32 challenge_digest, bytes32 challenge_number, uint testTarget) public view returns (bool success) {
bytes32 digest = bytes32(keccak256(abi.encodePacked(challenge_number, msg.sender, nonce)));
if(uint256(digest) > testTarget) revert();
return (digest == challenge_digest);
}
/// @notice Advanced mining solution validator for debugging with custom sender address
/// @dev Pure function that validates solutions for any sender address, useful for testing
/// @param nonce The nonce value to test
/// @param challenge_digest The expected digest result
/// @param challenge_number The challenge to solve
/// @param testTarget The difficulty target to test against
/// @param senda The sender address to use in hash calculation
/// @return bytes32 The computed digest for verification
/// @custom:debugging Advanced debugging tool for mining software development
/// @custom:pure-function No state dependencies, can test any combination of parameters
function checkMintSolution2(uint256 nonce, bytes32 challenge_digest, bytes32 challenge_number, uint testTarget, address senda) public pure returns (bytes32) {
bytes32 digest = bytes32(keccak256(abi.encodePacked(challenge_number, senda, nonce)));
if(uint256(digest) > testTarget) revert();
return digest;
}
/// @notice Returns the current mining challenge that needs to be solved
/// @dev The challenge changes with each successful mining operation
/// @return bytes32 Current challenge number based on recent Ethereum block hash
function getChallengeNumber() public view returns (bytes32) {
return challengeNumber;
}
/// @notice Returns the current mining difficulty (number of leading zeros required)
/// @dev Automatically adjusts based on mining performance to maintain target block times
/// @return uint Current difficulty calculated as _MAXIMUM_TARGET / current mining target
function getMiningDifficulty() public view returns (uint) {
return _MAXIMUM_TARGET.div(getMiningTarget());
}
/// @notice Returns the current mining target, adjusted for timing if near difficulty adjustment
/// @dev Implements dynamic target adjustment when blocks are taking too long
/// @return uint Current mining target (lower target = higher difficulty)
/// @custom:dynamic-adjustment Temporarily reduces difficulty if current block is very slow
/// @custom:timing-based Activates when blocksToReadjust() == 1 and block time exceeds target
/// @custom:overflow-protection Uses safe arithmetic to prevent overflow in calculations
function getMiningTarget() public view returns (uint) {
if(blocksToReadjust() == 1) {
uint targetTimez = targetTime;
uint blockTimestampz = block.timestamp;
uint previousBlkTimez = previousBlockTime;
if(targetTimez < (blockTimestampz - previousBlkTimez)) {
uint timeMultiplier = (blockTimestampz - previousBlkTimez) / (targetTimez / 2);
uint targetDivisor = targetTimez / (targetTimez / 2);
// First check if result would exceed 2^253
uint MAX_SAFE_VALUE = 1 << 253; // 2^253
// Check if miningTarget * timeMultiplier would overflow
if (timeMultiplier > MAX_SAFE_VALUE / miningTarget) {
// Would overflow, use maximum safe value
return MAX_SAFE_VALUE;
}
// Safe to calculate
uint256 product = miningTarget * timeMultiplier;
return product / targetDivisor;
}
}
return miningTarget;
}
/// @notice Returns the total number of tokens mined so far
/// @dev Tracks cumulative token creation across all mining operations
/// @return uint Total tokens minted since contract deployment
function getMiningMinted() public view returns (uint) {
return tokensMinted;
}
/// @notice Returns the total circulating supply of tokens
/// @dev Currently equivalent to total mined tokens (no burns or locks)
/// @return uint Total tokens in circulation
function getCirculatingSupply() public view returns (uint) {
return tokensMinted;
}
/// @notice Returns the current mining reward per successful block
/// @dev Implements Bitcoin-style reward halving based on current reward era
/// @return uint Current reward amount (50 tokens / 2^rewardEra)
/// @custom:halving-mechanism Reward halves every era as total supply increases
/// @custom:bitcoin-inspired Starts at 50 tokens and halves periodically
function getMiningReward() public view returns (uint) {
// Once we get half way thru the coins, only get 25 per block
// Every reward era, the reward amount halves.
return (50 * 10**18) / (2**(rewardEra));
}
/// @notice Returns the current epoch count (total blocks mined)
/// @dev Increments with each successful mining operation
/// @return uint Current epoch number
function getEpoch() public view returns (uint) {
return epochCount;
}
/// @notice Generates the mining digest for debugging purposes
/// @dev Computes the same hash that would be used in actual mining validation
/// @param nonce The nonce value to test
/// @param challenge_digest The expected digest (unused but kept for interface compatibility)
/// @param challenge_number The challenge (unused, uses current challengeNumber)
/// @return digesttest The computed digest for the current challenge, sender, and nonce
/// @custom:debugging Helps miners verify their hash calculations
/// @custom:current-state Uses actual current challenge and msg.sender
function getMintDigest(uint256 nonce, bytes32 challenge_digest, bytes32 challenge_number) public view returns (bytes32 digesttest) {
bytes32 digest = keccak256(abi.encodePacked(challengeNumber, msg.sender, nonce));
return digest;
}
/// @notice Converts a uint256 value to its string representation
/// @dev Pure function that handles digit-by-digit conversion without external dependencies
/// @dev Used for creating human-readable error messages with numeric values
/// @param value The unsigned integer to convert to string format
/// @return memory String representation of the input value
/// @custom:efficiency Calculates digit count first, then builds string in reverse order
/// @custom:usage Primarily used in revert messages to display required vs sent ETH amounts
function toString(uint256 value) internal pure returns (string memory) {
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);
}
/// @notice Handles calls to non-existent functions with optional data
/// @dev Fallback function that accepts ETH payments and arbitrary call data
fallback() external payable {
}
/// @notice Allows the contract to receive ETH payments directly
/// @dev Called when ETH is sent without function call data
receive() external payable {
}
}
/*
*
* MIT License
* ===========
*
* Copyright (c) 2025 B0x Token (B0x)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*/{
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract ABI
API[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"lp","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"epochCount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"newChallengeNumber","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"NumberOfTokensMinted","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"TokenMultipler","type":"uint256"}],"name":"MegaMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epochCount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"newChallengeNumber","type":"bytes32"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"TransferOwnership","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"ARewardSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"AddressLPReward","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"B0x_Mining_TOKEN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Token2Per","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"compensation","type":"uint256"},{"internalType":"uint256","name":"blocksToReadjustMENT","type":"uint256"}],"name":"TotalForContract","outputs":[{"internalType":"uint256","name":"B0xYouGet","type":"uint256"},{"internalType":"uint256","name":"ETHYouGet","type":"uint256"},{"internalType":"uint256","name":"ETHyouSpend","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"compensation","type":"uint256"}],"name":"TotalTotalsAndETHpriceAndCurrentMintTime","outputs":[{"internalType":"uint256","name":"B0xYouGet","type":"uint256"},{"internalType":"uint256","name":"ETHYouGet","type":"uint256"},{"internalType":"uint256","name":"ETHyouSpend","type":"uint256"},{"internalType":"uint256","name":"ETHPrice","type":"uint256"},{"internalType":"uint256","name":"secondsFromPreviousMintreturn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BLOCKS_PER_READJUSTMENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MAXIMUM_TARGET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MINIMUM_TARGET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_maxTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocksFromReadjust","outputs":[{"internalType":"uint256","name":"blocks","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocksToReadjust","outputs":[{"internalType":"uint256","name":"blocks","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"prevBlockTime","type":"uint256"},{"internalType":"uint256","name":"NumberOfCompensation","type":"uint256"}],"name":"calcReduceDifficulty","outputs":[{"internalType":"uint256","name":"miningDifficultyReduced","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"prevBlockTime","type":"uint256"},{"internalType":"uint256","name":"NumberOfCompensation","type":"uint256"}],"name":"calcReduceTarget","outputs":[{"internalType":"uint256","name":"miningTargetReduced","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"multiplier","type":"uint256"}],"name":"calculateCompensation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"challengeNumber","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes32","name":"challenge_digest","type":"bytes32"},{"internalType":"bytes32","name":"challenge_number","type":"bytes32"},{"internalType":"uint256","name":"testTarget","type":"uint256"}],"name":"checkMintSolution","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes32","name":"challenge_digest","type":"bytes32"},{"internalType":"bytes32","name":"challenge_number","type":"bytes32"},{"internalType":"uint256","name":"testTarget","type":"uint256"},{"internalType":"address","name":"senda","type":"address"}],"name":"checkMintSolution2","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"epochCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochOld","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBlockInfo","outputs":[{"internalType":"uint256","name":"slowBlockz","type":"uint256"},{"internalType":"uint256","name":"secondsUntilAdjustmentz","type":"uint256"},{"internalType":"uint256","name":"blocksFromReadjustz","type":"uint256"},{"internalType":"uint256","name":"blocksToReadjustz","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChallengeNumber","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCirculatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getETHPricePrecise","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMiningDifficulty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMiningMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMiningReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMiningTarget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes32","name":"challenge_digest","type":"bytes32"},{"internalType":"bytes32","name":"challenge_number","type":"bytes32"}],"name":"getMintDigest","outputs":[{"internalType":"bytes32","name":"digesttest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"give0x","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inflationMined","outputs":[{"internalType":"uint256","name":"YearlyInflation","type":"uint256"},{"internalType":"uint256","name":"EpochsPerYear","type":"uint256"},{"internalType":"uint256","name":"RewardsAtTime","type":"uint256"},{"internalType":"uint256","name":"TimePerEpoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastrun","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestDifficultyPeriodStarted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestDifficultyPeriodStarted2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"locked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"log2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"maxSupplyForEra","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miningTarget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes32","name":"challenge_digest","type":"bytes32"}],"name":"mint","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"nftAddresses","type":"address[]"},{"internalType":"uint256[]","name":"nftNumbers","type":"uint256[]"},{"internalType":"uint256[]","name":"nonces","type":"uint256[]"},{"internalType":"uint256","name":"maxNumberOfAnswersInMint","type":"uint256"}],"name":"mintNFT","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nonce","type":"uint256[]"},{"internalType":"address[]","name":"ExtraFunds","type":"address[]"},{"internalType":"address[]","name":"MintTo","type":"address[]"},{"internalType":"uint256","name":"maxNumberOfSolutions","type":"uint256"},{"internalType":"uint256","name":"minBlockTimeDifferencePerSolve","type":"uint256"}],"name":"mintTokensArrayTo","outputs":[{"internalType":"uint256","name":"owed","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nonce","type":"uint256[]"},{"internalType":"address[]","name":"ExtraFunds","type":"address[]"},{"internalType":"address","name":"MintTo","type":"address"},{"internalType":"uint256","name":"MaxAnswersInOneSubmit","type":"uint256"},{"internalType":"uint256","name":"minBlockTimeDifferencePerSolve","type":"uint256"}],"name":"mintTokensSameAddress","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"mintToAddress","type":"address"},{"internalType":"uint256[]","name":"nonce","type":"uint256[]"},{"internalType":"uint256","name":"maxAnswers","type":"uint256"},{"internalType":"uint256","name":"minPreviousBlockTimeDifference","type":"uint256"}],"name":"multi_MintTo","outputs":[{"internalType":"uint256","name":"NumberOfMintsDone","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"multipler","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oldecount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"openMining","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"previousBlockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readjustsToWhatDifficulty","outputs":[{"internalType":"uint256","name":"newDifficulty","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timeDifference","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"epochCountStart","type":"uint256"},{"internalType":"uint256","name":"epochCountEnd","type":"uint256"}],"name":"rewardAtTimeERC20","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardEra","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reward_amount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seconds_Until_adjustmentSwitch","outputs":[{"internalType":"uint256","name":"secs","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sentToLP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newDifficulty","type":"uint256"}],"name":"setDifficultyOnlyTestnet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slowBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeFromLastSolve","outputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toNextEraDays","outputs":[{"internalType":"uint256","name":"daysToNextEra","type":"uint256"},{"internalType":"uint256","name":"maxSupplyForEraTotal","type":"uint256"},{"internalType":"uint256","name":"tokensMintedTotal","type":"uint256"},{"internalType":"uint256","name":"amtDaily","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toNextEraEpochs","outputs":[{"internalType":"uint256","name":"epochs","type":"uint256"},{"internalType":"uint256","name":"epochTime","type":"uint256"},{"internalType":"uint256","name":"daysToNextEra","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"secondsFromPreviousMint","type":"uint256"},{"internalType":"uint256","name":"blocksToAdjust","type":"uint256"}],"name":"totalB0xToSendAtTime","outputs":[{"internalType":"uint256","name":"totalB0xToSendToUser","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalETH_MintedToMiners","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"secondsFromPreviousMint","type":"uint256"},{"internalType":"uint256","name":"miningDiff","type":"uint256"},{"internalType":"uint256","name":"blocksToAdjust","type":"uint256"}],"name":"totalETHowedAtTime","outputs":[{"internalType":"uint256","name":"totalETHNeeded","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalETHtoSendUserAtCurrentTime","outputs":[{"internalType":"uint256","name":"totalETHToSendToUser","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"secondsFromPreviousMint","type":"uint256"}],"name":"totalETHtoSendUserAtTime","outputs":[{"internalType":"uint256","name":"totalETHToSendToUser","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalOwedAtCurrentTime","outputs":[{"internalType":"uint256","name":"totalOwed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"secondsFromPreviousMint","type":"uint256"}],"name":"totalOwedAtTime","outputs":[{"internalType":"uint256","name":"totalOwed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedChallenges","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedChallengesNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedCombinations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a0346101dc5760009061578b3881900390601f8201601f191683016001600160401b038111848210176101c8579180849260409485528339810103126101c457610055602061004e836101e1565b92016101e1565b3360018060a01b03198454161783557f5c486528ec3e3f0ea91181cff8116f02bfa350e03b8b6f12e00765adbb5af85c60408051858152336020820152a16001546102586002556001600160a01b031916426202a2ff1981019081116101b057608052600160ea1b60065560098490554360001981019081116101b05740936001600b55506a0d073135f91b9ea7c00000600c556000600d556a08f69750e81d45e9700000600e556000600f556a08f69750e81d45e9700000601055600060115560006012556013549260006014556000601555600060165542601755600060185560006019556000601a5542601b5560018060a01b031617600155610100600160a81b039060081b169060018060a81b03191617601355426007554360085580600a5560005260046020526040600020600160ff1982541617905560405161559590816101f68239608051818181610bfe01526111370152f35b634e487b7160e01b85526011600452602485fd5b5080fd5b634e487b7160e01b85526041600452602485fd5b600080fd5b51906001600160a01b03821682036101dc5756fe60806040526004361015610010575b005b60003560e01c8062819439146121de578063012d3edf146121c0578063035ccc44146121a257806305411d8814612183578063080ca6e2146121445780630a891b83146121285780630c179832146120f75780630c97e564146103a757806310294317146120d9578063150b7a021461208357806317da485f1461206a5780631801fbe5146116785780632381a60e1461165a578063240c3b701461161c5780632656e97f14611609578063294ce45d146115eb5780632b112e49146108e35780632d38bf7a146115cd5780632f104e0c146115a05780633179fabc1461157e57806332e997081461156357806334d5b131146115485780633730837c146115225780633c953615146115045780633dc8a068146114e657806343346f351461149f57806345d8a23214611481578063490203a7146114495780634cbf68fe1461142b5780634ef3762814610af15780634fa972e11461140d57806351736a13146110a75780635456bf1314611089578063577e9ec11461105d5780635a993ae91461103f578063646222c014610cb45780636d2bfdba14610c995780636de9f32b14610c7b57806373d21f8614610c21578063757991a814610b4d57806378e9792514610be657806381269a5614610b82578063822dec0514610b6b578063829965cc14610b4d57806387a2a9d614610b2d5780638a769d3514610b0f5780638ae0368b14610af15780638da5cb5b14610ac857806397566aa014610a7057806399f584b314610a525780639d30dffb146109cf578063a68eb88e146109b1578063b5ade81b14610994578063b83bd2bd1461090f578063bd92d4d4146108e8578063c0abebe0146108e3578063c212f073146108c5578063c4dd180c14610848578063c76ae54014610826578063c8ce67b914610742578063cb9ae70714610724578063ccadb30a14610628578063cf30901214610605578063d0856d16146105ec578063d0f66e4b146105d0578063d317140b146104aa578063da9816b614610491578063dc6e9cf914610473578063dfe95b0c14610455578063e186ca981461041a578063e38cfe1f146103f1578063e932012b146103d3578063ec11a769146103ac578063f23a6e61146103a7578063f4ec14181461037b5763f95d39190361000e5734610376576000366003190112610376576020601454604051908152f35b600080fd5b3461037657606036600319011261037657602061039f604435602435600435615071565b604051908152f35b612292565b3461037657600036600319011261037657602061039f6103ce60175442612431565b614abc565b34610376576000366003190112610376576020600754604051908152f35b34610376576000366003190112610376576001546040516001600160a01b039091168152602090f35b346103765761045161043461042e36612302565b90614bf9565b604080519384526020840192909252908201529081906060820190565b0390f35b3461037657602036600319011261037657602061039f600435614abc565b34610376576000366003190112610376576020604051620100008152f35b3461037657602061039f6104a436612302565b9061498e565b3461037657602036600319011261037657600054600435906001600160a01b0316330361059e57612710811015610523578060131b9080820462080000149015171561050d578015610376576104ff90612454565b600655602060405160018152f35b634e487b7160e01b600052601160045260246000fd5b60405162461bcd60e51b815260206004820152604760248201527f4e657720646966666963756c7479206d757374206265206174206c656173742060448201527f62656c6f7720313030303020307842544320646966666963756c7479206e6f74606482015266103434b3b432b960c91b608482015260a490fd5b60405162461bcd60e51b815260206004820152600a60248201526927b7363c9027bbb732b960b11b6044820152606490fd5b346103765760003660031901126103765761045161043461490d565b346103765760003660031901126103765761000e6144c9565b3461037657600036600319011261037657602060ff601354166040519015158152f35b346103765760003660031901126103765761064560075442612431565b6001810180911161050d5761065f60095460125490612431565b801561071c575b6106729060025461247a565b6103e88202918083046103e8149015171561050d5761069091612463565b60065490610fa08111610713575b60fa811061070b575b6106b08161519d565b8211156106fd5750600160fd1b90505b6201000081106106f3575b600160fd1b81116106e8575b80156103765761039f602091612454565b50600160fd1b6106d7565b50620100006106cb565b61070691615205565b6106c0565b5060fa6106a7565b50610fa061069e565b506001610666565b34610376576000366003190112610376576020600854604051908152f35b60a0366003190112610376576004356001600160401b0381116103765761076d903690600401612366565b6024356001600160401b0381116103765761078c9036906004016123c3565b906044356001600160a01b03811690819003610376578251926001840180941161050d576107b98461234f565b936107c76040519586612318565b8085526107d6601f199161234f565b0136602086013760005b81516001810180911161050d57811015610809578083610802600193886125df565b52016107e0565b61081a608435606435878588613ebc565b50602060405160018152f35b3461037657600036600319011261037657602061039f60095460125490612431565b60a0366003190112610376576004356001600160401b03811161037657610873903690600401612366565b6024356001600160401b038111610376576108929036906004016123c3565b604435906001600160401b038211610376576020926108b861039f9336906004016123c3565b6084359260643592613ebc565b34610376576000366003190112610376576020601b54604051908152f35b610c7b565b3461037657600036600319011261037657602061039f61090a60175442612431565b612732565b6080366003190112610376576004356001600160401b0381116103765761093a9036906004016123c3565b6024356001600160401b03811161037657610959903690600401612366565b90604435906001600160401b0382116103765760209261098061098a933690600401612366565b90606435926134c7565b6040519015158152f35b346103765760003660031901126103765760206040516107e08152f35b34610376576000366003190112610376576020601854604051908152f35b346103765760a0366003190112610376576084356001600160a01b038116810361037657604051610a3b81610a2d60208201946004359060443587916054939183526001600160601b03199060601b16602083015260348201520190565b03601f198101835282612318565b519020606435811161037657602090604051908152f35b34610376576000366003190112610376576020601554604051908152f35b3461037657606036600319011261037657600a546040805160208181019384523360601b6001600160601b031916928201929092526004356054820152909190610abd8160748101610a2d565b519020604051908152f35b34610376576000366003190112610376576000546040516001600160a01b039091168152602090f35b34610376576000366003190112610376576020600a54604051908152f35b34610376576000366003190112610376576020600654604051908152f35b3461037657600036600319011261037657604051600160fd1b8152602090f35b34610376576000366003190112610376576020600954604051908152f35b34610376576106d7610b7c36612302565b9061262b565b346103765760803660031901126103765760408051604435602082019081523360601b6001600160601b031916928201929092526004356054820152610bcb8160748101610a2d565b51902060643581116103765760209060405190602435148152f35b346103765760003660031901126103765760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346103765760203660031901126103765760a0610c4060175442612431565b610c53610c4b612858565b600435614bf9565b9060409392935193845260208401526040830152660ffba26e7b326b60608301526080820152f35b34610376576000366003190112610376576020600e54604051908152f35b3461037657600036600319011261037657602061039f6133d2565b34610376576080366003190112610376576024356001600160401b03811161037657610ce49036906004016123c3565b606435610cf360443582612431565b90610d0361090a83600435612463565b90610d0e845161258a565b6000935b8551851015610da7576001850180861161050d575b8651811015610d9b576001600160a01b03610d4282896125df565b51166001600160a01b03610d56888a6125df565b511614610d6557600101610d27565b60405162461bcd60e51b815260206004820152600e60248201526d4e6f2073616d6520746f6b656e7360901b6044820152606490fd5b50600190940193610d12565b9350936000935b808510610dfb578560405180916020820160208352815180915260206040840192019060005b818110610de2575050500390f35b8251845285945060209384019390920191600101610dd4565b60005b8251811015611034576000610e138786612431565b600183018084116110205790610e2b610e319261292b565b9061284e565b15610e40575b50600101610dfe565b60249060206001600160a01b03610e5785886125df565b5116604051938480926370a0823160e01b82523060048301525afa918215611013578792829190610fda575b5081610e91575b5050610e37565b600384061580610fd1575b80610fc4575b15610f2f575090610ebb610ec092610ebb600b5461292b565b61247a565b90610eca8161292b565b6305f5e1008102908082046305f5e100148115171561050d576501d1a94a20000290808204614e20149015171561050d57610f0a610f1a91600194615337565b610f14838b6125df565b5161246d565b610f24828a6125df565b529050848880610e8a565b91610ebb610f4292610ebb600b5461292b565b610f4b8361292b565b916305f5e1008302928084046305f5e1001481151715610fb0576501d1a94a20000292808404614e201490151715610f9c578215610f995750610f9460019392610f1a92612463565b610f0a565b80fd5b634e487b7160e01b81526011600452602490fd5b634e487b7160e01b82526011600452602482fd5b5063010c8e008311610ea2565b50831515610e9c565b915091506020813d821161100b575b81610ff660209383612318565b81010312611007575186918a610e83565b5080fd5b3d9150610fe9565b50604051903d90823e3d90fd5b634e487b7160e01b83526011600452602483fd5b509360010193610dae565b3461037657602036600319011261037657602061039f600435613375565b346103765760203660031901126103765760043560005260056020526020604060002054604051908152f35b3461037657602036600319011261037657602061039f600435613352565b34610376576000366003190112610376576a08f69750e81d45e9700000600e54116113c8576001546040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa80156113bc5760009061137f575b6a10d0a9ee1d64709720000091501061132e57600d546112f35760135460ff81166112ae5760ff19166001176013557f0000000000000000000000000000000000000000000000000000000000000000428111159081611296575b501561124657600019430143811161050d574080600a55600b546111848161292b565b8015611230576802b5e3af16b188000004600d556001810180911161050d576111ac9061292b565b8015610376576111bb9061243e565b6a115eec47f6cf7e35000000036a115eec47f6cf7e35000000811161050d57600c55600160ea1b60065542600755436008556000601255600060095580600052600460205260ff604060002054166103765760005260046020526040600020600160ff19825416179055602060405160018152f35b634e487b7160e01b600052601260045260246000fd5b60405162461bcd60e51b815260206004820152602260248201527f37204461792077696e646f7720746f20616374697661746520537461727454696044820152616d6560f01b6064820152608490fd5b905062093a80810180911161050d5742111581611161565b60405162461bcd60e51b815260206004820152601860248201527f4f6e6c7920616c6c6f77656420746f2072756e206f6e636500000000000000006044820152606490fd5b60405162461bcd60e51b8152602060048201526013602482015272726577617264206d757374206265207a65726f60681b6044820152606490fd5b60405162461bcd60e51b815260206004820152602360248201527f4d75737420737570706c7920322a31305f3136345f313030206d696e20746f6b604482015262656e7360e81b6064820152608490fd5b506020813d6020116113b4575b8161139960209383612318565b81010312610376576a10d0a9ee1d6470972000009051611106565b3d915061138c565b6040513d6000823e3d90fd5b60405162461bcd60e51b815260206004820152601e60248201527f43616e74206d696e7420746f6b656e73206265666f7265206c61756e636800006044820152606490fd5b34610376576000366003190112610376576020600c54604051908152f35b34610376576000366003190112610376576020601954604051908152f35b3461037657600036600319011261037657611465600b5461292b565b801561123057602090604051906802b5e3af16b1880000048152f35b34610376576000366003190112610376576020600254604051908152f35b6080366003190112610376576114b3612239565b6024356001600160401b038111610376576020916114d861039f923690600401612366565b90606435916044359161299d565b34610376576000366003190112610376576020601654604051908152f35b34610376576000366003190112610376576020601a54604051908152f35b346103765760003660031901126103765760206040516a115eec47f6cf7e350000008152f35b3461037657600036600319011261037657602061039f612858565b3461037657600036600319011261037657602061039f612800565b34610376576000366003190112610376576020604051660ffba26e7b326b8152f35b346103765760003660031901126103765760135460405160089190911c6001600160a01b03168152602090f35b34610376576000366003190112610376576020600b54604051908152f35b3461037657602036600319011261037657602061039f600435612732565b3461037657602061039f610b7c36612302565b34610376576000366003190112610376576104516116386125f3565b6040805194855260208501939093529183015260608201529081906080820190565b34610376576000366003190112610376576020600d54604051908152f35b3461037657604036600319011261037657604080516116978282612318565b60018152601f1982013660208301376004356116b2826125bc565b526000916116be612858565b90836017549260025491600a549060065490885b885181101561205d576116e5818a6125df565b518751602081018681523360601b6001600160601b031916604083015260548201929092526117178160748101610a2d565b5190209161172d6117288486612463565b613375565b6107e061173a828461246d565b11612039575b8661174b828461246d565b1061200e575061175b8187612431565b61176e876117698c42612431565b612463565b80891015611fd75761178e6117878a60011c8093612463565b918a612463565b906006548015611fc3578e918c91600160fd1b819004821115611fac57505050508015611f9857600160fd1b0460ff8a8e5b8981526003602052818120888252602052205416908115611f8d575b50611f82576117ec905b8261246d565b908110611dca57806107e09193868d526003602052898d20908d52602052888c20600160ff198254161790551015611f705784821015611830576001905b016116d2565b50505090809293949550925b83159586611f2057846117698261185a8361176961186a9642612431565b50611863612570565b5042612431565b6103788102908082046103781490151715611f0c579061188991612463565b606481029080820460641490151715611ef8576103786064910411611ed8575b6118b38284614bf9565b9391908194816118c581600f5461246d565b600f55818110611dce57506118d991612431565b8801808911611c0057915b60095490808710611d19576118f9908261246d565b908110611c1457600955600e546a115eec47f6cf7e3500000010611d10575b6119206144c9565b61192c60075442612431565b60018101809111611c00576009549061195261194a60125484612431565b60025461247a565b916012556103e88102908082046103e81490151715611c56579061197591612463565b610fa08111611d07575b60fa8110611cff575b6119918161519d565b6006549190821115611cee575050600160fd1b6006555b4260075414611cba5742600755436008556201000060065410611cae575b600654600160fd1b10611ca1575b6000194301438111611c005740600a548751602081019183835289820152888152611a00606082612318565b519020808a52600460205260ff888b205416611c6a57808a526004602052878a20600160ff19825416179055600a558089526005602052868920549060018201809211611c5657906003918a52600560205280888b205511611c24575b600e54611a6a828261246d565b908110611c1457600c541080611c18575b611b6a575b50600154855163a9059cbb60e01b81523360048201526024810185905290602090829060449082908c906001600160a01b03165af18015611b6057611b33575b50600e54611ace848261246d565b908110611b2f57968080809360209a600e5542601755335af150611af061296d565b50600954845192835286830152838201527fcf6fbb9dcea7d07263ab4f5c3a92f53af33dffc421d9d121e1c74b307e68189d60603392a2505190158152f35b8780fd5b611b549060203d602011611b59575b611b4c8183612318565b81019061293a565b611ac0565b503d611b42565b86513d8a823e3d90fd5b909250600b546001810190818111611c005760029082600b5501808211611c0057611b949061292b565b8015611c1457611ba39061243e565b6a115eec47f6cf7e35000000036a115eec47f6cf7e350000008111611c0057600c55611bce9061292b565b8015611bec576802b5e3af16b188000004600d5560011c9187611a80565b634e487b7160e01b88526012600452602488fd5b634e487b7160e01b89526011600452602489fd5b8880fd5b50603b600b5410611a7b565b855162461bcd60e51b815260206004820152600b60248201526a4d617820332074696d657360a81b6044820152606490fd5b634e487b7160e01b8a52601160045260248afd5b875162461bcd60e51b815260206004820152601060248201526f75736564204368616c206265666f726560801b6044820152606490fd5b600160fd1b6006556119d4565b620100006006556119c6565b855162461bcd60e51b815260206004820152600d60248201526c4e6f2073616d6520626c6f636b60981b6044820152606490fd5b611cf791615205565b6006556119a8565b5060fa611988565b50610fa061197f565b87600d55611918565b6107e0036107e08111611c565786611d309161246d565b611d3a8782612431565b91611d45888261246d565b908110611dca576009556101f882109182611dbd575b8215611d9e575b8215611d7d575b505015611a5d57611d786144c9565b611a5d565b6105e811915081611d91575b508980611d69565b6105e89150101589611d89565b91506103f0821080611db1575b91611d62565b506103f0811015611dab565b6101f88210159250611d5b565b8a80fd5b90611dd99250612431565b80611ded578803888111611c0057916118e4565b604460458a89611ea46004600c611e0f611e09611eca9961526f565b9561526f565b845196879160208301977f4e65656420746f2073656e64207265717569726564204554482e20526571756989526403932b21d160dd1b88850152611e5c8151809260208688019101612908565b83016b0103bb2b4961029b2b73a1d160a51b83820152611e86825180936020605185019101612908565b0101632077656960e01b838201520301601b19810186520184612318565b5193849262461bcd60e51b84526020600485015251809281602486015285850190612908565b601f01601f19168101030190fd5b601954611ee5848261246d565b908110611ef4576019556118a9565b8680fd5b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b88526011600452602488fd5b855162461bcd60e51b8152602060048201526024808201527f4d75737420686176652076616c696420736f6c766520696e2074686520616e736044820152637765727360e01b6064820152608490fd5b5050509091929394506107e09261183c565b50915060019061182a565b90508410158d6117dc565b634e487b7160e01b8d52601260045260248dfd5b93611769611fbd9260ff959661247a565b926117c0565b634e487b7160e01b8f52601260045260248ffd5b50858c526003602052888c20848d5260205260ff898d2054168015612004575b611f82576117ec906117e6565b5084841015611ff7565b858c526003602052888c20848d5260205260ff898d205416801561200457611f82576117ec906117e6565b50806107e0036107e081111561174057634e487b7160e01b8c52601160045260248cfd5b509495965050909161183c565b34610376576000366003190112610376576106d7612800565b346103765760803660031901126103765761209c612239565b506120a561224f565b506064356001600160401b038111610376576120c5903690600401612265565b5050604051630a85bd0160e11b8152602090f35b34610376576000366003190112610376576020601754604051908152f35b34610376576020366003190112610376576004356000526004602052602060ff604060002054166040519015158152f35b346103765760003660031901126103765761045161163861248d565b346103765760403660031901126103765760043560005260036020526040600020602435600052602052602060ff604060002054166040519015158152f35b3461037657600036600319011261037657602061039f60175442612431565b34610376576000366003190112610376576020600f54604051908152f35b34610376576000366003190112610376576020601254604051908152f35b34610376576000366003190112610376576019546121fa6133d2565b9061045161220d60095460125490612431565b612215612858565b90604051948594859094939260609260808301968352602083015260408201520152565b600435906001600160a01b038216820361037657565b602435906001600160a01b038216820361037657565b9181601f84011215610376578235916001600160401b038311610376576020838186019501011161037657565b3461037657600060a0366003190112610f9957600435906001600160a01b0382168203610f995750506024356001600160a01b038116810361037657506084356001600160401b038111610376576122ee903690600401612265565b505060405163f23a6e6160e01b8152602090f35b6040906003190112610376576004359060243590565b90601f801991011681019081106001600160401b0382111761233957604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b0381116123395760051b60200190565b9080601f8301121561037657813561237d8161234f565b9261238b6040519485612318565b81845260208085019260051b82010192831161037657602001905b8282106123b35750505090565b81358152602091820191016123a6565b9080601f83011215610376578135906123db8261234f565b926123e96040519485612318565b82845260208085019360051b82010191821161037657602001915b8183106124115750505090565b82356001600160a01b038116810361037657815260209283019201612404565b9190820391821161050d57565b8015611230576a115eec47f6cf7e350000000490565b801561123057600160fd1b0490565b8115611230570490565b9190820180921161050d57565b8181029291811591840414171561050d57565b6009546012549061249e8282612431565b15612560576124bc6124c2926124b660075442612431565b92612431565b90612463565b801561253e575b600d54906103e88102918115928281046103e81484171561050d576103e8916124f86125089260025490612463565b838111156125265750829061247a565b049161123057806301e133800492612520848461247a565b93929190565b60fa811015612538575060fa9061247a565b9061247a565b60018101809111156124c957634e487b7160e01b600052601160045260246000fd5b5050600090600090600090600090565b612578612800565b80156103765761258790612454565b90565b906125948261234f565b6125a16040519182612318565b82815280926125b2601f199161234f565b0190602036910137565b8051156125c95760200190565b634e487b7160e01b600052603260045260246000fd5b80518210156125c95760209160051b010190565b61016d6125fe61248d565b5050500490811561261f57600c5491600e5491612520826117698587612431565b60009150819081908190565b9190916126416000936117696002549342612431565b80821061264c575050565b819293506126616126679260011c8092612463565b92612463565b600654801561123057600160fd1b819004831161268b57612587926117699161247a565b50600160fd1b92915050565b600090801561272b5780806001146127235760021461271b5760016101338210166001600b8310161761270d579060019060025b600181116126e4575082600019048211610f9c57500290565b9280600019048111610fb05760018416612704575b80029260011c6126cb565b809202916126f9565b6002900a919080610f9c5750565b506004919050565b505050600190565b5050600090565b610378810290808204610378149015171561050d5760025461275391612463565b606481028181046064148215171561050d57610378610bb89104106000146127c45761277e81612697565b80600f0290600f8204810361050d576274692202906207c2be82040361050d57620c08409004816297bb7002916297bb7083040361050d5761037861258792049061246d565b806018029060188204810361050d5763074692200290808204624d9b6c149015171561050d57610378900463ce09d1b0810180911161050d5790565b600161280a612858565b14612816575b60065490565b6002546017546128268142612431565b8210612833575050612810565b6128406126679142612431565b6126618360011c8092612463565b8115611230570690565b6009546012549061286b60075442612431565b6002549061288261287c8585612431565b8361247a565b916107e08102908082046107e0149015171561050d576001600160fe1b038316830361050d576128b28585612431565b9260021b821192836128fd575b5082156128f3575b5050156128d5575050600190565b6107e0916128e291612431565b066107e0036107e0811161050d5790565b10905038806128c7565b60fc109250386128bf565b60005b83811061291b5750506000910152565b818101518382015260200161290b565b60ff811161050d576001901b90565b90816020910312610376575180151581036103765790565b6001600160401b03811161233957601f01601f191660200190565b3d15612998573d9061297e82612952565b9161298c6040519384612318565b82523d6000602084013e565b606090565b9092916129a8612858565b91600091826017549060025492600a5495600654925b8a51811015613334576129d1818c6125df565b51604051612a0881610a2d60208201948d339087916054939183526001600160601b03199060601b16602083015260348201520190565b51902091612a196117288487612463565b84612a24828461246d565b11613324575b8a612a35828461246d565b106132f35750612a45818b612431565b612a538b6117698942612431565b808910156132b657612a6c6117878a60011c8093612463565b90600654801561123057600160fd1b8190048211156132a3575050801561123057600160fd1b045b8a600052600360205260406000208560005260205260ff60406000205416908115613298575b5061328d57612ac9908261246d565b90811061037657808491938a60005260036020526040600020906000526020526040600020600160ff19825416179055101561327c5788821015612b11576001905b016129be565b505050509091929380959650955b861561322b57612b33876117698442612431565b106131815785611769612b4892611863612570565b90610378820291808304610378149015171561050d57612b6791612463565b60648102908082046064149015171561050d576103786064910411613165575b612b918385614bf9565b829195929580612ba381600f5461246d565b600f558281106130645750612bc191612bbb91612431565b3461246d565b915b60095490808810612fb357612bd8908261246d565b90811061037657600955600e546a115eec47f6cf7e3500000010612fa9575b612bff6144c9565b612c0b60075442612431565b6001810180911161050d57600954612c2861194a60125483612431565b906012556103e88202918083046103e8149015171561050d57612c4a91612463565b610fa08111612fa0575b60fa8110612f98575b612c668161519d565b6006549190821115612f87575050600160fd1b6006555b4260075414612f525742600755436008556201000060065410612f46575b600654600160fd1b10612f39575b600019430143811161050d5740600a546040516020810191838352604082015260408152612cd8606082612318565b51902080600052600460205260ff60406000205416612f01578060005260046020526040600020600160ff19825416179055600a558060005260056020526040600020546001810180911161050d5760039160005260056020528060406000205511612ece575b600e54612d4c828261246d565b90811061037657600c541080612ec2575b612e3f575b5060015460405163a9059cbb60e01b81526001600160a01b03848116600483015260248201879052909160209183916044918391600091165af180156113bc57612e22575b50600e5491612db6858461246d565b92831061037657600e9290925542601755600091829182918291906001600160a01b03165af150612de561296d565b50600954604051928352602083015260408201527fcf6fbb9dcea7d07263ab4f5c3a92f53af33dffc421d9d121e1c74b307e68189d60603392a290565b612e3a9060203d602011611b5957611b4c8183612318565b612da7565b909350600b54600181019081811161050d5760029082600b550180821161050d57612e699061292b565b801561037657612e789061243e565b6a115eec47f6cf7e3500000003906a115eec47f6cf7e35000000821161050d57612ea491600c5561292b565b8015611230576802b5e3af16b188000004600d5560011c9238612d62565b50603b600b5410612d5d565b60405162461bcd60e51b815260206004820152600b60248201526a4d617820332074696d657360a81b6044820152606490fd5b60405162461bcd60e51b815260206004820152601060248201526f75736564204368616c206265666f726560801b6044820152606490fd5b600160fd1b600655612ca9565b62010000600655612c9b565b60405162461bcd60e51b815260206004820152600d60248201526c4e6f2073616d6520626c6f636b60981b6044820152606490fd5b612f9091615205565b600655612c7d565b5060fa612c5d565b50610fa0612c54565b6000600d55612bf7565b6107e0036107e0811161050d5787612fca9161246d565b612fd48882612431565b91612fdf898261246d565b908110610376576009556101f882109182613057575b8215613038575b8215613017575b505015612d3f576130126144c9565b612d3f565b6105e81191508161302b575b503880613003565b6105e89150101538613023565b91506103f082108061304b575b91612ffc565b506103f0811015613045565b6101f88210159250612ff5565b905061306f91612431565b803410613086576130809034612431565b91612bc3565b60446045613096611eca9361526f565b61313d6004600c6130a63461526f565b60405195869160208301967f4e65656420746f2073656e64207265717569726564204554482e20526571756988526403932b21d160dd1b60408501526130f58151809260208688019101612908565b83016b0103bb2b4961029b2b73a1d160a51b8382015261311f825180936020605185019101612908565b0101632077656960e01b838201520301601b19810185520183612318565b60405193849262461bcd60e51b84526020600485015251809281602486015285850190612908565b601954613172858261246d565b90811061037657601955612b87565b60405162461bcd60e51b815260206004820152607060248201527f4e6f7420656e6f75676820446966666572656e636520696e2070726576426c6f60448201527f636b54696d65202f20476f6f644c6f6f70732c20636f6d706172656420746f2060648201527f6d696e50726576696f7573426c6f636b54696d65446966666572656e6365206660848201526f756e6374696f6e207661726961626c6560801b60a482015260c490fd5b60405162461bcd60e51b8152602060048201526024808201527f4d75737420686176652076616c696420736f6c766520696e2074686520616e736044820152637765727360e01b6064820152608490fd5b505091929394959697505095612b1f565b509150600190612b0b565b905084101538612aba565b6132b192916117699161247a565b612a94565b5089600052600360205260406000208460005260205260ff6040600020541680156132e9575b61328d57612ac9906117e6565b50858410156132dc565b89600052600360205260406000208460005260205260ff6040600020541680156132e95761328d57612ac9906117e6565b5061332f8185612431565b612a2a565b50985050509091929394612b1f565b600019811461050d5760010190565b6000905b60018111613362575090565b61336f9060011c91613343565b90613356565b60048110613397576133899060011c613352565b6001810180911161050d5790565b50600190565b9190916000838201938412911290801582169115161761050d57565b8181039291600013801582851316918412161761050d57565b600954601254906133ea600754926124b68442612431565b916002546107e08102908082046107e0148115171561050d578461340d9161247a565b600281901b93906001600160fe1b0381160361050d5783811190816134bc575b81156134b2575b506134a95761344f60fc9161344a42918561339d565b6133b9565b931161346a575b505060008113156134645790565b50600090565b61344a61347892429261339d565b6000811380613495575b61348d575b80613456565b905038613487565b508181128061348257506000821315613482565b50505050600090565b9050811038613434565b60fc8611915061342d565b919260016134d3612858565b1480613ea4575b80613e98575b15613e62578251825103613e25576000906134f9612858565b90826017549360025490600a549360065491845b8b51811015613e1557613520818d6125df565b5160405161355681610a2d6020820194338d87916054939183526001600160601b03199060601b16602083015260348201520190565b519020916135676117288487612463565b84613572828461246d565b11613e05575b89613583828461246d565b10613dd85750613593818a612431565b6135a18a6117698d42612431565b80881015613d9f576135c16135ba8960011c8093612463565b9189612463565b906006548015613d8b57600160fd1b819004821115613d785750508015613d6457600160fd1b045b898952600360205260408920858a5260205260ff60408a205416908115613d59575b50613d4e5761361a908261246d565b908110611ef4578084919389895260036020526040892090895260205260408820600160ff198254161790551015613d3c578782101561365e576001905b0161350d565b50505050909192809495969750945b851561322b57856117698261185a836117696136899642612431565b610378810290808204610378149015171561102057906136a891612463565b606481029080820460641490151715610fb0576103786064910411613d20575b6136d28385614bf9565b8291959295806136e481600f5461246d565b600f55828110613cfe57506136fc91612bbb91612431565b915b60095490808810613c4957613713908261246d565b908110613be157600955600e546a115eec47f6cf7e3500000010613c40575b61373a6144c9565b61374660075442612431565b60018101809111613bcd576009549061376461194a60125484612431565b916012556103e88102908082046103e81490151715613bf1579061378791612463565b610fa08111613c37575b60fa8110613c2f575b6137a38161519d565b6006549190821115613c1e575050600160fd1b6006555b4260075414612f525742600755436008556201000060065410613c12575b600654600160fd1b10613c05575b6000194301438111613bcd5740600a546040516020810191838352604082015260408152613815606082612318565b519020808552600460205260ff604086205416612f0157808552600460205260408520600160ff19825416179055600a55808452600560205260408420549060018201809211613bf157906003918552600560205280604086205511612ece575b600e54613883828261246d565b908110613be157600c541080613be5575b613b37575b5060015460405163a9059cbb60e01b815233600482015260248101869052906020908290604490829087906001600160a01b03165af18015613b2c57613b0f575b50600e546138e8858261246d565b908110613b0b578280928192600e5542601755335af15061390761296d565b50600954604051928352602083015260408201527fcf6fbb9dcea7d07263ab4f5c3a92f53af33dffc421d9d121e1c74b307e68189d60603392a250600090815b8351811015613b02576001600160a01b0361396282866125df565b511661396e82846125df565b516040516301ffc9a760e01b8152636cdb3d1360e11b6004820152602081602481865afa869181613ae2575b50613a7d575b506040516301ffc9a760e01b81526380ac58cd60e01b6004820152602081602481865afa869181613a5d575b506139df575b5050506001905b01613947565b6139e957806139d2565b813b15613a595784809260a482936040519485938492635c46a7ef60e11b84523060048501523360248501526044840152608060648401528160848401525af19182613a49575b5050613a3e576001906139d9565b505060195550600190565b613a5291612318565b3884613a30565b8480fd5b613a7691925060203d8111611b5957611b4c8183612318565b90386139cc565b613a8757386139a0565b813b15613a595784809260c482936040519485938492637921219560e11b845230600485015233602485015260448401526001606484015260a060848401528160a48401525af19182613a49575050613a3e576001906139d9565b613afb91925060203d8111611b5957611b4c8183612318565b903861399a565b50505050600190565b8280fd5b613b279060203d602011611b5957611b4c8183612318565b6138da565b6040513d85823e3d90fd5b909350600b546001810190818111613bcd5760029082600b5501808211613bcd57613b619061292b565b8015613be157613b709061243e565b6a115eec47f6cf7e35000000036a115eec47f6cf7e350000008111613bcd57600c55613b9b9061292b565b8015613bb9576802b5e3af16b188000004600d5560011c9238613899565b634e487b7160e01b83526012600452602483fd5b634e487b7160e01b84526011600452602484fd5b8380fd5b50603b600b5410613894565b634e487b7160e01b85526011600452602485fd5b600160fd1b6006556137e6565b620100006006556137d8565b613c2791615205565b6006556137ba565b5060fa61379a565b50610fa0613791565b82600d55613732565b6107e0036107e08111613bf15787613c609161246d565b613c6a8882612431565b91613c75898261246d565b908110613cfa576009556101f882109182613ced575b8215613cce575b8215613cad575b50501561387657613ca86144c9565b613876565b6105e811915081613cc1575b503880613c99565b6105e89150101538613cb9565b91506103f0821080613ce1575b91613c92565b506103f0811015613cdb565b6101f88210159250613c8b565b8580fd5b9050613d0991612431565b80341061308657613d1a9034612431565b916136fe565b601954613d2d858261246d565b908110611007576019556136c8565b5050919293949596979850509461366d565b509150600190613658565b90508410153861360b565b634e487b7160e01b89526012600452602489fd5b613d8692916117699161247a565b6135e9565b634e487b7160e01b8b52601260045260248bfd5b5088885260036020526040882084895260205260ff6040892054168015613dce575b613d4e5761361a906117e6565b5085841015613dc1565b88885260036020526040882084895260205260ff6040892054168015613dce57613d4e5761361a906117e6565b50613e108185612431565b613578565b509798995050509091929361366d565b60405162461bcd60e51b8152602060048201526015602482015274082e4e4c2f240d8cadccee8d040dad2e6dac2e8c6d605b1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d1391950810591a9d5cdd0810985960921b6044820152606490fd5b5060fc601954116134e0565b506005613eb660095460125490612431565b106134da565b60175461176996959294613ef49361090a93613eeb92906001600160a01b03613ee4896125bc565b511661299d565b96879142612431565b926009549460009185156144bf57835185519060018201809211613bf157036144545760018060a01b036001541695613f2d865161258a565b92845b8751811015613fac57886001600160a01b03613f4c838b6125df565b511614613f5b57600101613f30565b60405162461bcd60e51b8152602060048201526024808201527f4e6f7420616c6c6f77656420746f204552433230206d696e74204d61696e205460448201526337b5b2b760e11b6064820152608490fd5b5090929594979193965086905b80821061414c5750505060005b85811080614142575b156140f5576001600160a01b03613fe682866125df565b511690613ff381876125df565b518061400a575b506140059150613343565b613fc6565b60135460405163a9059cbb60e01b815260089190911c6001600160a01b03166004820152602481018290526020816044816000885af180156113bc576140d9575b50600182019081831161050d576140a7936020926001600160a01b0390614072908d6125df565b5116600060405180978195829463a9059cbb60e01b84526004840160209093929193604081019460018060a01b031681520152565b03925af19182156113bc576140059215613ffa576140d29060203d8111611b5957611b4c8183612318565b5038613ffa565b6140f09060203d8111611b5957611b4c8183612318565b61404b565b5093925093505060095490600a54604051928352602083015260408201528160608201527f87e5a7775b8ac2ead741e32752431bffeff76ec5f347cc202a6bad454653930b60803392a290565b5083518110613fcf565b909497600097949796939296975b89518910156144455760018901808a1161050d5761418061417a8261292b565b8a61284e565b614214575b8a51811015614208576001600160a01b036141a0828d6125df565b51166001600160a01b036141b48c8e6125df565b5116146141c357600101614185565b60405162461bcd60e51b815260206004820152601b60248201527f4e6f207072696e74696e67205468652073616d6520746f6b656e7300000000006044820152606490fd5b5060019098019761415a565b50989593989694909192965b88156144365788821061442e575b60005b89811080614424575b15614401576001810180821161050d5761425661425c9161292b565b8861284e565b15614270575b61426b90613343565b614231565b6000806001600160a01b03614285848c6125df565b511660405160208101906370a0823160e01b8252306024820152602481526142ae604482612318565b51915afa6142ba61296d565b90806143f5575b156143ed57805160208083019260009281010312610f995750515b806142e8575b50614262565b896003830615806143e4575b806143d7575b15614371576143089161247a565b906143128161292b565b916305f5e1008302928084046305f5e100148115171561050d576501d1a94a20000292808404614e20149015171561050d5761436a826143648f9361426b9661435a91615337565b610f1483866125df565b926125df565b52906142e2565b61437a9161247a565b906143848161292b565b916305f5e1008302928084046305f5e100148115171561050d576501d1a94a20000292808404614e20149015171561050d5782156103765761436a826143648f9361426b966143d291612463565b61435a565b5063010c8e0081116142fa565b508215156142f4565b5060006142dc565b506020815110156142c1565b50949097509795929097600019810190811161050d57600190915b019091613fb9565b508751811061423a565b88915061422e565b9491989693600191985061441c565b98959398969490919296614220565b60405162461bcd60e51b815260206004820152603a60248201527f4d696e74546f2068617320746f206861766520616e206578747261206164647260448201527f65737320636f6d706172656420746f20457874726146756e64730000000000006064820152608490fd5b9550509250505090565b6000606447818102918115918304141715610fb057670214e8348c4d796090048060155560c881106000146146ce57806501a3185c500002906501a3185c5000820403610fb05760c890045b601855614527600e5460105490612431565b614536600f5460115490612431565b60015460135460405163a9059cbb60e01b81526001600160a01b0360089290921c8216600482015260248101859052929392916020918391168187816044810103925af180156146c3576146a6575b50614593601454918261246d565b908110613b0b57601455476018546107e08102908082046107e01490151715613bcd5760011c9081605002916050830403613bcd57839291101561469c576013548291829182919060081c6001600160a01b03165af16145f161296d565b5015614661576001601a5560135460081c6001600160a01b0316803b1561100757818091600460405180948193636645e41360e01b83525af1801561465657614646575b50505b600e54601055600f54601155565b8161465091612318565b38614635565b6040513d84823e3d90fd5b60405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b6044820152606490fd5b5050601a55614638565b6146be9060203d602011611b5957611b4c8183612318565b614585565b6040513d86823e3d90fd5b6101908110156146fa57806502ba7def300002906502ba7def3000820403610fb0576101909004614515565b610320811015614726578065048c27395000029065048c27395000820403610fb0576103209004614515565b6106408110156147525780650746a52880000290650746a5288000820403610fb0576106409004614515565b610bb881101561477e5780650ae9f7bcc0000290650ae9f7bcc000820403610fb057610bb89004614515565b6113888110156147aa5780650da475abf0000290650da475abf000820403610fb0576113889004614515565b6127108110156147d657806512309ce5400002906512309ce54000820403610fb0576127109004614515565b614e208110156148025780651b48eb57e0000290651b48eb57e000820403610fb057614e209004614515565b619c4081101561482e5780652d79883d20000290652d79883d2000820403610fb057619c409004614515565b620186a081101561485c5780655af3107a40000290655af3107a4000820403610fb057620186a09004614515565b62030d4081101561488a578065886c98b76000029065886c98b76000820403610fb05762030d409004614515565b6207a1208110156148b8578065e35fa931a000029065e35fa931a000820403610fb0576207a1209004614515565b620f42408110156148e857806601c6bf5263400002906601c6bf52634000820403610fb057620f42409004614515565b806601c6bf5263400002906601c6bf52634000820403610fb057620f42409004614515565b6009546012549061491e8282612431565b15614981576124bc614936926124b660075442612431565b9061493f6125f3565b50505090821561496f575b62015180820282810462015180148315171561050d578361496a91612463565b929190565b916001810180911161050d579161494a565b5050600090600090600090565b90600d54916103e88102908082046103e8149015171561050d5760016149b76002548093612463565b9214801580614ab1575b156149db575050506149d76103e891829061247a565b0490565b60fa8310156149f6575050506149d76103e89160fa9061247a565b80614aa6575b614a0f575b506149d7906103e89261247a565b614a1b60075442612431565b6001810180911161050d57614a3560095460125490612431565b908115614a8c575b614a556103e895936117696149d79694600494612463565b1015614a6957506107d0905b925090614a01565b90610fa0821180614a84575b15614a6157610fa09150614a61565b506001614a75565b939192906001810180911161050d57919390929190614a3d565b506107d082116149fc565b506103e883116149c1565b600080916103788102908082046103781490151715610fb057600254614ae191612463565b606481028181046064148215171561102057610378900491610bb8831015614bb85750614b0d81612697565b80600f0290600f8204810361050d576274692202906207c2be82040361050d57620c08409004816297bb7002916297bb7083040361050d57610378614b5392049061246d565b601a549182614b63575b50505090565b6107d09192935010600014614b92576305f5e10091610ebb614b88926018549061247a565b045b388080614b5d565b5060185480610140029061014082040361050d57600a91614bb29161247a565b04614b8a565b9080601802906018820481036110205763074692200290808204624d9b6c1490151715610fb05761037890049063ce09d1b08201809211610f9c5750614b53565b91909160009182614c08612800565b801561100757614c1790612454565b9460175493614c268542612431565b94811561502057614c3d61287c6103ce8489612463565b5060065491838110614fdf575082611769614c589242612431565b9060025491808310614f7a575b5080915015613b0b57614c7790612454565b91614c828286612463565b90600d54916103e88102908082046103e81490151715610fb057614ca96002548092612463565b915060fa821015614ecb575050614cc56103e89160fa9061247a565b0491614cd18286612463565b90614ce060009160131c615359565b90610fa09280614e9f575b50610fa08311614e95575b6103e8831080614e8e575b15614dd057506103e89150614d1790829061247a565b0490600019810181811161050d5761253882614d55614d6796614d4f614d4984614d44614d4f998e612463565b61498e565b8661247a565b9061246d565b99614d628260009a612463565b615071565b9184614d71575b50565b670de0b6b3a76400008302838104670de0b6b3a76400001484151715610fb057614da18664746a52880092612463565b1015614d6e579091508364746a528800029064746a52880082048503610f9c5750670de0b6b3a7640000900490565b6101f483109081614deb575b50506103e891614d179161247a565b614df760075442612431565b9060018201809211610f9c5750916103e893916004614e3a614e31614d1796614e2560095460125490612431565b908115614e8557612463565b60025490612463565b1080918192614e7d575b5015614e5a57506101f491505b91819350614ddc565b60fa83109081614e74575b5015614e515760fa9150614e51565b90501538614e65565b905038614e44565b60019150612463565b5080614d01565b610fa09250614cf6565b9092506002546103e88102908082046103e81490151715613bcd5790614ec491612463565b9138614ceb565b6107d08211614ee3575b50614cc5906103e89261247a565b614eef60075442612431565b6001810180911161050d57614f0960095460125490612431565b908115614f60575b614f296103e89593611769614cc59694600494612463565b1015614f3d57506107d0905b925090614ed5565b90610fa0821180614f58575b15614f3557610fa09150614f35565b506001614f49565b939192906001810180911161050d57919390929190614f11565b614f9290614f8c8460011c8092612463565b93612463565b908015614fcb57600160fd1b819004831115614fb95750600160fd1b9150505b8038614c65565b614fc6926117699161247a565b614fb2565b634e487b7160e01b85526012600452602485fd5b9250505083945061253881615005614fff82614d4481614d67989a612463565b8261247a565b97614d628261501a614fff6103ce838d612463565b99612463565b60405162461bcd60e51b815260206004820152602360248201527f436f6d70656e736174696f6e206d75737420626520677265617465722074686160448201526206e20360ec1b6064820152608490fd5b9061507e9060131c615359565b91610fa09180615171575b50610fa08211615167575b6103e882108061515c575b156150b45750506149d76103e891829061247a565b60011480615151575b6150cf575b6149d7906103e89261247a565b6150db60075442612431565b906001820180921161050d576103e8926004615106614e316149d795614e2560095460125490612431565b108080615146575b1561512357506101f491505b925090506150c2565b60fa8310908161513d575b501561511a5760fa915061511a565b9050153861512e565b506101f4831061510e565b506101f481106150bd565b50600181141561509f565b610fa09150615094565b909150600254906103e88202918083046103e8149015171561050d5761519691612463565b9038615089565b607d81111561037657806103e8600160fd1b098180600003168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030291600181806000030401821515607d03029160000304170290565b80820290600019838209908280831092039180830392836103e811156103765714615264577fac083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d5936103e8910990828211900360fd1b910360031c170290565b50506103e891500490565b801561531757600081805b615303575061528881612952565b906152966040519283612318565b808252601f196152a582612952565b013660208401375b809280156152fc57600019820191821161050d578193600a8206603001928360301161050d57845111156125c957600a9260f81b6001600160f81b03191660001a908401601f015304916152ad565b5050905090565b9061530f600a91613343565b91048061527a565b50604051615326604082612318565b60018152600360fc1b602082015290565b908015610376578061534c6153529284612463565b9261284e565b6133895790565b600060018210615554576002821061554957600a821061553e5760648210615533576103e88210615528576161a8821061551c5761c3508210615510576201e8488210615504576203d09082106154f7576207a12082106154e557620f424082106154d957622dc6c082106154c757506298968081106154bc576301312d0081106154b1576302faf08081106154a6576305f5e100811061549b57630ee6b280811061548f57631dcd6500811061548357633b9aca008110615477576377359400811061546b5763b2d05e00811061545f5764012a05f2008110615453576509184e72a000624c4b409091048181029182040361050d5790565b5066246139ca80000090565b506612309ce540000090565b506609184e72a0000090565b5066048c273950000090565b50660246139ca8000090565b5066012309ce54000090565b50659184e72a000090565b506548c27395000090565b5065246139ca800090565b506512309ce5400090565b809150610f9c5750650da475abf00090565b50506509184e72a00090565b809150610f9c5750650610344c6aaa90565b90505065048c2739500090565b505065048c2739500090565b5050650246139ca80090565b505065012309ce540090565b5050649184e72a0090565b50506448c273950090565b505064246139ca8090565b50506412309ce54090565b50506409184e72a09056fea26469706673582212208b6a2f4e48277282ae24d5483fd67055ae947a614a18019515154e41704c856b64736f6c634300081c0033000000000000000000000000b379a851ac41bcdf0c2564b88916b10e5a08daae0000000000000000000000003ea249809f032b1f5ae7b1dd4986490d05ee2dc2
Deployed Bytecode
0x60806040526004361015610010575b005b60003560e01c8062819439146121de578063012d3edf146121c0578063035ccc44146121a257806305411d8814612183578063080ca6e2146121445780630a891b83146121285780630c179832146120f75780630c97e564146103a757806310294317146120d9578063150b7a021461208357806317da485f1461206a5780631801fbe5146116785780632381a60e1461165a578063240c3b701461161c5780632656e97f14611609578063294ce45d146115eb5780632b112e49146108e35780632d38bf7a146115cd5780632f104e0c146115a05780633179fabc1461157e57806332e997081461156357806334d5b131146115485780633730837c146115225780633c953615146115045780633dc8a068146114e657806343346f351461149f57806345d8a23214611481578063490203a7146114495780634cbf68fe1461142b5780634ef3762814610af15780634fa972e11461140d57806351736a13146110a75780635456bf1314611089578063577e9ec11461105d5780635a993ae91461103f578063646222c014610cb45780636d2bfdba14610c995780636de9f32b14610c7b57806373d21f8614610c21578063757991a814610b4d57806378e9792514610be657806381269a5614610b82578063822dec0514610b6b578063829965cc14610b4d57806387a2a9d614610b2d5780638a769d3514610b0f5780638ae0368b14610af15780638da5cb5b14610ac857806397566aa014610a7057806399f584b314610a525780639d30dffb146109cf578063a68eb88e146109b1578063b5ade81b14610994578063b83bd2bd1461090f578063bd92d4d4146108e8578063c0abebe0146108e3578063c212f073146108c5578063c4dd180c14610848578063c76ae54014610826578063c8ce67b914610742578063cb9ae70714610724578063ccadb30a14610628578063cf30901214610605578063d0856d16146105ec578063d0f66e4b146105d0578063d317140b146104aa578063da9816b614610491578063dc6e9cf914610473578063dfe95b0c14610455578063e186ca981461041a578063e38cfe1f146103f1578063e932012b146103d3578063ec11a769146103ac578063f23a6e61146103a7578063f4ec14181461037b5763f95d39190361000e5734610376576000366003190112610376576020601454604051908152f35b600080fd5b3461037657606036600319011261037657602061039f604435602435600435615071565b604051908152f35b612292565b3461037657600036600319011261037657602061039f6103ce60175442612431565b614abc565b34610376576000366003190112610376576020600754604051908152f35b34610376576000366003190112610376576001546040516001600160a01b039091168152602090f35b346103765761045161043461042e36612302565b90614bf9565b604080519384526020840192909252908201529081906060820190565b0390f35b3461037657602036600319011261037657602061039f600435614abc565b34610376576000366003190112610376576020604051620100008152f35b3461037657602061039f6104a436612302565b9061498e565b3461037657602036600319011261037657600054600435906001600160a01b0316330361059e57612710811015610523578060131b9080820462080000149015171561050d578015610376576104ff90612454565b600655602060405160018152f35b634e487b7160e01b600052601160045260246000fd5b60405162461bcd60e51b815260206004820152604760248201527f4e657720646966666963756c7479206d757374206265206174206c656173742060448201527f62656c6f7720313030303020307842544320646966666963756c7479206e6f74606482015266103434b3b432b960c91b608482015260a490fd5b60405162461bcd60e51b815260206004820152600a60248201526927b7363c9027bbb732b960b11b6044820152606490fd5b346103765760003660031901126103765761045161043461490d565b346103765760003660031901126103765761000e6144c9565b3461037657600036600319011261037657602060ff601354166040519015158152f35b346103765760003660031901126103765761064560075442612431565b6001810180911161050d5761065f60095460125490612431565b801561071c575b6106729060025461247a565b6103e88202918083046103e8149015171561050d5761069091612463565b60065490610fa08111610713575b60fa811061070b575b6106b08161519d565b8211156106fd5750600160fd1b90505b6201000081106106f3575b600160fd1b81116106e8575b80156103765761039f602091612454565b50600160fd1b6106d7565b50620100006106cb565b61070691615205565b6106c0565b5060fa6106a7565b50610fa061069e565b506001610666565b34610376576000366003190112610376576020600854604051908152f35b60a0366003190112610376576004356001600160401b0381116103765761076d903690600401612366565b6024356001600160401b0381116103765761078c9036906004016123c3565b906044356001600160a01b03811690819003610376578251926001840180941161050d576107b98461234f565b936107c76040519586612318565b8085526107d6601f199161234f565b0136602086013760005b81516001810180911161050d57811015610809578083610802600193886125df565b52016107e0565b61081a608435606435878588613ebc565b50602060405160018152f35b3461037657600036600319011261037657602061039f60095460125490612431565b60a0366003190112610376576004356001600160401b03811161037657610873903690600401612366565b6024356001600160401b038111610376576108929036906004016123c3565b604435906001600160401b038211610376576020926108b861039f9336906004016123c3565b6084359260643592613ebc565b34610376576000366003190112610376576020601b54604051908152f35b610c7b565b3461037657600036600319011261037657602061039f61090a60175442612431565b612732565b6080366003190112610376576004356001600160401b0381116103765761093a9036906004016123c3565b6024356001600160401b03811161037657610959903690600401612366565b90604435906001600160401b0382116103765760209261098061098a933690600401612366565b90606435926134c7565b6040519015158152f35b346103765760003660031901126103765760206040516107e08152f35b34610376576000366003190112610376576020601854604051908152f35b346103765760a0366003190112610376576084356001600160a01b038116810361037657604051610a3b81610a2d60208201946004359060443587916054939183526001600160601b03199060601b16602083015260348201520190565b03601f198101835282612318565b519020606435811161037657602090604051908152f35b34610376576000366003190112610376576020601554604051908152f35b3461037657606036600319011261037657600a546040805160208181019384523360601b6001600160601b031916928201929092526004356054820152909190610abd8160748101610a2d565b519020604051908152f35b34610376576000366003190112610376576000546040516001600160a01b039091168152602090f35b34610376576000366003190112610376576020600a54604051908152f35b34610376576000366003190112610376576020600654604051908152f35b3461037657600036600319011261037657604051600160fd1b8152602090f35b34610376576000366003190112610376576020600954604051908152f35b34610376576106d7610b7c36612302565b9061262b565b346103765760803660031901126103765760408051604435602082019081523360601b6001600160601b031916928201929092526004356054820152610bcb8160748101610a2d565b51902060643581116103765760209060405190602435148152f35b346103765760003660031901126103765760206040517f0000000000000000000000000000000000000000000000000000000068b32fa68152f35b346103765760203660031901126103765760a0610c4060175442612431565b610c53610c4b612858565b600435614bf9565b9060409392935193845260208401526040830152660ffba26e7b326b60608301526080820152f35b34610376576000366003190112610376576020600e54604051908152f35b3461037657600036600319011261037657602061039f6133d2565b34610376576080366003190112610376576024356001600160401b03811161037657610ce49036906004016123c3565b606435610cf360443582612431565b90610d0361090a83600435612463565b90610d0e845161258a565b6000935b8551851015610da7576001850180861161050d575b8651811015610d9b576001600160a01b03610d4282896125df565b51166001600160a01b03610d56888a6125df565b511614610d6557600101610d27565b60405162461bcd60e51b815260206004820152600e60248201526d4e6f2073616d6520746f6b656e7360901b6044820152606490fd5b50600190940193610d12565b9350936000935b808510610dfb578560405180916020820160208352815180915260206040840192019060005b818110610de2575050500390f35b8251845285945060209384019390920191600101610dd4565b60005b8251811015611034576000610e138786612431565b600183018084116110205790610e2b610e319261292b565b9061284e565b15610e40575b50600101610dfe565b60249060206001600160a01b03610e5785886125df565b5116604051938480926370a0823160e01b82523060048301525afa918215611013578792829190610fda575b5081610e91575b5050610e37565b600384061580610fd1575b80610fc4575b15610f2f575090610ebb610ec092610ebb600b5461292b565b61247a565b90610eca8161292b565b6305f5e1008102908082046305f5e100148115171561050d576501d1a94a20000290808204614e20149015171561050d57610f0a610f1a91600194615337565b610f14838b6125df565b5161246d565b610f24828a6125df565b529050848880610e8a565b91610ebb610f4292610ebb600b5461292b565b610f4b8361292b565b916305f5e1008302928084046305f5e1001481151715610fb0576501d1a94a20000292808404614e201490151715610f9c578215610f995750610f9460019392610f1a92612463565b610f0a565b80fd5b634e487b7160e01b81526011600452602490fd5b634e487b7160e01b82526011600452602482fd5b5063010c8e008311610ea2565b50831515610e9c565b915091506020813d821161100b575b81610ff660209383612318565b81010312611007575186918a610e83565b5080fd5b3d9150610fe9565b50604051903d90823e3d90fd5b634e487b7160e01b83526011600452602483fd5b509360010193610dae565b3461037657602036600319011261037657602061039f600435613375565b346103765760203660031901126103765760043560005260056020526020604060002054604051908152f35b3461037657602036600319011261037657602061039f600435613352565b34610376576000366003190112610376576a08f69750e81d45e9700000600e54116113c8576001546040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa80156113bc5760009061137f575b6a10d0a9ee1d64709720000091501061132e57600d546112f35760135460ff81166112ae5760ff19166001176013557f0000000000000000000000000000000000000000000000000000000068b32fa6428111159081611296575b501561124657600019430143811161050d574080600a55600b546111848161292b565b8015611230576802b5e3af16b188000004600d556001810180911161050d576111ac9061292b565b8015610376576111bb9061243e565b6a115eec47f6cf7e35000000036a115eec47f6cf7e35000000811161050d57600c55600160ea1b60065542600755436008556000601255600060095580600052600460205260ff604060002054166103765760005260046020526040600020600160ff19825416179055602060405160018152f35b634e487b7160e01b600052601260045260246000fd5b60405162461bcd60e51b815260206004820152602260248201527f37204461792077696e646f7720746f20616374697661746520537461727454696044820152616d6560f01b6064820152608490fd5b905062093a80810180911161050d5742111581611161565b60405162461bcd60e51b815260206004820152601860248201527f4f6e6c7920616c6c6f77656420746f2072756e206f6e636500000000000000006044820152606490fd5b60405162461bcd60e51b8152602060048201526013602482015272726577617264206d757374206265207a65726f60681b6044820152606490fd5b60405162461bcd60e51b815260206004820152602360248201527f4d75737420737570706c7920322a31305f3136345f313030206d696e20746f6b604482015262656e7360e81b6064820152608490fd5b506020813d6020116113b4575b8161139960209383612318565b81010312610376576a10d0a9ee1d6470972000009051611106565b3d915061138c565b6040513d6000823e3d90fd5b60405162461bcd60e51b815260206004820152601e60248201527f43616e74206d696e7420746f6b656e73206265666f7265206c61756e636800006044820152606490fd5b34610376576000366003190112610376576020600c54604051908152f35b34610376576000366003190112610376576020601954604051908152f35b3461037657600036600319011261037657611465600b5461292b565b801561123057602090604051906802b5e3af16b1880000048152f35b34610376576000366003190112610376576020600254604051908152f35b6080366003190112610376576114b3612239565b6024356001600160401b038111610376576020916114d861039f923690600401612366565b90606435916044359161299d565b34610376576000366003190112610376576020601654604051908152f35b34610376576000366003190112610376576020601a54604051908152f35b346103765760003660031901126103765760206040516a115eec47f6cf7e350000008152f35b3461037657600036600319011261037657602061039f612858565b3461037657600036600319011261037657602061039f612800565b34610376576000366003190112610376576020604051660ffba26e7b326b8152f35b346103765760003660031901126103765760135460405160089190911c6001600160a01b03168152602090f35b34610376576000366003190112610376576020600b54604051908152f35b3461037657602036600319011261037657602061039f600435612732565b3461037657602061039f610b7c36612302565b34610376576000366003190112610376576104516116386125f3565b6040805194855260208501939093529183015260608201529081906080820190565b34610376576000366003190112610376576020600d54604051908152f35b3461037657604036600319011261037657604080516116978282612318565b60018152601f1982013660208301376004356116b2826125bc565b526000916116be612858565b90836017549260025491600a549060065490885b885181101561205d576116e5818a6125df565b518751602081018681523360601b6001600160601b031916604083015260548201929092526117178160748101610a2d565b5190209161172d6117288486612463565b613375565b6107e061173a828461246d565b11612039575b8661174b828461246d565b1061200e575061175b8187612431565b61176e876117698c42612431565b612463565b80891015611fd75761178e6117878a60011c8093612463565b918a612463565b906006548015611fc3578e918c91600160fd1b819004821115611fac57505050508015611f9857600160fd1b0460ff8a8e5b8981526003602052818120888252602052205416908115611f8d575b50611f82576117ec905b8261246d565b908110611dca57806107e09193868d526003602052898d20908d52602052888c20600160ff198254161790551015611f705784821015611830576001905b016116d2565b50505090809293949550925b83159586611f2057846117698261185a8361176961186a9642612431565b50611863612570565b5042612431565b6103788102908082046103781490151715611f0c579061188991612463565b606481029080820460641490151715611ef8576103786064910411611ed8575b6118b38284614bf9565b9391908194816118c581600f5461246d565b600f55818110611dce57506118d991612431565b8801808911611c0057915b60095490808710611d19576118f9908261246d565b908110611c1457600955600e546a115eec47f6cf7e3500000010611d10575b6119206144c9565b61192c60075442612431565b60018101809111611c00576009549061195261194a60125484612431565b60025461247a565b916012556103e88102908082046103e81490151715611c56579061197591612463565b610fa08111611d07575b60fa8110611cff575b6119918161519d565b6006549190821115611cee575050600160fd1b6006555b4260075414611cba5742600755436008556201000060065410611cae575b600654600160fd1b10611ca1575b6000194301438111611c005740600a548751602081019183835289820152888152611a00606082612318565b519020808a52600460205260ff888b205416611c6a57808a526004602052878a20600160ff19825416179055600a558089526005602052868920549060018201809211611c5657906003918a52600560205280888b205511611c24575b600e54611a6a828261246d565b908110611c1457600c541080611c18575b611b6a575b50600154855163a9059cbb60e01b81523360048201526024810185905290602090829060449082908c906001600160a01b03165af18015611b6057611b33575b50600e54611ace848261246d565b908110611b2f57968080809360209a600e5542601755335af150611af061296d565b50600954845192835286830152838201527fcf6fbb9dcea7d07263ab4f5c3a92f53af33dffc421d9d121e1c74b307e68189d60603392a2505190158152f35b8780fd5b611b549060203d602011611b59575b611b4c8183612318565b81019061293a565b611ac0565b503d611b42565b86513d8a823e3d90fd5b909250600b546001810190818111611c005760029082600b5501808211611c0057611b949061292b565b8015611c1457611ba39061243e565b6a115eec47f6cf7e35000000036a115eec47f6cf7e350000008111611c0057600c55611bce9061292b565b8015611bec576802b5e3af16b188000004600d5560011c9187611a80565b634e487b7160e01b88526012600452602488fd5b634e487b7160e01b89526011600452602489fd5b8880fd5b50603b600b5410611a7b565b855162461bcd60e51b815260206004820152600b60248201526a4d617820332074696d657360a81b6044820152606490fd5b634e487b7160e01b8a52601160045260248afd5b875162461bcd60e51b815260206004820152601060248201526f75736564204368616c206265666f726560801b6044820152606490fd5b600160fd1b6006556119d4565b620100006006556119c6565b855162461bcd60e51b815260206004820152600d60248201526c4e6f2073616d6520626c6f636b60981b6044820152606490fd5b611cf791615205565b6006556119a8565b5060fa611988565b50610fa061197f565b87600d55611918565b6107e0036107e08111611c565786611d309161246d565b611d3a8782612431565b91611d45888261246d565b908110611dca576009556101f882109182611dbd575b8215611d9e575b8215611d7d575b505015611a5d57611d786144c9565b611a5d565b6105e811915081611d91575b508980611d69565b6105e89150101589611d89565b91506103f0821080611db1575b91611d62565b506103f0811015611dab565b6101f88210159250611d5b565b8a80fd5b90611dd99250612431565b80611ded578803888111611c0057916118e4565b604460458a89611ea46004600c611e0f611e09611eca9961526f565b9561526f565b845196879160208301977f4e65656420746f2073656e64207265717569726564204554482e20526571756989526403932b21d160dd1b88850152611e5c8151809260208688019101612908565b83016b0103bb2b4961029b2b73a1d160a51b83820152611e86825180936020605185019101612908565b0101632077656960e01b838201520301601b19810186520184612318565b5193849262461bcd60e51b84526020600485015251809281602486015285850190612908565b601f01601f19168101030190fd5b601954611ee5848261246d565b908110611ef4576019556118a9565b8680fd5b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b88526011600452602488fd5b855162461bcd60e51b8152602060048201526024808201527f4d75737420686176652076616c696420736f6c766520696e2074686520616e736044820152637765727360e01b6064820152608490fd5b5050509091929394506107e09261183c565b50915060019061182a565b90508410158d6117dc565b634e487b7160e01b8d52601260045260248dfd5b93611769611fbd9260ff959661247a565b926117c0565b634e487b7160e01b8f52601260045260248ffd5b50858c526003602052888c20848d5260205260ff898d2054168015612004575b611f82576117ec906117e6565b5084841015611ff7565b858c526003602052888c20848d5260205260ff898d205416801561200457611f82576117ec906117e6565b50806107e0036107e081111561174057634e487b7160e01b8c52601160045260248cfd5b509495965050909161183c565b34610376576000366003190112610376576106d7612800565b346103765760803660031901126103765761209c612239565b506120a561224f565b506064356001600160401b038111610376576120c5903690600401612265565b5050604051630a85bd0160e11b8152602090f35b34610376576000366003190112610376576020601754604051908152f35b34610376576020366003190112610376576004356000526004602052602060ff604060002054166040519015158152f35b346103765760003660031901126103765761045161163861248d565b346103765760403660031901126103765760043560005260036020526040600020602435600052602052602060ff604060002054166040519015158152f35b3461037657600036600319011261037657602061039f60175442612431565b34610376576000366003190112610376576020600f54604051908152f35b34610376576000366003190112610376576020601254604051908152f35b34610376576000366003190112610376576019546121fa6133d2565b9061045161220d60095460125490612431565b612215612858565b90604051948594859094939260609260808301968352602083015260408201520152565b600435906001600160a01b038216820361037657565b602435906001600160a01b038216820361037657565b9181601f84011215610376578235916001600160401b038311610376576020838186019501011161037657565b3461037657600060a0366003190112610f9957600435906001600160a01b0382168203610f995750506024356001600160a01b038116810361037657506084356001600160401b038111610376576122ee903690600401612265565b505060405163f23a6e6160e01b8152602090f35b6040906003190112610376576004359060243590565b90601f801991011681019081106001600160401b0382111761233957604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b0381116123395760051b60200190565b9080601f8301121561037657813561237d8161234f565b9261238b6040519485612318565b81845260208085019260051b82010192831161037657602001905b8282106123b35750505090565b81358152602091820191016123a6565b9080601f83011215610376578135906123db8261234f565b926123e96040519485612318565b82845260208085019360051b82010191821161037657602001915b8183106124115750505090565b82356001600160a01b038116810361037657815260209283019201612404565b9190820391821161050d57565b8015611230576a115eec47f6cf7e350000000490565b801561123057600160fd1b0490565b8115611230570490565b9190820180921161050d57565b8181029291811591840414171561050d57565b6009546012549061249e8282612431565b15612560576124bc6124c2926124b660075442612431565b92612431565b90612463565b801561253e575b600d54906103e88102918115928281046103e81484171561050d576103e8916124f86125089260025490612463565b838111156125265750829061247a565b049161123057806301e133800492612520848461247a565b93929190565b60fa811015612538575060fa9061247a565b9061247a565b60018101809111156124c957634e487b7160e01b600052601160045260246000fd5b5050600090600090600090600090565b612578612800565b80156103765761258790612454565b90565b906125948261234f565b6125a16040519182612318565b82815280926125b2601f199161234f565b0190602036910137565b8051156125c95760200190565b634e487b7160e01b600052603260045260246000fd5b80518210156125c95760209160051b010190565b61016d6125fe61248d565b5050500490811561261f57600c5491600e5491612520826117698587612431565b60009150819081908190565b9190916126416000936117696002549342612431565b80821061264c575050565b819293506126616126679260011c8092612463565b92612463565b600654801561123057600160fd1b819004831161268b57612587926117699161247a565b50600160fd1b92915050565b600090801561272b5780806001146127235760021461271b5760016101338210166001600b8310161761270d579060019060025b600181116126e4575082600019048211610f9c57500290565b9280600019048111610fb05760018416612704575b80029260011c6126cb565b809202916126f9565b6002900a919080610f9c5750565b506004919050565b505050600190565b5050600090565b610378810290808204610378149015171561050d5760025461275391612463565b606481028181046064148215171561050d57610378610bb89104106000146127c45761277e81612697565b80600f0290600f8204810361050d576274692202906207c2be82040361050d57620c08409004816297bb7002916297bb7083040361050d5761037861258792049061246d565b806018029060188204810361050d5763074692200290808204624d9b6c149015171561050d57610378900463ce09d1b0810180911161050d5790565b600161280a612858565b14612816575b60065490565b6002546017546128268142612431565b8210612833575050612810565b6128406126679142612431565b6126618360011c8092612463565b8115611230570690565b6009546012549061286b60075442612431565b6002549061288261287c8585612431565b8361247a565b916107e08102908082046107e0149015171561050d576001600160fe1b038316830361050d576128b28585612431565b9260021b821192836128fd575b5082156128f3575b5050156128d5575050600190565b6107e0916128e291612431565b066107e0036107e0811161050d5790565b10905038806128c7565b60fc109250386128bf565b60005b83811061291b5750506000910152565b818101518382015260200161290b565b60ff811161050d576001901b90565b90816020910312610376575180151581036103765790565b6001600160401b03811161233957601f01601f191660200190565b3d15612998573d9061297e82612952565b9161298c6040519384612318565b82523d6000602084013e565b606090565b9092916129a8612858565b91600091826017549060025492600a5495600654925b8a51811015613334576129d1818c6125df565b51604051612a0881610a2d60208201948d339087916054939183526001600160601b03199060601b16602083015260348201520190565b51902091612a196117288487612463565b84612a24828461246d565b11613324575b8a612a35828461246d565b106132f35750612a45818b612431565b612a538b6117698942612431565b808910156132b657612a6c6117878a60011c8093612463565b90600654801561123057600160fd1b8190048211156132a3575050801561123057600160fd1b045b8a600052600360205260406000208560005260205260ff60406000205416908115613298575b5061328d57612ac9908261246d565b90811061037657808491938a60005260036020526040600020906000526020526040600020600160ff19825416179055101561327c5788821015612b11576001905b016129be565b505050509091929380959650955b861561322b57612b33876117698442612431565b106131815785611769612b4892611863612570565b90610378820291808304610378149015171561050d57612b6791612463565b60648102908082046064149015171561050d576103786064910411613165575b612b918385614bf9565b829195929580612ba381600f5461246d565b600f558281106130645750612bc191612bbb91612431565b3461246d565b915b60095490808810612fb357612bd8908261246d565b90811061037657600955600e546a115eec47f6cf7e3500000010612fa9575b612bff6144c9565b612c0b60075442612431565b6001810180911161050d57600954612c2861194a60125483612431565b906012556103e88202918083046103e8149015171561050d57612c4a91612463565b610fa08111612fa0575b60fa8110612f98575b612c668161519d565b6006549190821115612f87575050600160fd1b6006555b4260075414612f525742600755436008556201000060065410612f46575b600654600160fd1b10612f39575b600019430143811161050d5740600a546040516020810191838352604082015260408152612cd8606082612318565b51902080600052600460205260ff60406000205416612f01578060005260046020526040600020600160ff19825416179055600a558060005260056020526040600020546001810180911161050d5760039160005260056020528060406000205511612ece575b600e54612d4c828261246d565b90811061037657600c541080612ec2575b612e3f575b5060015460405163a9059cbb60e01b81526001600160a01b03848116600483015260248201879052909160209183916044918391600091165af180156113bc57612e22575b50600e5491612db6858461246d565b92831061037657600e9290925542601755600091829182918291906001600160a01b03165af150612de561296d565b50600954604051928352602083015260408201527fcf6fbb9dcea7d07263ab4f5c3a92f53af33dffc421d9d121e1c74b307e68189d60603392a290565b612e3a9060203d602011611b5957611b4c8183612318565b612da7565b909350600b54600181019081811161050d5760029082600b550180821161050d57612e699061292b565b801561037657612e789061243e565b6a115eec47f6cf7e3500000003906a115eec47f6cf7e35000000821161050d57612ea491600c5561292b565b8015611230576802b5e3af16b188000004600d5560011c9238612d62565b50603b600b5410612d5d565b60405162461bcd60e51b815260206004820152600b60248201526a4d617820332074696d657360a81b6044820152606490fd5b60405162461bcd60e51b815260206004820152601060248201526f75736564204368616c206265666f726560801b6044820152606490fd5b600160fd1b600655612ca9565b62010000600655612c9b565b60405162461bcd60e51b815260206004820152600d60248201526c4e6f2073616d6520626c6f636b60981b6044820152606490fd5b612f9091615205565b600655612c7d565b5060fa612c5d565b50610fa0612c54565b6000600d55612bf7565b6107e0036107e0811161050d5787612fca9161246d565b612fd48882612431565b91612fdf898261246d565b908110610376576009556101f882109182613057575b8215613038575b8215613017575b505015612d3f576130126144c9565b612d3f565b6105e81191508161302b575b503880613003565b6105e89150101538613023565b91506103f082108061304b575b91612ffc565b506103f0811015613045565b6101f88210159250612ff5565b905061306f91612431565b803410613086576130809034612431565b91612bc3565b60446045613096611eca9361526f565b61313d6004600c6130a63461526f565b60405195869160208301967f4e65656420746f2073656e64207265717569726564204554482e20526571756988526403932b21d160dd1b60408501526130f58151809260208688019101612908565b83016b0103bb2b4961029b2b73a1d160a51b8382015261311f825180936020605185019101612908565b0101632077656960e01b838201520301601b19810185520183612318565b60405193849262461bcd60e51b84526020600485015251809281602486015285850190612908565b601954613172858261246d565b90811061037657601955612b87565b60405162461bcd60e51b815260206004820152607060248201527f4e6f7420656e6f75676820446966666572656e636520696e2070726576426c6f60448201527f636b54696d65202f20476f6f644c6f6f70732c20636f6d706172656420746f2060648201527f6d696e50726576696f7573426c6f636b54696d65446966666572656e6365206660848201526f756e6374696f6e207661726961626c6560801b60a482015260c490fd5b60405162461bcd60e51b8152602060048201526024808201527f4d75737420686176652076616c696420736f6c766520696e2074686520616e736044820152637765727360e01b6064820152608490fd5b505091929394959697505095612b1f565b509150600190612b0b565b905084101538612aba565b6132b192916117699161247a565b612a94565b5089600052600360205260406000208460005260205260ff6040600020541680156132e9575b61328d57612ac9906117e6565b50858410156132dc565b89600052600360205260406000208460005260205260ff6040600020541680156132e95761328d57612ac9906117e6565b5061332f8185612431565b612a2a565b50985050509091929394612b1f565b600019811461050d5760010190565b6000905b60018111613362575090565b61336f9060011c91613343565b90613356565b60048110613397576133899060011c613352565b6001810180911161050d5790565b50600190565b9190916000838201938412911290801582169115161761050d57565b8181039291600013801582851316918412161761050d57565b600954601254906133ea600754926124b68442612431565b916002546107e08102908082046107e0148115171561050d578461340d9161247a565b600281901b93906001600160fe1b0381160361050d5783811190816134bc575b81156134b2575b506134a95761344f60fc9161344a42918561339d565b6133b9565b931161346a575b505060008113156134645790565b50600090565b61344a61347892429261339d565b6000811380613495575b61348d575b80613456565b905038613487565b508181128061348257506000821315613482565b50505050600090565b9050811038613434565b60fc8611915061342d565b919260016134d3612858565b1480613ea4575b80613e98575b15613e62578251825103613e25576000906134f9612858565b90826017549360025490600a549360065491845b8b51811015613e1557613520818d6125df565b5160405161355681610a2d6020820194338d87916054939183526001600160601b03199060601b16602083015260348201520190565b519020916135676117288487612463565b84613572828461246d565b11613e05575b89613583828461246d565b10613dd85750613593818a612431565b6135a18a6117698d42612431565b80881015613d9f576135c16135ba8960011c8093612463565b9189612463565b906006548015613d8b57600160fd1b819004821115613d785750508015613d6457600160fd1b045b898952600360205260408920858a5260205260ff60408a205416908115613d59575b50613d4e5761361a908261246d565b908110611ef4578084919389895260036020526040892090895260205260408820600160ff198254161790551015613d3c578782101561365e576001905b0161350d565b50505050909192809495969750945b851561322b57856117698261185a836117696136899642612431565b610378810290808204610378149015171561102057906136a891612463565b606481029080820460641490151715610fb0576103786064910411613d20575b6136d28385614bf9565b8291959295806136e481600f5461246d565b600f55828110613cfe57506136fc91612bbb91612431565b915b60095490808810613c4957613713908261246d565b908110613be157600955600e546a115eec47f6cf7e3500000010613c40575b61373a6144c9565b61374660075442612431565b60018101809111613bcd576009549061376461194a60125484612431565b916012556103e88102908082046103e81490151715613bf1579061378791612463565b610fa08111613c37575b60fa8110613c2f575b6137a38161519d565b6006549190821115613c1e575050600160fd1b6006555b4260075414612f525742600755436008556201000060065410613c12575b600654600160fd1b10613c05575b6000194301438111613bcd5740600a546040516020810191838352604082015260408152613815606082612318565b519020808552600460205260ff604086205416612f0157808552600460205260408520600160ff19825416179055600a55808452600560205260408420549060018201809211613bf157906003918552600560205280604086205511612ece575b600e54613883828261246d565b908110613be157600c541080613be5575b613b37575b5060015460405163a9059cbb60e01b815233600482015260248101869052906020908290604490829087906001600160a01b03165af18015613b2c57613b0f575b50600e546138e8858261246d565b908110613b0b578280928192600e5542601755335af15061390761296d565b50600954604051928352602083015260408201527fcf6fbb9dcea7d07263ab4f5c3a92f53af33dffc421d9d121e1c74b307e68189d60603392a250600090815b8351811015613b02576001600160a01b0361396282866125df565b511661396e82846125df565b516040516301ffc9a760e01b8152636cdb3d1360e11b6004820152602081602481865afa869181613ae2575b50613a7d575b506040516301ffc9a760e01b81526380ac58cd60e01b6004820152602081602481865afa869181613a5d575b506139df575b5050506001905b01613947565b6139e957806139d2565b813b15613a595784809260a482936040519485938492635c46a7ef60e11b84523060048501523360248501526044840152608060648401528160848401525af19182613a49575b5050613a3e576001906139d9565b505060195550600190565b613a5291612318565b3884613a30565b8480fd5b613a7691925060203d8111611b5957611b4c8183612318565b90386139cc565b613a8757386139a0565b813b15613a595784809260c482936040519485938492637921219560e11b845230600485015233602485015260448401526001606484015260a060848401528160a48401525af19182613a49575050613a3e576001906139d9565b613afb91925060203d8111611b5957611b4c8183612318565b903861399a565b50505050600190565b8280fd5b613b279060203d602011611b5957611b4c8183612318565b6138da565b6040513d85823e3d90fd5b909350600b546001810190818111613bcd5760029082600b5501808211613bcd57613b619061292b565b8015613be157613b709061243e565b6a115eec47f6cf7e35000000036a115eec47f6cf7e350000008111613bcd57600c55613b9b9061292b565b8015613bb9576802b5e3af16b188000004600d5560011c9238613899565b634e487b7160e01b83526012600452602483fd5b634e487b7160e01b84526011600452602484fd5b8380fd5b50603b600b5410613894565b634e487b7160e01b85526011600452602485fd5b600160fd1b6006556137e6565b620100006006556137d8565b613c2791615205565b6006556137ba565b5060fa61379a565b50610fa0613791565b82600d55613732565b6107e0036107e08111613bf15787613c609161246d565b613c6a8882612431565b91613c75898261246d565b908110613cfa576009556101f882109182613ced575b8215613cce575b8215613cad575b50501561387657613ca86144c9565b613876565b6105e811915081613cc1575b503880613c99565b6105e89150101538613cb9565b91506103f0821080613ce1575b91613c92565b506103f0811015613cdb565b6101f88210159250613c8b565b8580fd5b9050613d0991612431565b80341061308657613d1a9034612431565b916136fe565b601954613d2d858261246d565b908110611007576019556136c8565b5050919293949596979850509461366d565b509150600190613658565b90508410153861360b565b634e487b7160e01b89526012600452602489fd5b613d8692916117699161247a565b6135e9565b634e487b7160e01b8b52601260045260248bfd5b5088885260036020526040882084895260205260ff6040892054168015613dce575b613d4e5761361a906117e6565b5085841015613dc1565b88885260036020526040882084895260205260ff6040892054168015613dce57613d4e5761361a906117e6565b50613e108185612431565b613578565b509798995050509091929361366d565b60405162461bcd60e51b8152602060048201526015602482015274082e4e4c2f240d8cadccee8d040dad2e6dac2e8c6d605b1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d1391950810591a9d5cdd0810985960921b6044820152606490fd5b5060fc601954116134e0565b506005613eb660095460125490612431565b106134da565b60175461176996959294613ef49361090a93613eeb92906001600160a01b03613ee4896125bc565b511661299d565b96879142612431565b926009549460009185156144bf57835185519060018201809211613bf157036144545760018060a01b036001541695613f2d865161258a565b92845b8751811015613fac57886001600160a01b03613f4c838b6125df565b511614613f5b57600101613f30565b60405162461bcd60e51b8152602060048201526024808201527f4e6f7420616c6c6f77656420746f204552433230206d696e74204d61696e205460448201526337b5b2b760e11b6064820152608490fd5b5090929594979193965086905b80821061414c5750505060005b85811080614142575b156140f5576001600160a01b03613fe682866125df565b511690613ff381876125df565b518061400a575b506140059150613343565b613fc6565b60135460405163a9059cbb60e01b815260089190911c6001600160a01b03166004820152602481018290526020816044816000885af180156113bc576140d9575b50600182019081831161050d576140a7936020926001600160a01b0390614072908d6125df565b5116600060405180978195829463a9059cbb60e01b84526004840160209093929193604081019460018060a01b031681520152565b03925af19182156113bc576140059215613ffa576140d29060203d8111611b5957611b4c8183612318565b5038613ffa565b6140f09060203d8111611b5957611b4c8183612318565b61404b565b5093925093505060095490600a54604051928352602083015260408201528160608201527f87e5a7775b8ac2ead741e32752431bffeff76ec5f347cc202a6bad454653930b60803392a290565b5083518110613fcf565b909497600097949796939296975b89518910156144455760018901808a1161050d5761418061417a8261292b565b8a61284e565b614214575b8a51811015614208576001600160a01b036141a0828d6125df565b51166001600160a01b036141b48c8e6125df565b5116146141c357600101614185565b60405162461bcd60e51b815260206004820152601b60248201527f4e6f207072696e74696e67205468652073616d6520746f6b656e7300000000006044820152606490fd5b5060019098019761415a565b50989593989694909192965b88156144365788821061442e575b60005b89811080614424575b15614401576001810180821161050d5761425661425c9161292b565b8861284e565b15614270575b61426b90613343565b614231565b6000806001600160a01b03614285848c6125df565b511660405160208101906370a0823160e01b8252306024820152602481526142ae604482612318565b51915afa6142ba61296d565b90806143f5575b156143ed57805160208083019260009281010312610f995750515b806142e8575b50614262565b896003830615806143e4575b806143d7575b15614371576143089161247a565b906143128161292b565b916305f5e1008302928084046305f5e100148115171561050d576501d1a94a20000292808404614e20149015171561050d5761436a826143648f9361426b9661435a91615337565b610f1483866125df565b926125df565b52906142e2565b61437a9161247a565b906143848161292b565b916305f5e1008302928084046305f5e100148115171561050d576501d1a94a20000292808404614e20149015171561050d5782156103765761436a826143648f9361426b966143d291612463565b61435a565b5063010c8e0081116142fa565b508215156142f4565b5060006142dc565b506020815110156142c1565b50949097509795929097600019810190811161050d57600190915b019091613fb9565b508751811061423a565b88915061422e565b9491989693600191985061441c565b98959398969490919296614220565b60405162461bcd60e51b815260206004820152603a60248201527f4d696e74546f2068617320746f206861766520616e206578747261206164647260448201527f65737320636f6d706172656420746f20457874726146756e64730000000000006064820152608490fd5b9550509250505090565b6000606447818102918115918304141715610fb057670214e8348c4d796090048060155560c881106000146146ce57806501a3185c500002906501a3185c5000820403610fb05760c890045b601855614527600e5460105490612431565b614536600f5460115490612431565b60015460135460405163a9059cbb60e01b81526001600160a01b0360089290921c8216600482015260248101859052929392916020918391168187816044810103925af180156146c3576146a6575b50614593601454918261246d565b908110613b0b57601455476018546107e08102908082046107e01490151715613bcd5760011c9081605002916050830403613bcd57839291101561469c576013548291829182919060081c6001600160a01b03165af16145f161296d565b5015614661576001601a5560135460081c6001600160a01b0316803b1561100757818091600460405180948193636645e41360e01b83525af1801561465657614646575b50505b600e54601055600f54601155565b8161465091612318565b38614635565b6040513d84823e3d90fd5b60405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b6044820152606490fd5b5050601a55614638565b6146be9060203d602011611b5957611b4c8183612318565b614585565b6040513d86823e3d90fd5b6101908110156146fa57806502ba7def300002906502ba7def3000820403610fb0576101909004614515565b610320811015614726578065048c27395000029065048c27395000820403610fb0576103209004614515565b6106408110156147525780650746a52880000290650746a5288000820403610fb0576106409004614515565b610bb881101561477e5780650ae9f7bcc0000290650ae9f7bcc000820403610fb057610bb89004614515565b6113888110156147aa5780650da475abf0000290650da475abf000820403610fb0576113889004614515565b6127108110156147d657806512309ce5400002906512309ce54000820403610fb0576127109004614515565b614e208110156148025780651b48eb57e0000290651b48eb57e000820403610fb057614e209004614515565b619c4081101561482e5780652d79883d20000290652d79883d2000820403610fb057619c409004614515565b620186a081101561485c5780655af3107a40000290655af3107a4000820403610fb057620186a09004614515565b62030d4081101561488a578065886c98b76000029065886c98b76000820403610fb05762030d409004614515565b6207a1208110156148b8578065e35fa931a000029065e35fa931a000820403610fb0576207a1209004614515565b620f42408110156148e857806601c6bf5263400002906601c6bf52634000820403610fb057620f42409004614515565b806601c6bf5263400002906601c6bf52634000820403610fb057620f42409004614515565b6009546012549061491e8282612431565b15614981576124bc614936926124b660075442612431565b9061493f6125f3565b50505090821561496f575b62015180820282810462015180148315171561050d578361496a91612463565b929190565b916001810180911161050d579161494a565b5050600090600090600090565b90600d54916103e88102908082046103e8149015171561050d5760016149b76002548093612463565b9214801580614ab1575b156149db575050506149d76103e891829061247a565b0490565b60fa8310156149f6575050506149d76103e89160fa9061247a565b80614aa6575b614a0f575b506149d7906103e89261247a565b614a1b60075442612431565b6001810180911161050d57614a3560095460125490612431565b908115614a8c575b614a556103e895936117696149d79694600494612463565b1015614a6957506107d0905b925090614a01565b90610fa0821180614a84575b15614a6157610fa09150614a61565b506001614a75565b939192906001810180911161050d57919390929190614a3d565b506107d082116149fc565b506103e883116149c1565b600080916103788102908082046103781490151715610fb057600254614ae191612463565b606481028181046064148215171561102057610378900491610bb8831015614bb85750614b0d81612697565b80600f0290600f8204810361050d576274692202906207c2be82040361050d57620c08409004816297bb7002916297bb7083040361050d57610378614b5392049061246d565b601a549182614b63575b50505090565b6107d09192935010600014614b92576305f5e10091610ebb614b88926018549061247a565b045b388080614b5d565b5060185480610140029061014082040361050d57600a91614bb29161247a565b04614b8a565b9080601802906018820481036110205763074692200290808204624d9b6c1490151715610fb05761037890049063ce09d1b08201809211610f9c5750614b53565b91909160009182614c08612800565b801561100757614c1790612454565b9460175493614c268542612431565b94811561502057614c3d61287c6103ce8489612463565b5060065491838110614fdf575082611769614c589242612431565b9060025491808310614f7a575b5080915015613b0b57614c7790612454565b91614c828286612463565b90600d54916103e88102908082046103e81490151715610fb057614ca96002548092612463565b915060fa821015614ecb575050614cc56103e89160fa9061247a565b0491614cd18286612463565b90614ce060009160131c615359565b90610fa09280614e9f575b50610fa08311614e95575b6103e8831080614e8e575b15614dd057506103e89150614d1790829061247a565b0490600019810181811161050d5761253882614d55614d6796614d4f614d4984614d44614d4f998e612463565b61498e565b8661247a565b9061246d565b99614d628260009a612463565b615071565b9184614d71575b50565b670de0b6b3a76400008302838104670de0b6b3a76400001484151715610fb057614da18664746a52880092612463565b1015614d6e579091508364746a528800029064746a52880082048503610f9c5750670de0b6b3a7640000900490565b6101f483109081614deb575b50506103e891614d179161247a565b614df760075442612431565b9060018201809211610f9c5750916103e893916004614e3a614e31614d1796614e2560095460125490612431565b908115614e8557612463565b60025490612463565b1080918192614e7d575b5015614e5a57506101f491505b91819350614ddc565b60fa83109081614e74575b5015614e515760fa9150614e51565b90501538614e65565b905038614e44565b60019150612463565b5080614d01565b610fa09250614cf6565b9092506002546103e88102908082046103e81490151715613bcd5790614ec491612463565b9138614ceb565b6107d08211614ee3575b50614cc5906103e89261247a565b614eef60075442612431565b6001810180911161050d57614f0960095460125490612431565b908115614f60575b614f296103e89593611769614cc59694600494612463565b1015614f3d57506107d0905b925090614ed5565b90610fa0821180614f58575b15614f3557610fa09150614f35565b506001614f49565b939192906001810180911161050d57919390929190614f11565b614f9290614f8c8460011c8092612463565b93612463565b908015614fcb57600160fd1b819004831115614fb95750600160fd1b9150505b8038614c65565b614fc6926117699161247a565b614fb2565b634e487b7160e01b85526012600452602485fd5b9250505083945061253881615005614fff82614d4481614d67989a612463565b8261247a565b97614d628261501a614fff6103ce838d612463565b99612463565b60405162461bcd60e51b815260206004820152602360248201527f436f6d70656e736174696f6e206d75737420626520677265617465722074686160448201526206e20360ec1b6064820152608490fd5b9061507e9060131c615359565b91610fa09180615171575b50610fa08211615167575b6103e882108061515c575b156150b45750506149d76103e891829061247a565b60011480615151575b6150cf575b6149d7906103e89261247a565b6150db60075442612431565b906001820180921161050d576103e8926004615106614e316149d795614e2560095460125490612431565b108080615146575b1561512357506101f491505b925090506150c2565b60fa8310908161513d575b501561511a5760fa915061511a565b9050153861512e565b506101f4831061510e565b506101f481106150bd565b50600181141561509f565b610fa09150615094565b909150600254906103e88202918083046103e8149015171561050d5761519691612463565b9038615089565b607d81111561037657806103e8600160fd1b098180600003168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030291600181806000030401821515607d03029160000304170290565b80820290600019838209908280831092039180830392836103e811156103765714615264577fac083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d5936103e8910990828211900360fd1b910360031c170290565b50506103e891500490565b801561531757600081805b615303575061528881612952565b906152966040519283612318565b808252601f196152a582612952565b013660208401375b809280156152fc57600019820191821161050d578193600a8206603001928360301161050d57845111156125c957600a9260f81b6001600160f81b03191660001a908401601f015304916152ad565b5050905090565b9061530f600a91613343565b91048061527a565b50604051615326604082612318565b60018152600360fc1b602082015290565b908015610376578061534c6153529284612463565b9261284e565b6133895790565b600060018210615554576002821061554957600a821061553e5760648210615533576103e88210615528576161a8821061551c5761c3508210615510576201e8488210615504576203d09082106154f7576207a12082106154e557620f424082106154d957622dc6c082106154c757506298968081106154bc576301312d0081106154b1576302faf08081106154a6576305f5e100811061549b57630ee6b280811061548f57631dcd6500811061548357633b9aca008110615477576377359400811061546b5763b2d05e00811061545f5764012a05f2008110615453576509184e72a000624c4b409091048181029182040361050d5790565b5066246139ca80000090565b506612309ce540000090565b506609184e72a0000090565b5066048c273950000090565b50660246139ca8000090565b5066012309ce54000090565b50659184e72a000090565b506548c27395000090565b5065246139ca800090565b506512309ce5400090565b809150610f9c5750650da475abf00090565b50506509184e72a00090565b809150610f9c5750650610344c6aaa90565b90505065048c2739500090565b505065048c2739500090565b5050650246139ca80090565b505065012309ce540090565b5050649184e72a0090565b50506448c273950090565b505064246139ca8090565b50506412309ce54090565b50506409184e72a09056fea26469706673582212208b6a2f4e48277282ae24d5483fd67055ae947a614a18019515154e41704c856b64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b379a851ac41bcdf0c2564b88916b10e5a08daae0000000000000000000000003ea249809f032b1f5ae7b1dd4986490d05ee2dc2
-----Decoded View---------------
Arg [0] : token (address): 0xb379A851AC41bcDF0c2564b88916B10E5A08daAe
Arg [1] : lp (address): 0x3eA249809f032b1F5AE7B1Dd4986490d05eE2dC2
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000b379a851ac41bcdf0c2564b88916b10e5a08daae
Arg [1] : 0000000000000000000000003ea249809f032b1f5ae7b1dd4986490d05ee2dc2
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.