ERC-20
Gaming
Overview
Max Total Supply
69,920,799,379.576275523979 XEX
Holders
109 (0.00%)
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Main
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./Math.sol"; import "abdk-libraries-solidity/ABDKMath64x64.sol"; import "./@layerzerolabs/solidity-examples/contracts/token/oft/v2/OFTV2.sol"; contract Main is Context, OFTV2 { using Math for uint256; using ABDKMath64x64 for int128; using ABDKMath64x64 for uint256; // INTERNAL TYPE TO DESCRIBE A XEX MINT INFO struct MintInfo { address user; uint256 term; uint256 maturityTs; uint256 rank; uint256 amplifier; uint256 eaaRate; } // INTERNAL TYPE TO DESCRIBE A XEX STAKE struct StakeInfo { uint256 term; uint256 maturityTs; uint256 amount; uint256 apy; } // PUBLIC CONSTANTS uint256 public constant SECONDS_IN_DAY = 3_600 * 24; uint256 public constant DAYS_IN_YEAR = 365; uint256 public constant GENESIS_RANK = 1; uint256 public constant MIN_TERM = 1 * SECONDS_IN_DAY - 1; uint256 public constant MAX_TERM_START = 100 * SECONDS_IN_DAY; uint256 public constant MAX_TERM_END = 244 * SECONDS_IN_DAY; uint256 public constant TERM_AMPLIFIER = 15; uint256 public constant TERM_AMPLIFIER_THRESHOLD = 5_000; uint256 public constant REWARD_AMPLIFIER_START = 730; uint256 public constant REWARD_AMPLIFIER_END = 1; uint256 public constant EAA_PM_START = 1_000; uint256 public constant EAA_PM_STEP = 10; uint256 public constant EAA_RANK_STEP = 10_000; uint256 public constant WITHDRAWAL_WINDOW_DAYS = 7; uint256 public constant MAX_PENALTY_PCT = 99; uint256 public constant XEX_MIN_STAKE = 0; uint256 public constant XEX_MIN_BURN = 0; uint256 public constant XEX_APY_START = 35; uint256 public constant XEX_APY_DAYS_STEP = 20; uint256 public constant XEX_APY_END = 0; string public constant AUTHORS_XEN = "@MrJackLevin @lbelyaev faircrypto.org"; // PUBLIC STATE, READABLE VIA NAMESAKE GETTERS uint256 public immutable genesisTs; uint256 public globalRank = GENESIS_RANK; uint256 public activeMinters; uint256 public activeStakes; uint256 public totalXexStaked; // user address => XEX mint info mapping(address => MintInfo) public userMints; // user address => XEX stake info mapping(address => StakeInfo) public userStakes; // user address => XEX burn amount mapping(address => uint256) public userBurns; event Redeemed( address indexed user, address indexed xenContract, address indexed tokenContract, uint256 xenAmount, uint256 tokenAmount ); event RankClaimed(address indexed user, uint256 term, uint256 rank, uint AMP, uint EAA, uint maturity); event MintClaimed(address indexed user, uint256 rewardAmount); event Staked(address indexed user, uint256 amount, uint256 term); event Withdrawn(address indexed user, uint256 amount, uint256 reward); // CONSTRUCTOR constructor(uint _fee, address _endpoint, string memory _symbol, string memory _name, uint _initialMint) OFTV2(_name, _symbol, 8, _endpoint, _fee) { genesisTs = block.timestamp; // initial mint to seed liquidity if (_initialMint > 0) { _mint(msg.sender, _initialMint); } } // PRIVATE METHODS /** * @dev calculates current MaxTerm based on Global Rank * (if Global Rank crosses over TERM_AMPLIFIER_THRESHOLD) */ function _calculateMaxTerm() private view returns (uint256) { if (globalRank > TERM_AMPLIFIER_THRESHOLD) { uint256 delta = globalRank.fromUInt().log_2().mul(TERM_AMPLIFIER.fromUInt()).toUInt(); uint256 newMax = MAX_TERM_START + delta * SECONDS_IN_DAY; return Math.min(newMax, MAX_TERM_END); } return MAX_TERM_START; } /** * @dev calculates Withdrawal Penalty depending on lateness */ function _penalty(uint256 secsLate) private pure returns (uint256) { // =MIN(2^(daysLate+3)/window-1,99) uint256 daysLate = secsLate / SECONDS_IN_DAY; if (daysLate > WITHDRAWAL_WINDOW_DAYS - 1) return MAX_PENALTY_PCT; uint256 penalty = (uint256(1) << (daysLate + 3)) / WITHDRAWAL_WINDOW_DAYS - 1; return Math.min(penalty, MAX_PENALTY_PCT); } /** * @dev calculates net Mint Reward (adjusted for Penalty) */ function _calculateMintReward( uint256 cRank, uint256 term, uint256 maturityTs, uint256 amplifier, uint256 eeaRate ) private view returns (uint256) { uint256 secsLate = block.timestamp - maturityTs; uint256 penalty = _penalty(secsLate); uint256 rankDelta = Math.max(globalRank - cRank, 2); uint256 EAA = (1_000 + eeaRate); uint256 reward = getGrossReward(rankDelta, amplifier, term, EAA); return (reward * (100 - penalty)) / 100; } /** * @dev cleans up User Mint storage (gets some Gas credit;)) */ function _cleanUpUserMint() private { delete userMints[msg.sender]; activeMinters--; } /** * @dev calculates XEX Stake Reward */ function _calculateStakeReward( uint256 amount, uint256 term, uint256 maturityTs, uint256 apy ) private view returns (uint256) { if (block.timestamp > maturityTs) { uint256 rate = (apy * term * 1_000_000) / DAYS_IN_YEAR; return (amount * rate) / 100_000_000; } return 0; } /** * @dev calculates Reward Amplifier */ function _calculateRewardAmplifier() private view returns (uint256) { uint256 amplifierDecrease = (block.timestamp - genesisTs) / SECONDS_IN_DAY; if (amplifierDecrease < REWARD_AMPLIFIER_START) { return Math.max(REWARD_AMPLIFIER_START - amplifierDecrease, REWARD_AMPLIFIER_END); } else { return REWARD_AMPLIFIER_END; } } /** * @dev calculates Early Adopter Amplifier Rate (in 1/000ths) * actual EAA is (1_000 + EAAR) / 1_000 */ function _calculateEAARate() private view returns (uint256) { uint256 decrease = (EAA_PM_STEP * globalRank) / EAA_RANK_STEP; if (decrease > EAA_PM_START) return 0; return EAA_PM_START - decrease; } /** * @dev calculates APY (in %) */ function _calculateAPY() private view returns (uint256) { uint256 decrease = (block.timestamp - genesisTs) / (SECONDS_IN_DAY * XEX_APY_DAYS_STEP); if (XEX_APY_START - XEX_APY_END < decrease) return XEX_APY_END; return XEX_APY_START - decrease; } /** * @dev creates User Stake */ function _createStake(uint256 amount, uint256 term) private { userStakes[msg.sender] = StakeInfo({ term : term, maturityTs : block.timestamp + term * SECONDS_IN_DAY, amount : amount, apy : _calculateAPY() }); activeStakes++; totalXexStaked += amount; } // PUBLIC CONVENIENCE GETTERS /** * @dev calculates gross Mint Reward */ function getGrossReward( uint256 rankDelta, uint256 amplifier, uint256 term, uint256 eaa ) public pure returns (uint256) { int128 log128 = rankDelta.fromUInt().log_2(); int128 reward128 = log128.mul(amplifier.fromUInt()).mul(term.fromUInt()).mul(eaa.fromUInt()); return reward128.div(uint256(1_000).fromUInt()).toUInt(); } /** * @dev returns User Mint object associated with User account address */ function getUserMint() external view returns (MintInfo memory) { return userMints[msg.sender]; } /** * @dev returns XEX Stake object associated with User account address */ function getUserStake() external view returns (StakeInfo memory) { return userStakes[msg.sender]; } /** * @dev returns current AMP */ function getCurrentAMP() public view returns (uint256) { return _calculateRewardAmplifier(); } /** * @dev returns current EAA Rate */ function getCurrentEAAR() external view returns (uint256) { return _calculateEAARate(); } /** * @dev returns current APY */ function getCurrentAPY() external view returns (uint256) { return _calculateAPY(); } /** * @dev returns current MaxTerm */ function getCurrentMaxTerm() external view returns (uint256) { return _calculateMaxTerm(); } // PUBLIC STATE-CHANGING METHODS /** * @dev accepts User cRank claim provided all checks pass (incl. no current claim exists) */ function claimRank(uint256 term) external { uint256 termSec = term * SECONDS_IN_DAY; require(termSec > MIN_TERM); require(termSec < _calculateMaxTerm() + 1); require(userMints[msg.sender].rank == 0); // create and store new MintInfo MintInfo memory mintInfo = MintInfo({ user : msg.sender, term : term, maturityTs : block.timestamp + termSec, rank : globalRank, amplifier : _calculateRewardAmplifier(), eaaRate : _calculateEAARate() }); userMints[msg.sender] = mintInfo; activeMinters++; emit RankClaimed(msg.sender, term, globalRank++, getCurrentAMP(), mintInfo.eaaRate, mintInfo.maturityTs); } /** * @dev ends minting upon maturity (and within permitted Withdrawal Time Window), gets minted XEX */ function claimMintReward() public payable checkFee { MintInfo memory mintInfo = userMints[msg.sender]; require(mintInfo.rank > 0, "A"); require(block.timestamp > mintInfo.maturityTs, "B"); // calculate reward and mint tokens uint256 rewardAmount = _calculateMintReward( mintInfo.rank, mintInfo.term, mintInfo.maturityTs, mintInfo.amplifier, mintInfo.eaaRate ) * 1 ether; _mint(msg.sender, rewardAmount); _mint(treasure, rewardAmount / 100); _cleanUpUserMint(); emit MintClaimed(msg.sender, rewardAmount); } /** * @dev ends minting upon maturity (and within permitted Withdrawal time Window) * mints XEX coins and stakes 'pct' of it for 'term' */ function claimMintRewardAndStake(uint256 pct, uint256 term) external payable checkFee { MintInfo memory mintInfo = userMints[msg.sender]; // require(pct > 0, "CRank: Cannot share zero percent"); require(pct < 101); require(mintInfo.rank > 0); require(block.timestamp > mintInfo.maturityTs); // calculate reward uint256 rewardAmount = _calculateMintReward( mintInfo.rank, mintInfo.term, mintInfo.maturityTs, mintInfo.amplifier, mintInfo.eaaRate ) * 1 ether; uint256 stakedReward = (rewardAmount * pct) / 100; uint256 ownReward = rewardAmount - stakedReward; // mint reward tokens part _mint(msg.sender, ownReward); _mint(treasure, rewardAmount / 100); _cleanUpUserMint(); emit MintClaimed(msg.sender, rewardAmount); // nothing to burn since we haven't minted this part yet // stake extra tokens part require(stakedReward > XEX_MIN_STAKE); require(term * SECONDS_IN_DAY > MIN_TERM); require(term * SECONDS_IN_DAY < MAX_TERM_END + 1); require(userStakes[msg.sender].amount == 0); _createStake(stakedReward, term); emit Staked(msg.sender, stakedReward, term); } /** * @dev initiates XEX Stake in amount for a term (days) */ function stake(uint256 amount, uint256 term) external payable checkFee { require(balanceOf(msg.sender) >= amount); require(amount > XEX_MIN_STAKE); require(term * SECONDS_IN_DAY > MIN_TERM); require(term * SECONDS_IN_DAY < MAX_TERM_END + 1); require(userStakes[msg.sender].amount == 0); // burn staked XEX _burn(msg.sender, amount); // create XEX Stake _createStake(amount, term); emit Staked(msg.sender, amount, term); } /** * @dev ends XEX Stake and gets reward if the Stake is mature */ function withdraw() external payable checkFee { StakeInfo memory userStake = userStakes[msg.sender]; require(userStake.amount > 0); uint256 xenReward = _calculateStakeReward( userStake.amount, userStake.term, userStake.maturityTs, userStake.apy ); activeStakes--; totalXexStaked -= userStake.amount; // mint staked XEX (+ reward) _mint(msg.sender, userStake.amount + xenReward); _mint(treasure, xenReward / 100); emit Withdrawn(msg.sender, userStake.amount, xenReward); delete userStakes[msg.sender]; } /** * dev calculate mint reward without penalty. */ function getMintReward( uint256 cRank, uint256 term, uint256 maturityTs, uint256 amplifier, uint256 eeaRate ) public view returns (uint256) { if (block.timestamp > maturityTs) { // maturity passed, we can apply the fee uint256 secsLate = block.timestamp - maturityTs; uint256 penalty = _penalty(secsLate); uint256 rankDelta = Math.max(globalRank - cRank, 2); uint256 EAA = (1_000 + eeaRate); uint256 reward = getGrossReward(rankDelta, amplifier, term, EAA); return (reward * (100 - penalty)) / 100; } else { // maturity hasn't passed, return without fee uint256 rankDelta = Math.max(globalRank - cRank, 2); uint256 EAA = (1_000 + eeaRate); return getGrossReward(rankDelta, amplifier, term, EAA); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: BSD-4-Clause /* * ABDK Math 64.64 Smart Contract Library. Copyright © 2019 by ABDK Consulting. * Author: Mikhail Vladimirov <[email protected]> */ pragma solidity ^0.8.0; /** * Smart contract library of mathematical functions operating with signed * 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is * basically a simple fraction whose numerator is signed 128-bit integer and * denominator is 2^64. As long as denominator is always the same, there is no * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are * represented by int128 type holding only the numerator. */ library ABDKMath64x64 { /* * Minimum value signed 64.64-bit fixed point number may have. */ int128 private constant MIN_64x64 = -0x80000000000000000000000000000000; /* * Maximum value signed 64.64-bit fixed point number may have. */ int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; /** * Convert signed 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromInt (int256 x) internal pure returns (int128) { unchecked { require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF); return int128 (x << 64); } } /** * Convert signed 64.64 fixed point number into signed 64-bit integer number * rounding down. * * @param x signed 64.64-bit fixed point number * @return signed 64-bit integer number */ function toInt (int128 x) internal pure returns (int64) { unchecked { return int64 (x >> 64); } } /** * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromUInt (uint256 x) internal pure returns (int128) { unchecked { require (x <= 0x7FFFFFFFFFFFFFFF); return int128 (int256 (x << 64)); } } /** * Convert signed 64.64 fixed point number into unsigned 64-bit integer * number rounding down. Revert on underflow. * * @param x signed 64.64-bit fixed point number * @return unsigned 64-bit integer number */ function toUInt (int128 x) internal pure returns (uint64) { unchecked { require (x >= 0); return uint64 (uint128 (x >> 64)); } } /** * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point * number rounding down. Revert on overflow. * * @param x signed 128.128-bin fixed point number * @return signed 64.64-bit fixed point number */ function from128x128 (int256 x) internal pure returns (int128) { unchecked { int256 result = x >> 64; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Convert signed 64.64 fixed point number into signed 128.128 fixed point * number. * * @param x signed 64.64-bit fixed point number * @return signed 128.128 fixed point number */ function to128x128 (int128 x) internal pure returns (int256) { unchecked { return int256 (x) << 64; } } /** * Calculate x + y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function add (int128 x, int128 y) internal pure returns (int128) { unchecked { int256 result = int256(x) + y; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate x - y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function sub (int128 x, int128 y) internal pure returns (int128) { unchecked { int256 result = int256(x) - y; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate x * y rounding down. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function mul (int128 x, int128 y) internal pure returns (int128) { unchecked { int256 result = int256(x) * y >> 64; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point * number and y is signed 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y signed 256-bit integer number * @return signed 256-bit integer number */ function muli (int128 x, int256 y) internal pure returns (int256) { unchecked { if (x == MIN_64x64) { require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF && y <= 0x1000000000000000000000000000000000000000000000000); return -y << 63; } else { bool negativeResult = false; if (x < 0) { x = -x; negativeResult = true; } if (y < 0) { y = -y; // We rely on overflow behavior here negativeResult = !negativeResult; } uint256 absoluteResult = mulu (x, uint256 (y)); if (negativeResult) { require (absoluteResult <= 0x8000000000000000000000000000000000000000000000000000000000000000); return -int256 (absoluteResult); // We rely on overflow behavior here } else { require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int256 (absoluteResult); } } } } /** * Calculate x * y rounding down, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y unsigned 256-bit integer number * @return unsigned 256-bit integer number */ function mulu (int128 x, uint256 y) internal pure returns (uint256) { unchecked { if (y == 0) return 0; require (x >= 0); uint256 lo = (uint256 (int256 (x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64; uint256 hi = uint256 (int256 (x)) * (y >> 128); require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); hi <<= 64; require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo); return hi + lo; } } /** * Calculate x / y rounding towards zero. Revert on overflow or when y is * zero. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function div (int128 x, int128 y) internal pure returns (int128) { unchecked { require (y != 0); int256 result = (int256 (x) << 64) / y; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate x / y rounding towards zero, where x and y are signed 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x signed 256-bit integer number * @param y signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function divi (int256 x, int256 y) internal pure returns (int128) { unchecked { require (y != 0); bool negativeResult = false; if (x < 0) { x = -x; // We rely on overflow behavior here negativeResult = true; } if (y < 0) { y = -y; // We rely on overflow behavior here negativeResult = !negativeResult; } uint128 absoluteResult = divuu (uint256 (x), uint256 (y)); if (negativeResult) { require (absoluteResult <= 0x80000000000000000000000000000000); return -int128 (absoluteResult); // We rely on overflow behavior here } else { require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int128 (absoluteResult); // We rely on overflow behavior here } } } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ function divu (uint256 x, uint256 y) internal pure returns (int128) { unchecked { require (y != 0); uint128 result = divuu (x, y); require (result <= uint128 (MAX_64x64)); return int128 (result); } } /** * Calculate -x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function neg (int128 x) internal pure returns (int128) { unchecked { require (x != MIN_64x64); return -x; } } /** * Calculate |x|. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function abs (int128 x) internal pure returns (int128) { unchecked { require (x != MIN_64x64); return x < 0 ? -x : x; } } /** * Calculate 1 / x rounding towards zero. Revert on overflow or when x is * zero. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function inv (int128 x) internal pure returns (int128) { unchecked { require (x != 0); int256 result = int256 (0x100000000000000000000000000000000) / x; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function avg (int128 x, int128 y) internal pure returns (int128) { unchecked { return int128 ((int256 (x) + int256 (y)) >> 1); } } /** * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down. * Revert on overflow or in case x * y is negative. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function gavg (int128 x, int128 y) internal pure returns (int128) { unchecked { int256 m = int256 (x) * int256 (y); require (m >= 0); require (m < 0x4000000000000000000000000000000000000000000000000000000000000000); return int128 (sqrtu (uint256 (m))); } } /** * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y uint256 value * @return signed 64.64-bit fixed point number */ function pow (int128 x, uint256 y) internal pure returns (int128) { unchecked { bool negative = x < 0 && y & 1 == 1; uint256 absX = uint128 (x < 0 ? -x : x); uint256 absResult; absResult = 0x100000000000000000000000000000000; if (absX <= 0x10000000000000000) { absX <<= 63; while (y != 0) { if (y & 0x1 != 0) { absResult = absResult * absX >> 127; } absX = absX * absX >> 127; if (y & 0x2 != 0) { absResult = absResult * absX >> 127; } absX = absX * absX >> 127; if (y & 0x4 != 0) { absResult = absResult * absX >> 127; } absX = absX * absX >> 127; if (y & 0x8 != 0) { absResult = absResult * absX >> 127; } absX = absX * absX >> 127; y >>= 4; } absResult >>= 64; } else { uint256 absXShift = 63; if (absX < 0x1000000000000000000000000) { absX <<= 32; absXShift -= 32; } if (absX < 0x10000000000000000000000000000) { absX <<= 16; absXShift -= 16; } if (absX < 0x1000000000000000000000000000000) { absX <<= 8; absXShift -= 8; } if (absX < 0x10000000000000000000000000000000) { absX <<= 4; absXShift -= 4; } if (absX < 0x40000000000000000000000000000000) { absX <<= 2; absXShift -= 2; } if (absX < 0x80000000000000000000000000000000) { absX <<= 1; absXShift -= 1; } uint256 resultShift = 0; while (y != 0) { require (absXShift < 64); if (y & 0x1 != 0) { absResult = absResult * absX >> 127; resultShift += absXShift; if (absResult > 0x100000000000000000000000000000000) { absResult >>= 1; resultShift += 1; } } absX = absX * absX >> 127; absXShift <<= 1; if (absX >= 0x100000000000000000000000000000000) { absX >>= 1; absXShift += 1; } y >>= 1; } require (resultShift < 64); absResult >>= 64 - resultShift; } int256 result = negative ? -int256 (absResult) : int256 (absResult); require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate sqrt (x) rounding down. Revert if x < 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function sqrt (int128 x) internal pure returns (int128) { unchecked { require (x >= 0); return int128 (sqrtu (uint256 (int256 (x)) << 64)); } } /** * Calculate binary logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function log_2 (int128 x) internal pure returns (int128) { unchecked { require (x > 0); int256 msb = 0; int256 xc = x; if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; } if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore int256 result = msb - 64 << 64; uint256 ux = uint256 (int256 (x)) << uint256 (127 - msb); for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) { ux *= ux; uint256 b = ux >> 255; ux >>= 127 + b; result += bit * int256 (b); } return int128 (result); } } /** * Calculate natural logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function ln (int128 x) internal pure returns (int128) { unchecked { require (x > 0); return int128 (int256 ( uint256 (int256 (log_2 (x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128)); } } /** * Calculate binary exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp_2 (int128 x) internal pure returns (int128) { unchecked { require (x < 0x400000000000000000); // Overflow if (x < -0x400000000000000000) return 0; // Underflow uint256 result = 0x80000000000000000000000000000000; if (x & 0x8000000000000000 > 0) result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128; if (x & 0x4000000000000000 > 0) result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128; if (x & 0x2000000000000000 > 0) result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128; if (x & 0x1000000000000000 > 0) result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128; if (x & 0x800000000000000 > 0) result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128; if (x & 0x400000000000000 > 0) result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128; if (x & 0x200000000000000 > 0) result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128; if (x & 0x100000000000000 > 0) result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128; if (x & 0x80000000000000 > 0) result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128; if (x & 0x40000000000000 > 0) result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128; if (x & 0x20000000000000 > 0) result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128; if (x & 0x10000000000000 > 0) result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128; if (x & 0x8000000000000 > 0) result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128; if (x & 0x4000000000000 > 0) result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128; if (x & 0x2000000000000 > 0) result = result * 0x1000162E525EE054754457D5995292026 >> 128; if (x & 0x1000000000000 > 0) result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128; if (x & 0x800000000000 > 0) result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128; if (x & 0x400000000000 > 0) result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128; if (x & 0x200000000000 > 0) result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128; if (x & 0x100000000000 > 0) result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128; if (x & 0x80000000000 > 0) result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128; if (x & 0x40000000000 > 0) result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128; if (x & 0x20000000000 > 0) result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128; if (x & 0x10000000000 > 0) result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128; if (x & 0x8000000000 > 0) result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128; if (x & 0x4000000000 > 0) result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128; if (x & 0x2000000000 > 0) result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128; if (x & 0x1000000000 > 0) result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128; if (x & 0x800000000 > 0) result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128; if (x & 0x400000000 > 0) result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128; if (x & 0x200000000 > 0) result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128; if (x & 0x100000000 > 0) result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128; if (x & 0x80000000 > 0) result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128; if (x & 0x40000000 > 0) result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128; if (x & 0x20000000 > 0) result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128; if (x & 0x10000000 > 0) result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128; if (x & 0x8000000 > 0) result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128; if (x & 0x4000000 > 0) result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128; if (x & 0x2000000 > 0) result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128; if (x & 0x1000000 > 0) result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128; if (x & 0x800000 > 0) result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128; if (x & 0x400000 > 0) result = result * 0x100000000002C5C85FDF477B662B26945 >> 128; if (x & 0x200000 > 0) result = result * 0x10000000000162E42FEFA3AE53369388C >> 128; if (x & 0x100000 > 0) result = result * 0x100000000000B17217F7D1D351A389D40 >> 128; if (x & 0x80000 > 0) result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128; if (x & 0x40000 > 0) result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128; if (x & 0x20000 > 0) result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128; if (x & 0x10000 > 0) result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128; if (x & 0x8000 > 0) result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128; if (x & 0x4000 > 0) result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128; if (x & 0x2000 > 0) result = result * 0x1000000000000162E42FEFA39F02B772C >> 128; if (x & 0x1000 > 0) result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128; if (x & 0x800 > 0) result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128; if (x & 0x400 > 0) result = result * 0x100000000000002C5C85FDF473DEA871F >> 128; if (x & 0x200 > 0) result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128; if (x & 0x100 > 0) result = result * 0x100000000000000B17217F7D1CF79E949 >> 128; if (x & 0x80 > 0) result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128; if (x & 0x40 > 0) result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128; if (x & 0x20 > 0) result = result * 0x100000000000000162E42FEFA39EF366F >> 128; if (x & 0x10 > 0) result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128; if (x & 0x8 > 0) result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128; if (x & 0x4 > 0) result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128; if (x & 0x2 > 0) result = result * 0x1000000000000000162E42FEFA39EF358 >> 128; if (x & 0x1 > 0) result = result * 0x10000000000000000B17217F7D1CF79AB >> 128; result >>= uint256 (int256 (63 - (x >> 64))); require (result <= uint256 (int256 (MAX_64x64))); return int128 (int256 (result)); } } /** * Calculate natural exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp (int128 x) internal pure returns (int128) { unchecked { require (x < 0x400000000000000000); // Overflow if (x < -0x400000000000000000) return 0; // Underflow return exp_2 ( int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128)); } } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return unsigned 64.64-bit fixed point number */ function divuu (uint256 x, uint256 y) private pure returns (uint128) { unchecked { require (y != 0); uint256 result; if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y; else { uint256 msb = 192; uint256 xc = x >> 192; if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1); require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); uint256 hi = result * (y >> 128); uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); uint256 xh = x >> 192; uint256 xl = x << 64; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here lo = hi << 128; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here assert (xh == hi >> 128); result += xl / y; } require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return uint128 (result); } } /** * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer * number. * * @param x unsigned 256-bit integer number * @return unsigned 128-bit integer number */ function sqrtu (uint256 x) private pure returns (uint128) { unchecked { if (x == 0) return 0; else { uint256 xx = x; uint256 r = 1; if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; } if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; } if (xx >= 0x100000000) { xx >>= 32; r <<= 16; } if (xx >= 0x10000) { xx >>= 16; r <<= 8; } if (xx >= 0x100) { xx >>= 8; r <<= 4; } if (xx >= 0x10) { xx >>= 4; r <<= 2; } if (xx >= 0x8) { r <<= 1; } r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; // Seven iterations should be enough uint256 r1 = x / r; return uint128 (r < r1 ? r : r1); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; import "./ILayerZeroUserApplicationConfig.sol"; interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig { // @notice send a LayerZero message to the specified address at a LayerZero endpoint. // @param _dstChainId - the destination chain identifier // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains // @param _payload - a custom bytes payload to send to the destination contract // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable; // @notice used by the messaging library to publish verified payload // @param _srcChainId - the source chain identifier // @param _srcAddress - the source contract (as bytes) at the source chain // @param _dstAddress - the address on destination chain // @param _nonce - the unbound message ordering nonce // @param _gasLimit - the gas limit for external contract execution // @param _payload - verified payload to send to the destination contract function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external; // @notice get the inboundNonce of a lzApp from a source chain which could be EVM or non-EVM chain // @param _srcChainId - the source chain identifier // @param _srcAddress - the source chain contract address function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64); // @notice get the outboundNonce from this source chain which, consequently, is always an EVM // @param _srcAddress - the source chain contract address function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64); // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery // @param _dstChainId - the destination chain identifier // @param _userApplication - the user app address on this EVM chain // @param _payload - the custom message to send over LayerZero // @param _payInZRO - if false, user app pays the protocol fee in native token // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee); // @notice get this Endpoint's immutable source identifier function getChainId() external view returns (uint16); // @notice the interface to retry failed message on this Endpoint destination // @param _srcChainId - the source chain identifier // @param _srcAddress - the source chain contract address // @param _payload - the payload to be retried function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external; // @notice query if any STORED payload (message blocking) at the endpoint. // @param _srcChainId - the source chain identifier // @param _srcAddress - the source chain contract address function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool); // @notice query if the _libraryAddress is valid for sending msgs. // @param _userApplication - the user app address on this EVM chain function getSendLibraryAddress(address _userApplication) external view returns (address); // @notice query if the _libraryAddress is valid for receiving msgs. // @param _userApplication - the user app address on this EVM chain function getReceiveLibraryAddress(address _userApplication) external view returns (address); // @notice query if the non-reentrancy guard for send() is on // @return true if the guard is on. false otherwise function isSendingPayload() external view returns (bool); // @notice query if the non-reentrancy guard for receive() is on // @return true if the guard is on. false otherwise function isReceivingPayload() external view returns (bool); // @notice get the configuration of the LayerZero messaging library of the specified version // @param _version - messaging library version // @param _chainId - the chainId for the pending config change // @param _userApplication - the contract address of the user application // @param _configType - type of configuration. every messaging library has its own convention. function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory); // @notice get the send() LayerZero messaging library version // @param _userApplication - the contract address of the user application function getSendVersion(address _userApplication) external view returns (uint16); // @notice get the lzReceive() LayerZero messaging library version // @param _userApplication - the contract address of the user application function getReceiveVersion(address _userApplication) external view returns (uint16); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; interface ILayerZeroReceiver { // @notice LayerZero endpoint will invoke this function to deliver the message on the destination // @param _srcChainId - the source endpoint identifier // @param _srcAddress - the source sending contract address from the source chain // @param _nonce - the ordered message nonce // @param _payload - the signed payload is the UA bytes has encoded to be sent function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; interface ILayerZeroUserApplicationConfig { // @notice set the configuration of the LayerZero messaging library of the specified version // @param _version - messaging library version // @param _chainId - the chainId for the pending config change // @param _configType - type of configuration. every messaging library has its own convention. // @param _config - configuration in the bytes. can encode arbitrary content. function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external; // @notice set the send() LayerZero messaging library version to _version // @param _version - new messaging library version function setSendVersion(uint16 _version) external; // @notice set the lzReceive() LayerZero messaging library version to _version // @param _version - new messaging library version function setReceiveVersion(uint16 _version) external; // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload // @param _srcChainId - the chainId of the source chain // @param _srcAddress - the contract address of the source contract at the source chain function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "../interfaces/ILayerZeroReceiver.sol"; import "../interfaces/ILayerZeroUserApplicationConfig.sol"; import "../interfaces/ILayerZeroEndpoint.sol"; import "../util/BytesLib.sol"; /* * a generic LzReceiver implementation */ abstract contract LzApp is Ownable, ILayerZeroReceiver, ILayerZeroUserApplicationConfig { using BytesLib for bytes; ILayerZeroEndpoint public lzEndpoint; mapping(uint16 => bytes) public trustedRemoteLookup; mapping(uint16 => mapping(uint16 => uint)) public minDstGasLookup; address public precrime; event SetPrecrime(address precrime); event SetTrustedRemote(uint16 _remoteChainId, bytes _path); event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress); event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint _minDstGas); constructor(address _endpoint) { lzEndpoint = ILayerZeroEndpoint(_endpoint); } function setEndpoint(address _endpoint) external onlyOwner { require( address(lzEndpoint) == address(0)); lzEndpoint = ILayerZeroEndpoint(_endpoint); } function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public virtual override { // lzReceive must be called by the endpoint for security require(_msgSender() == address(lzEndpoint), "LzApp: invalid endpoint caller"); bytes memory trustedRemote = trustedRemoteLookup[_srcChainId]; // if will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote. require(_srcAddress.length == trustedRemote.length && trustedRemote.length > 0 && keccak256(_srcAddress) == keccak256(trustedRemote), "LzApp: invalid source sending contract"); _blockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload); } // abstract function - the default behaviour of LayerZero is blocking. See: NonblockingLzApp if you dont need to enforce ordered messaging function _blockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual; function _lzSend(uint16 _dstChainId, bytes memory _payload, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams, uint _nativeFee) internal virtual { bytes memory trustedRemote = trustedRemoteLookup[_dstChainId]; require(trustedRemote.length != 0, "LzApp: destination chain is not a trusted source"); lzEndpoint.send{value: _nativeFee}(_dstChainId, trustedRemote, _payload, _refundAddress, _zroPaymentAddress, _adapterParams); } function _checkGasLimit(uint16 _dstChainId, uint16 _type, bytes memory _adapterParams, uint _extraGas) internal view virtual { uint providedGasLimit = _getGasLimit(_adapterParams); uint minGasLimit = minDstGasLookup[_dstChainId][_type] + _extraGas; require(minGasLimit > 0, "LzApp: minGasLimit not set"); require(providedGasLimit >= minGasLimit, "LzApp: gas limit is too low"); } function _getGasLimit(bytes memory _adapterParams) internal pure virtual returns (uint gasLimit) { require(_adapterParams.length >= 34, "LzApp: invalid adapterParams"); assembly { gasLimit := mload(add(_adapterParams, 34)) } } //---------------------------UserApplication config---------------------------------------- function getConfig(uint16 _version, uint16 _chainId, address, uint _configType) external view returns (bytes memory) { return lzEndpoint.getConfig(_version, _chainId, address(this), _configType); } // generic config for LayerZero user Application function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external override onlyOwner { lzEndpoint.setConfig(_version, _chainId, _configType, _config); } function setSendVersion(uint16 _version) external override onlyOwner { lzEndpoint.setSendVersion(_version); } function setReceiveVersion(uint16 _version) external override onlyOwner { lzEndpoint.setReceiveVersion(_version); } function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyOwner { lzEndpoint.forceResumeReceive(_srcChainId, _srcAddress); } // _path = abi.encodePacked(remoteAddress, localAddress) // this function set the trusted path for the cross-chain communication function setTrustedRemote(uint16 _srcChainId, bytes calldata _path) external onlyOwner { trustedRemoteLookup[_srcChainId] = _path; emit SetTrustedRemote(_srcChainId, _path); } function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyOwner { trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this)); emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress); } function getTrustedRemoteAddress(uint16 _remoteChainId) external view returns (bytes memory) { bytes memory path = trustedRemoteLookup[_remoteChainId]; require(path.length != 0, "LzApp: no trusted path record"); return path.slice(0, path.length - 20); // the last 20 bytes should be address(this) } function setPrecrime(address _precrime) external onlyOwner { precrime = _precrime; emit SetPrecrime(_precrime); } function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint _minGas) external onlyOwner { require(_minGas > 0, "LzApp: invalid minGas"); minDstGasLookup[_dstChainId][_packetType] = _minGas; emit SetMinDstGas(_dstChainId, _packetType, _minGas); } //--------------------------- VIEW FUNCTION ---------------------------------------- function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool) { bytes memory trustedSource = trustedRemoteLookup[_srcChainId]; return keccak256(trustedSource) == keccak256(_srcAddress); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./LzApp.sol"; import "../util/ExcessivelySafeCall.sol"; /* * the default LayerZero messaging behaviour is blocking, i.e. any failed message will block the channel * this abstract class try-catch all fail messages and store locally for future retry. hence, non-blocking * NOTE: if the srcAddress is not configured properly, it will still block the message pathway from (srcChainId, srcAddress) */ abstract contract NonblockingLzApp is LzApp { using ExcessivelySafeCall for address; constructor(address _endpoint) LzApp(_endpoint) {} mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages; event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload, bytes _reason); event RetryMessageSuccess(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _payloadHash); // overriding the virtual function in LzReceiver function _blockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual override { (bool success, bytes memory reason) = address(this).excessivelySafeCall(gasleft(), 150, abi.encodeWithSelector(this.nonblockingLzReceive.selector, _srcChainId, _srcAddress, _nonce, _payload)); // try-catch all errors/exceptions if (!success) { _storeFailedMessage(_srcChainId, _srcAddress, _nonce, _payload, reason); } } function _storeFailedMessage(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload, bytes memory _reason) internal virtual { failedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(_payload); emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload, _reason); } function nonblockingLzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public virtual { // only internal transaction require(_msgSender() == address(this)); _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload); } //@notice override this function function _nonblockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual; function retryMessage(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public payable virtual { // assert there is message to retry bytes32 payloadHash = failedMessages[_srcChainId][_srcAddress][_nonce]; require(payloadHash != bytes32(0)); require(keccak256(_payload) == payloadHash); // clear the stored message failedMessages[_srcChainId][_srcAddress][_nonce] = bytes32(0); // execute the message. revert if it fails again _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload); emit RetryMessageSuccess(_srcChainId, _srcAddress, _nonce, payloadHash); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./OFTCoreV2.sol"; import "./IOFTV2.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; abstract contract BaseOFTV2 is OFTCoreV2, ERC165, IOFTV2 { address public treasure; uint public fee; constructor(uint8 _sharedDecimals, address _lzEndpoint) OFTCoreV2(_sharedDecimals, _lzEndpoint) { } modifier checkFee(){ require( msg.value >= fee, "F"); if( msg.value > 0 && fee > 0 ){ (bool status,) = payable(treasure).call{value: fee}(""); require(status); } _; } function setTreasure(address _treasure) external onlyOwner { require(_treasure != address(0)); treasure = _treasure; } /************************************************************************ * public functions ************************************************************************/ function sendFrom(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount, LzCallParams calldata _callParams) public payable checkFee virtual override { uint _nativeFee = msg.value - fee; _send(_from, _dstChainId, _toAddress, _amount, _callParams.refundAddress, _callParams.zroPaymentAddress, _callParams.adapterParams, _nativeFee); } function sendAndCall(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount, bytes calldata _payload, uint64 _dstGasForCall, LzCallParams calldata _callParams) public payable checkFee virtual override { uint _nativeFee = msg.value - fee; _sendAndCall(_from, _dstChainId, _toAddress, _amount, _payload, _dstGasForCall, _callParams.refundAddress, _callParams.zroPaymentAddress, _callParams.adapterParams, _nativeFee); } /************************************************************************ * public view functions ************************************************************************/ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IOFTV2).interfaceId || super.supportsInterface(interfaceId); } function estimateSendFee(uint16 _dstChainId, bytes32 _toAddress, uint _amount, bool _useZro, bytes calldata _adapterParams) public view virtual override returns (uint nativeFee, uint zroFee) { (uint nativeFee, uint zroFee) = _estimateSendFee(_dstChainId, _toAddress, _amount, _useZro, _adapterParams); return (nativeFee + fee, zroFee); } function estimateSendAndCallFee(uint16 _dstChainId, bytes32 _toAddress, uint _amount, bytes calldata _payload, uint64 _dstGasForCall, bool _useZro, bytes calldata _adapterParams) public view virtual override returns (uint nativeFee, uint zroFee) { (uint nativeFee, uint zroFee) = _estimateSendAndCallFee(_dstChainId, _toAddress, _amount, _payload, _dstGasForCall, _useZro, _adapterParams); return (nativeFee + fee, zroFee); } function circulatingSupply() public view virtual override returns (uint); function token() public view virtual override returns (address); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @dev Interface of the IOFT core standard */ interface ICommonOFT is IERC165 { struct LzCallParams { address payable refundAddress; address zroPaymentAddress; bytes adapterParams; } /** * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`) * _dstChainId - L0 defined chain id to send tokens too * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain * _amount - amount of the tokens to transfer * _useZro - indicates to use zro to pay L0 fees * _adapterParam - flexible bytes array to indicate messaging adapter services in L0 */ function estimateSendFee(uint16 _dstChainId, bytes32 _toAddress, uint _amount, bool _useZro, bytes calldata _adapterParams) external view returns (uint nativeFee, uint zroFee); function estimateSendAndCallFee(uint16 _dstChainId, bytes32 _toAddress, uint _amount, bytes calldata _payload, uint64 _dstGasForCall, bool _useZro, bytes calldata _adapterParams) external view returns (uint nativeFee, uint zroFee); /** * @dev returns the circulating amount of tokens on current chain */ function circulatingSupply() external view returns (uint); /** * @dev returns the address of the ERC20 token */ function token() external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; interface IOFTReceiverV2 { /** * @dev Called by the OFT contract when tokens are received from source chain. * @param _srcChainId The chain id of the source chain. * @param _srcAddress The address of the OFT token contract on the source chain. * @param _nonce The nonce of the transaction on the source chain. * @param _from The address of the account who calls the sendAndCall() on the source chain. * @param _amount The amount of tokens to transfer. * @param _payload Additional data with no specified format. */ function onOFTReceived(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes32 _from, uint _amount, bytes calldata _payload) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; import "./ICommonOFT.sol"; /** * @dev Interface of the IOFT core standard */ interface IOFTV2 is ICommonOFT { /** * @dev send `_amount` amount of token to (`_dstChainId`, `_toAddress`) from `_from` * `_from` the owner of token * `_dstChainId` the destination chain identifier * `_toAddress` can be any size depending on the `dstChainId`. * `_amount` the quantity of tokens in wei * `_refundAddress` the address LayerZero refunds if too much message fee is sent * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token) * `_adapterParams` is a flexible bytes array to indicate messaging adapter services */ function sendFrom(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount, LzCallParams calldata _callParams) external payable; function sendAndCall(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount, bytes calldata _payload, uint64 _dstGasForCall, LzCallParams calldata _callParams) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../../lzApp/NonblockingLzApp.sol"; import "../../../util/ExcessivelySafeCall.sol"; import "./ICommonOFT.sol"; import "./IOFTReceiverV2.sol"; abstract contract OFTCoreV2 is NonblockingLzApp { using BytesLib for bytes; using ExcessivelySafeCall for address; uint public constant NO_EXTRA_GAS = 0; // packet type uint8 public constant PT_SEND = 0; uint8 public constant PT_SEND_AND_CALL = 1; uint8 public immutable sharedDecimals; bool public useCustomAdapterParams; mapping(uint16 => mapping(bytes => mapping(uint64 => bool))) public creditedPackets; /** * @dev Emitted when `_amount` tokens are moved from the `_sender` to (`_dstChainId`, `_toAddress`) * `_nonce` is the outbound nonce */ event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes32 indexed _toAddress, uint _amount); /** * @dev Emitted when `_amount` tokens are received from `_srcChainId` into the `_toAddress` on the local chain. * `_nonce` is the inbound nonce. */ event ReceiveFromChain(uint16 indexed _srcChainId, address indexed _to, uint _amount); event SetUseCustomAdapterParams(bool _useCustomAdapterParams); event CallOFTReceivedSuccess(uint16 indexed _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _hash); event NonContractAddress(address _address); // _sharedDecimals should be the minimum decimals on all chains constructor(uint8 _sharedDecimals, address _lzEndpoint) NonblockingLzApp(_lzEndpoint) { sharedDecimals = _sharedDecimals; } /************************************************************************ * public functions ************************************************************************/ function callOnOFTReceived(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes32 _from, address _to, uint _amount, bytes calldata _payload, uint _gasForCall) public virtual { require(_msgSender() == address(this)); // send _amount = _transferFrom(address(this), _to, _amount); emit ReceiveFromChain(_srcChainId, _to, _amount); // call IOFTReceiverV2(_to).onOFTReceived{gas: _gasForCall}(_srcChainId, _srcAddress, _nonce, _from, _amount, _payload); } function setUseCustomAdapterParams(bool _useCustomAdapterParams) public virtual onlyOwner { useCustomAdapterParams = _useCustomAdapterParams; emit SetUseCustomAdapterParams(_useCustomAdapterParams); } /************************************************************************ * internal functions ************************************************************************/ function _estimateSendFee(uint16 _dstChainId, bytes32 _toAddress, uint _amount, bool _useZro, bytes memory _adapterParams) internal view virtual returns (uint nativeFee, uint zroFee) { // mock the payload for sendFrom() bytes memory payload = _encodeSendPayload(_toAddress, _ld2sd(_amount)); return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams); } function _estimateSendAndCallFee(uint16 _dstChainId, bytes32 _toAddress, uint _amount, bytes memory _payload, uint64 _dstGasForCall, bool _useZro, bytes memory _adapterParams) internal view virtual returns (uint nativeFee, uint zroFee) { // mock the payload for sendAndCall() bytes memory payload = _encodeSendAndCallPayload(msg.sender, _toAddress, _ld2sd(_amount), _payload, _dstGasForCall); return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams); } function _nonblockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual override { uint8 packetType = _payload.toUint8(0); if (packetType == PT_SEND) { _sendAck(_srcChainId, _srcAddress, _nonce, _payload); } else if (packetType == PT_SEND_AND_CALL) { _sendAndCallAck(_srcChainId, _srcAddress, _nonce, _payload); } else { revert(""); } } function _send(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams, uint _nativeFee) internal virtual returns (uint amount) { _checkAdapterParams(_dstChainId, PT_SEND, _adapterParams, NO_EXTRA_GAS); (amount,) = _removeDust(_amount); amount = _debitFrom(_from, _dstChainId, _toAddress, amount); // amount returned should not have dust require(amount > 0); bytes memory lzPayload = _encodeSendPayload(_toAddress, _ld2sd(amount)); _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, _nativeFee); emit SendToChain(_dstChainId, _from, _toAddress, amount); } function _sendAck(uint16 _srcChainId, bytes memory, uint64, bytes memory _payload) internal virtual { (address to, uint64 amountSD) = _decodeSendPayload(_payload); if (to == address(0)) { to = address(0xdead); } uint amount = _sd2ld(amountSD); amount = _creditTo(_srcChainId, to, amount); emit ReceiveFromChain(_srcChainId, to, amount); } function _sendAndCall(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount, bytes memory _payload, uint64 _dstGasForCall, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams, uint _nativeFee) internal virtual returns (uint amount) { _checkAdapterParams(_dstChainId, PT_SEND_AND_CALL, _adapterParams, _dstGasForCall); (amount,) = _removeDust(_amount); amount = _debitFrom(_from, _dstChainId, _toAddress, amount); require(amount > 0); // encode the msg.sender into the payload instead of _from bytes memory lzPayload = _encodeSendAndCallPayload(msg.sender, _toAddress, _ld2sd(amount), _payload, _dstGasForCall); _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, _nativeFee); emit SendToChain(_dstChainId, _from, _toAddress, amount); } function _sendAndCallAck(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual { (bytes32 from, address to, uint64 amountSD, bytes memory payloadForCall, uint64 gasForCall) = _decodeSendAndCallPayload(_payload); bool credited = creditedPackets[_srcChainId][_srcAddress][_nonce]; uint amount = _sd2ld(amountSD); // credit to this contract first, and then transfer to receiver only if callOnOFTReceived() succeeds if (!credited) { amount = _creditTo(_srcChainId, address(this), amount); creditedPackets[_srcChainId][_srcAddress][_nonce] = true; } if (!_isContract(to)) { emit NonContractAddress(to); return; } // workaround for stack too deep uint16 srcChainId = _srcChainId; bytes memory srcAddress = _srcAddress; uint64 nonce = _nonce; bytes memory payload = _payload; bytes32 from_ = from; address to_ = to; uint amount_ = amount; bytes memory payloadForCall_ = payloadForCall; // no gas limit for the call if retry uint gas = credited ? gasleft() : gasForCall; (bool success, bytes memory reason) = address(this).excessivelySafeCall(gasleft(), 150, abi.encodeWithSelector(this.callOnOFTReceived.selector, srcChainId, srcAddress, nonce, from_, to_, amount_, payloadForCall_, gas)); if (success) { bytes32 hash = keccak256(payload); emit CallOFTReceivedSuccess(srcChainId, srcAddress, nonce, hash); } else { // store the failed message into the nonblockingLzApp _storeFailedMessage(srcChainId, srcAddress, nonce, payload, reason); } } function _isContract(address _account) internal view returns (bool) { return _account.code.length > 0; } function _checkAdapterParams(uint16 _dstChainId, uint16 _pkType, bytes memory _adapterParams, uint _extraGas) internal virtual { if (useCustomAdapterParams) { _checkGasLimit(_dstChainId, _pkType, _adapterParams, _extraGas); } else { require(_adapterParams.length == 0); } } function _ld2sd(uint _amount) internal virtual view returns (uint64) { uint amountSD = _amount / _ld2sdRate(); require(amountSD <= type(uint64).max); return uint64(amountSD); } function _sd2ld(uint64 _amountSD) internal virtual view returns (uint) { return _amountSD * _ld2sdRate(); } function _removeDust(uint _amount) internal virtual view returns (uint amountAfter, uint dust) { dust = _amount % _ld2sdRate(); amountAfter = _amount - dust; } function _encodeSendPayload(bytes32 _toAddress, uint64 _amountSD) internal virtual view returns (bytes memory) { return abi.encodePacked(PT_SEND, _toAddress, _amountSD); } function _decodeSendPayload(bytes memory _payload) internal virtual view returns (address to, uint64 amountSD) { require(_payload.toUint8(0) == PT_SEND && _payload.length == 41); to = _payload.toAddress(13); // drop the first 12 bytes of bytes32 amountSD = _payload.toUint64(33); } function _encodeSendAndCallPayload(address _from, bytes32 _toAddress, uint64 _amountSD, bytes memory _payload, uint64 _dstGasForCall) internal virtual view returns (bytes memory) { return abi.encodePacked( PT_SEND_AND_CALL, _toAddress, _amountSD, _addressToBytes32(_from), _dstGasForCall, _payload ); } function _decodeSendAndCallPayload(bytes memory _payload) internal virtual view returns (bytes32 from, address to, uint64 amountSD, bytes memory payload, uint64 dstGasForCall) { require(_payload.toUint8(0) == PT_SEND_AND_CALL); to = _payload.toAddress(13); // drop the first 12 bytes of bytes32 amountSD = _payload.toUint64(33); from = _payload.toBytes32(41); dstGasForCall = _payload.toUint64(73); payload = _payload.slice(81, _payload.length - 81); } function _addressToBytes32(address _address) internal pure virtual returns (bytes32) { return bytes32(uint(uint160(_address))); } function _debitFrom(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount) internal virtual returns (uint); function _creditTo(uint16 _srcChainId, address _toAddress, uint _amount) internal virtual returns (uint); function _transferFrom(address _from, address _to, uint _amount) internal virtual returns (uint); function _ld2sdRate() internal view virtual returns (uint); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "./BaseOFTV2.sol"; contract OFTV2 is BaseOFTV2, ERC20 { uint internal immutable ld2sdRate; constructor(string memory _name, string memory _symbol, uint8 _sharedDecimals, address _lzEndpoint, uint _fee) ERC20(_name, _symbol) BaseOFTV2(_sharedDecimals, _lzEndpoint) { uint8 decimals = decimals(); require(_sharedDecimals <= decimals); ld2sdRate = 10 ** (decimals - _sharedDecimals); fee = _fee; treasure = msg.sender; } /************************************************************************ * public functions ************************************************************************/ function circulatingSupply() public view virtual override returns (uint) { return totalSupply(); } function token() public view virtual override returns (address) { return address(this); } /************************************************************************ * internal functions ************************************************************************/ function _debitFrom(address _from, uint16, bytes32, uint _amount) internal virtual override returns (uint) { address spender = _msgSender(); if (_from != spender) _spendAllowance(_from, spender, _amount); _burn(_from, _amount); return _amount; } function _creditTo(uint16, address _toAddress, uint _amount) internal virtual override returns (uint) { _mint(_toAddress, _amount); return _amount; } function _transferFrom(address _from, address _to, uint _amount) internal virtual override returns (uint) { address spender = _msgSender(); // if transfer from this contract, no need to check allowance if (_from != address(this) && _from != spender) _spendAllowance(_from, spender, _amount); _transfer(_from, _to, _amount); return _amount; } function _ld2sdRate() internal view virtual override returns (uint) { return ld2sdRate; } }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.7.6; library ExcessivelySafeCall { uint256 constant LOW_28_MASK = 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff; /// @notice Use when you _really_ really _really_ don't trust the called /// contract. This prevents the called contract from causing reversion of /// the caller in as many ways as we can. /// @dev The main difference between this and a solidity low-level call is /// that we limit the number of bytes that the callee can cause to be /// copied to caller memory. This prevents stupid things like malicious /// contracts returning 10,000,000 bytes causing a local OOG when copying /// to memory. /// @param _target The address to call /// @param _gas The amount of gas to forward to the remote contract /// @param _maxCopy The maximum number of bytes of returndata to copy /// to memory. /// @param _calldata The data to send to the remote contract /// @return success and returndata, as `.call()`. Returndata is capped to /// `_maxCopy` bytes. function excessivelySafeCall( address _target, uint256 _gas, uint16 _maxCopy, bytes memory _calldata ) internal returns (bool, bytes memory) { // set up for assembly call uint256 _toCopy; bool _success; bytes memory _returnData = new bytes(_maxCopy); // dispatch message to recipient // by assembly calling "handle" function // we call via assembly to avoid memcopying a very large returndata // returned by a malicious contract assembly { _success := call( _gas, // gas _target, // recipient 0, // ether value add(_calldata, 0x20), // inloc mload(_calldata), // inlen 0, // outloc 0 // outlen ) // limit our copy to 256 bytes _toCopy := returndatasize() if gt(_toCopy, _maxCopy) { _toCopy := _maxCopy } // Store the length of the copied bytes mstore(_returnData, _toCopy) // copy the bytes from returndata[0:_toCopy] returndatacopy(add(_returnData, 0x20), 0, _toCopy) } return (_success, _returnData); } /// @notice Use when you _really_ really _really_ don't trust the called /// contract. This prevents the called contract from causing reversion of /// the caller in as many ways as we can. /// @dev The main difference between this and a solidity low-level call is /// that we limit the number of bytes that the callee can cause to be /// copied to caller memory. This prevents stupid things like malicious /// contracts returning 10,000,000 bytes causing a local OOG when copying /// to memory. /// @param _target The address to call /// @param _gas The amount of gas to forward to the remote contract /// @param _maxCopy The maximum number of bytes of returndata to copy /// to memory. /// @param _calldata The data to send to the remote contract /// @return success and returndata, as `.call()`. Returndata is capped to /// `_maxCopy` bytes. function excessivelySafeStaticCall( address _target, uint256 _gas, uint16 _maxCopy, bytes memory _calldata ) internal view returns (bool, bytes memory) { // set up for assembly call uint256 _toCopy; bool _success; bytes memory _returnData = new bytes(_maxCopy); // dispatch message to recipient // by assembly calling "handle" function // we call via assembly to avoid memcopying a very large returndata // returned by a malicious contract assembly { _success := staticcall( _gas, // gas _target, // recipient add(_calldata, 0x20), // inloc mload(_calldata), // inlen 0, // outloc 0 // outlen ) // limit our copy to 256 bytes _toCopy := returndatasize() if gt(_toCopy, _maxCopy) { _toCopy := _maxCopy } // Store the length of the copied bytes mstore(_returnData, _toCopy) // copy the bytes from returndata[0:_toCopy] returndatacopy(add(_returnData, 0x20), 0, _toCopy) } return (_success, _returnData); } /** * @notice Swaps function selectors in encoded contract calls * @dev Allows reuse of encoded calldata for functions with identical * argument types but different names. It simply swaps out the first 4 bytes * for the new selector. This function modifies memory in place, and should * only be used with caution. * @param _newSelector The new 4-byte selector * @param _buf The encoded contract args */ function swapSelector(bytes4 _newSelector, bytes memory _buf) internal pure { require(_buf.length >= 4); uint256 _mask = LOW_28_MASK; assembly { // load the first word of let _word := mload(add(_buf, 0x20)) // mask out the top 4 bytes // /x _word := and(_word, _mask) _word := or(_newSelector, _word) mstore(add(_buf, 0x20), _word) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "abdk-libraries-solidity/ABDKMath64x64.sol"; library Math { function min(uint256 a, uint256 b) external pure returns (uint256) { if (a > b) return b; return a; } function max(uint256 a, uint256 b) external pure returns (uint256) { if (a > b) return a; return b; } function logX64(uint256 x) external pure returns (int128) { return ABDKMath64x64.log_2(ABDKMath64x64.fromUInt(x)); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/Math.sol": { "Math": "0x9953dc76b5e96dfffa0a926aafab93a7c988ad08" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address","name":"_endpoint","type":"address"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"uint256","name":"_initialMint","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"CallOFTReceivedSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"_reason","type":"bytes"}],"name":"MessageFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"MintClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"}],"name":"NonContractAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rank","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AMP","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"EAA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maturity","type":"uint256"}],"name":"RankClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"ReceiveFromChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"xenContract","type":"address"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"xenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"Redeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"_payloadHash","type":"bytes32"}],"name":"RetryMessageSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"bytes32","name":"_toAddress","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"SendToChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"_type","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_minDstGas","type":"uint256"}],"name":"SetMinDstGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"precrime","type":"address"}],"name":"SetPrecrime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_path","type":"bytes"}],"name":"SetTrustedRemote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"SetTrustedRemoteAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_useCustomAdapterParams","type":"bool"}],"name":"SetUseCustomAdapterParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"AUTHORS_XEN","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAYS_IN_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_RANK_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_RANK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PENALTY_PCT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TERM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NO_EXTRA_GAS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PT_SEND","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PT_SEND_AND_CALL","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER_THRESHOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAWAL_WINDOW_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEX_APY_DAYS_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEX_APY_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEX_APY_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEX_MIN_BURN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEX_MIN_STAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeMinters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes32","name":"_from","type":"bytes32"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_payload","type":"bytes"},{"internalType":"uint256","name":"_gasForCall","type":"uint256"}],"name":"callOnOFTReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"circulatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimMintReward","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pct","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimMintRewardAndStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimRank","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"creditedPackets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes32","name":"_toAddress","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_payload","type":"bytes"},{"internalType":"uint64","name":"_dstGasForCall","type":"uint64"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"estimateSendAndCallFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes32","name":"_toAddress","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"estimateSendFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"failedMessages","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"forceResumeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_configType","type":"uint256"}],"name":"getConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAPY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEAAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentMaxTerm","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rankDelta","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"eaa","type":"uint256"}],"name":"getGrossReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"cRank","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eeaRate","type":"uint256"}],"name":"getMintReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"}],"name":"getTrustedRemoteAddress","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserMint","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"internalType":"struct Main.MintInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserStake","outputs":[{"components":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"internalType":"struct Main.StakeInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalRank","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"isTrustedRemote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lzEndpoint","outputs":[{"internalType":"contract ILayerZeroEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"}],"name":"minDstGasLookup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"nonblockingLzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"precrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"retryMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes32","name":"_toAddress","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_payload","type":"bytes"},{"internalType":"uint64","name":"_dstGasForCall","type":"uint64"},{"components":[{"internalType":"address payable","name":"refundAddress","type":"address"},{"internalType":"address","name":"zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"adapterParams","type":"bytes"}],"internalType":"struct ICommonOFT.LzCallParams","name":"_callParams","type":"tuple"}],"name":"sendAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes32","name":"_toAddress","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"components":[{"internalType":"address payable","name":"refundAddress","type":"address"},{"internalType":"address","name":"zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"adapterParams","type":"bytes"}],"internalType":"struct ICommonOFT.LzCallParams","name":"_callParams","type":"tuple"}],"name":"sendFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"uint256","name":"_configType","type":"uint256"},{"internalType":"bytes","name":"_config","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_endpoint","type":"address"}],"name":"setEndpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint16","name":"_packetType","type":"uint16"},{"internalType":"uint256","name":"_minGas","type":"uint256"}],"name":"setMinDstGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_precrime","type":"address"}],"name":"setPrecrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setReceiveVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setSendVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasure","type":"address"}],"name":"setTreasure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_path","type":"bytes"}],"name":"setTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"setTrustedRemoteAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_useCustomAdapterParams","type":"bool"}],"name":"setUseCustomAdapterParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalXexStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasure","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemoteLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"useCustomAdapterParams","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBurns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMints","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userStakes","outputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60e06040526001600f553480156200001657600080fd5b5060405162006458380380620064588339810160408190526200003991620003c2565b818360088688848484848181808062000052336200014c565b600180546001600160a01b0319166001600160a01b0392909216919091179055505060f81b7fff000000000000000000000000000000000000000000000000000000000000001660805250508151620000b390600d90602085019062000269565b508051620000c990600e90602084019062000269565b5050506000620000de6200019c60201b60201c565b90508060ff168460ff161115620000f457600080fd5b6200010084826200058f565b6200010d90600a620004c1565b60a052506009555050600880546001600160a01b0319163317905550504260c05280156200014157620001413382620001a1565b50505050506200061e565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b601290565b6001600160a01b038216620001fc5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b80600c60008282546200021091906200045d565b90915550506001600160a01b0382166000818152600a60209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b8280546200027790620005b5565b90600052602060002090601f0160209004810192826200029b5760008555620002e6565b82601f10620002b657805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e6578251825591602001919060010190620002c9565b50620002f4929150620002f8565b5090565b5b80821115620002f45760008155600101620002f9565b600082601f83011262000320578081fd5b81516001600160401b03808211156200033d576200033d62000608565b604051601f8301601f19908116603f0116810190828211818310171562000368576200036862000608565b8160405283815260209250868385880101111562000384578485fd5b8491505b83821015620003a7578582018301518183018401529082019062000388565b83821115620003b857848385830101525b9695505050505050565b600080600080600060a08688031215620003da578081fd5b855160208701519095506001600160a01b0381168114620003f9578182fd5b60408701519094506001600160401b038082111562000416578283fd5b6200042489838a016200030f565b945060608801519150808211156200043a578283fd5b5062000449888289016200030f565b925050608086015190509295509295909350565b60008219821115620004735762000473620005f2565b500190565b600181815b80851115620004b95781600019048211156200049d576200049d620005f2565b80851615620004ab57918102915b93841c93908002906200047d565b509250929050565b6000620004d260ff841683620004d9565b9392505050565b600082620004ea5750600162000589565b81620004f95750600062000589565b81600181146200051257600281146200051d576200053d565b600191505062000589565b60ff841115620005315762000531620005f2565b50506001821b62000589565b5060208310610133831016604e8410600b841016171562000562575081810a62000589565b6200056e838362000478565b8060001904821115620005855762000585620005f2565b0290505b92915050565b600060ff821660ff841680821015620005ac57620005ac620005f2565b90039392505050565b600181811c90821680620005ca57607f821691505b60208210811415620005ec57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60805160f81c60a05160c051615deb6200066d60003960008181610f1201528181613eae0152613f110152600081816144fe015281816148630152614adb01526000610a190152615deb6000f3fe60806040526004361061050c5760003560e01c80638da5cb5b11610297578063c56f0bab11610165578063e6a20ae6116100cc578063ed629c5c11610085578063ed629c5c1461100a578063f060482914611024578063f2fde38b14611039578063f340faed14611059578063f5ecbdbc1461106f578063fc0c546a1461108f57600080fd5b8063e6a20ae614610f69578063e81917b414610f7e578063eab45d9c14610f94578063eaffd49a14610fb4578063eb8d72b714610fd4578063ed2f236914610ff457600080fd5b8063ddca3f431161011e578063ddca3f4314610e39578063df28233114610e4f578063df2a5b3b14610ee0578063e3af6d0a14610f00578063e520fc7e14610f34578063e54f57c014610f5457600080fd5b8063c56f0bab14610d84578063cbed8b9c14610d99578063ce653d5f14610db9578063d1deba1f14610de6578063dbbb415514610df9578063dd62ed3e14610e1957600080fd5b8063a457c2d711610209578063b21d35f2116101c2578063b21d35f214610cee578063b353aaa714610d04578063b4800cdc14610d24578063baf3292d14610d3a578063bcfe394f14610d5a578063c0c6525914610d6f57600080fd5b8063a457c2d714610c38578063a4c51df514610c58578063a6c3d16514610c78578063a9059cbb14610c98578063b0fc721714610cb8578063b0fd1fc214610cce57600080fd5b806395d89b411161025b57806395d89b4114610b67578063962ca49614610b7c5780639920245414610b915780639bdb981214610ba65780639f38369a14610bf85780639ff054df14610c1857600080fd5b80638da5cb5b14610a885780638da7ad2314610aba578063909a2ff614610b1c5780639358928b14610b32578063950c8a7414610b4757600080fd5b806344770515116103df5780637010d7a1116103465780637b0472f0116102ff5780637b0472f0146109f4578063857749b014610a0757806385eb8321146107f45780638979c87c14610a3b57806389fb998f146107f45780638cfd8f5c14610a5057600080fd5b80637010d7a1146108fc57806370a0823114610961578063715018a61461099757806372475f94146109ac5780637533d788146109c157806376203b48146109e157600080fd5b8063543d365211610398578063543d3652146106ab5780635b8c41e6146108505780635bccb4c41461089f57806361a52a36146108b257806366ad5c8a146108c9578063695ef6bf146108e957600080fd5b806344770515146107f45780634512571514610809578063471191a1146107f45780634c42899a1461081e5780634e2207a41461083357806352c7f8dc1461084857600080fd5b80631c24408211610483578063365260b41161043c578063365260b414610737578063395093511461076c5780633ccfd60b1461078c5780633d8b38f61461079457806342d65a8d146107b45780634411ad04146107d457600080fd5b80631c244082146106955780631c6f212e146106ab5780631d3cd2a6146106c057806323b872dd146106e0578063313ce56714610700578063323ac7d81461072257600080fd5b8063095ea7b3116104d5578063095ea7b3146105ce5780630bfae56b146105ee5780630f2e12281461060357806310ddb1371461061857806316f9c8fd1461063857806318160ddd1461068057600080fd5b80621d35671461051157806301ffc9a714610533578063023789321461056857806306fdde031461058c57806307e0db17146105ae575b600080fd5b34801561051d57600080fd5b5061053161052c36600461547d565b6110a2565b005b34801561053f57600080fd5b5061055361054e36600461518d565b6112be565b60405190151581526020015b60405180910390f35b34801561057457600080fd5b5061057e61016d81565b60405190815260200161055f565b34801561059857600080fd5b506105a16112f5565b60405161055f919061589c565b3480156105ba57600080fd5b506105316105c9366004615223565b611387565b3480156105da57600080fd5b506105536105e9366004615148565b6113f4565b3480156105fa57600080fd5b5061057e61140c565b34801561060f57600080fd5b5061057e606381565b34801561062457600080fd5b50610531610633366004615223565b61141d565b34801561064457600080fd5b5061064d611459565b60405161055f91908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561068c57600080fd5b50600c5461057e565b3480156106a157600080fd5b5061057e600f5481565b3480156106b757600080fd5b5061057e600181565b3480156106cc57600080fd5b506105316106db366004614f94565b6114ca565b3480156106ec57600080fd5b506105536106fb366004614fe8565b611507565b34801561070c57600080fd5b5060125b60405160ff909116815260200161055f565b34801561072e57600080fd5b5061057e602381565b34801561074357600080fd5b5061075761075236600461523d565b61152b565b6040805192835260208301919091520161055f565b34801561077857600080fd5b50610553610787366004615148565b611595565b6105316115b7565b3480156107a057600080fd5b506105536107af366004615368565b61178a565b3480156107c057600080fd5b506105316107cf366004615368565b611856565b3480156107e057600080fd5b5061057e6107ef36600461575a565b6118c0565b34801561080057600080fd5b5061057e600081565b34801561081557600080fd5b5061057e611a9f565b34801561082a57600080fd5b50610710600081565b34801561083f57600080fd5b506105a1611aae565b610531611aca565b34801561085c57600080fd5b5061057e61086b3660046154fb565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b6105316108ad3660046156e5565b611cce565b3480156108be57600080fd5b5061057e6201518081565b3480156108d557600080fd5b506105316108e436600461547d565b611f90565b6105316108f73660046150d7565b61201a565b34801561090857600080fd5b50610911612136565b60405161055f919081516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0918201519181019190915260c00190565b34801561096d57600080fd5b5061057e61097c366004614f94565b6001600160a01b03166000908152600a602052604090205490565b3480156109a357600080fd5b506105316121db565b3480156109b857600080fd5b5061057e600f81565b3480156109cd57600080fd5b506105a16109dc366004615223565b6121ef565b6105316109ef366004615028565b612289565b610531610a023660046156e5565b6123ea565b348015610a1357600080fd5b506107107f000000000000000000000000000000000000000000000000000000000000000081565b348015610a4757600080fd5b5061057e612579565b348015610a5c57600080fd5b5061057e610a6b366004615590565b600360209081526000928352604080842090915290825290205481565b348015610a9457600080fd5b506000546001600160a01b03165b6040516001600160a01b03909116815260200161055f565b348015610ac657600080fd5b50610afc610ad5366004614f94565b60146020526000908152604090208054600182015460028301546003909301549192909184565b60408051948552602085019390935291830152606082015260800161055f565b348015610b2857600080fd5b5061057e6103e881565b348015610b3e57600080fd5b5061057e612583565b348015610b5357600080fd5b50600454610aa2906001600160a01b031681565b348015610b7357600080fd5b506105a161258e565b348015610b8857600080fd5b5061057e61259d565b348015610b9d57600080fd5b5061057e6125a7565b348015610bb257600080fd5b50610553610bc13660046154fb565b6007602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205460ff1681565b348015610c0457600080fd5b506105a1610c13366004615223565b6125b1565b348015610c2457600080fd5b50610531610c333660046156b5565b6126c8565b348015610c4457600080fd5b50610553610c53366004615148565b61286e565b348015610c6457600080fd5b50610757610c733660046152b2565b6128e9565b348015610c8457600080fd5b50610531610c93366004615368565b61299c565b348015610ca457600080fd5b50610553610cb3366004615148565b612a2f565b348015610cc457600080fd5b5061057e60125481565b348015610cda57600080fd5b5061057e610ce9366004615729565b612a3d565b348015610cfa57600080fd5b5061057e61138881565b348015610d1057600080fd5b50600154610aa2906001600160a01b031681565b348015610d3057600080fd5b5061057e60105481565b348015610d4657600080fd5b50610531610d55366004614f94565b612acc565b348015610d6657600080fd5b5061057e600a81565b348015610d7b57600080fd5b5061057e612b29565b348015610d9057600080fd5b5061057e600781565b348015610da557600080fd5b50610531610db4366004615649565b612b37565b348015610dc557600080fd5b5061057e610dd4366004614f94565b60156020526000908152604090205481565b610531610df436600461547d565b612bb0565b348015610e0557600080fd5b50610531610e14366004614f94565b612d2a565b348015610e2557600080fd5b5061057e610e34366004614fb0565b612d6a565b348015610e4557600080fd5b5061057e60095481565b348015610e5b57600080fd5b50610ea9610e6a366004614f94565b6013602052600090815260409020805460018201546002830154600384015460048501546005909501546001600160a01b039094169492939192909186565b604080516001600160a01b0390971687526020870195909552938501929092526060840152608083015260a082015260c00161055f565b348015610eec57600080fd5b50610531610efb36600461560e565b612d95565b348015610f0c57600080fd5b5061057e7f000000000000000000000000000000000000000000000000000000000000000081565b348015610f4057600080fd5b50600854610aa2906001600160a01b031681565b348015610f6057600080fd5b5061057e601481565b348015610f7557600080fd5b50610710600181565b348015610f8a57600080fd5b5061057e6102da81565b348015610fa057600080fd5b50610531610faf366004615173565b612e47565b348015610fc057600080fd5b50610531610fcf3660046153b8565b612e90565b348015610fe057600080fd5b50610531610fef366004615368565b612f6c565b34801561100057600080fd5b5061057e60115481565b34801561101657600080fd5b506006546105539060ff1681565b34801561103057600080fd5b5061057e612fc6565b34801561104557600080fd5b50610531611054366004614f94565b612fdf565b34801561106557600080fd5b5061057e61271081565b34801561107b57600080fd5b506105a161108a3660046155c2565b613058565b34801561109b57600080fd5b5030610aa2565b6001546001600160a01b0316336001600160a01b03161461110a5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff86166000908152600260205260408120805461112890615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461115490615cd5565b80156111a15780601f10611176576101008083540402835291602001916111a1565b820191906000526020600020905b81548152906001019060200180831161118457829003601f168201915b505050505090508051868690501480156111bc575060008151115b80156111e45750805160208201206040516111da90889088906157e9565b6040518091039020145b61123f5760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401611101565b6112b58787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506130f192505050565b50505050505050565b60006001600160e01b03198216631f7ecdf760e01b14806112ef57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600d805461130490615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461133090615cd5565b801561137d5780601f106113525761010080835404028352916020019161137d565b820191906000526020600020905b81548152906001019060200180831161136057829003601f168201915b5050505050905090565b61138f61316a565b6001546040516307e0db1760e01b815261ffff831660048201526001600160a01b03909116906307e0db17906024015b600060405180830381600087803b1580156113d957600080fd5b505af11580156113ed573d6000803e3d6000fd5b5050505050565b6000336114028185856131c4565b5060019392505050565b61141a620151806064615c5c565b81565b61142561316a565b6001546040516310ddb13760e01b815261ffff831660048201526001600160a01b03909116906310ddb137906024016113bf565b6114846040518060800160405280600081526020016000815260200160008152602001600081525090565b5033600090815260146020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b6114d261316a565b6001600160a01b0381166114e557600080fd5b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6000336115158582856132e9565b611520858585613363565b506001949350505050565b6000806000806115748a8a8a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061350e92505050565b91509150600954826115869190615c30565b9a909950975050505050505050565b6000336114028185856115a88383612d6a565b6115b29190615c30565b6131c4565b6009543410156115d95760405162461bcd60e51b8152600401611101906158dd565b6000341180156115eb57506000600954115b15611654576008546009546040516000926001600160a01b031691908381818185875af1925050503d806000811461163f576040519150601f19603f3d011682016040523d82523d6000602084013e611644565b606091505b505090508061165257600080fd5b505b3360009081526014602090815260409182902082516080810184528154815260018201549281019290925260028101549282018390526003015460608201529061169d57600080fd5b60006116bb82604001518360000151846020015185606001516135f3565b6011805491925060006116cd83615cbe565b91905055508160400151601260008282546116e89190615c7b565b92505081905550611708338284604001516117039190615c30565b613651565b600854611723906001600160a01b0316611703606484615c48565b60408083015181519081526020810183905233917f92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc6910160405180910390a25050336000908152601460205260408120818155600181018290556002810182905560030155565b61ffff8316600090815260026020526040812080548291906117ab90615cd5565b80601f01602080910402602001604051908101604052809291908181526020018280546117d790615cd5565b80156118245780601f106117f957610100808354040283529160200191611824565b820191906000526020600020905b81548152906001019060200180831161180757829003601f168201915b50505050509050838360405161183b9291906157e9565b60405180910390208180519060200120149150509392505050565b61185e61316a565b6001546040516342d65a8d60e01b81526001600160a01b03909116906342d65a8d906118929086908690869060040161594c565b600060405180830381600087803b1580156118ac57600080fd5b505af11580156112b5573d6000803e3d6000fd5b6000834211156119d35760006118d68542615c7b565b905060006118e382613712565b90506000739953dc76b5e96dfffa0a926aafab93a7c988ad08636d5433e68a600f5461190f9190615c7b565b6040516001600160e01b031960e084901b16815260048101919091526002602482015260440160206040518083038186803b15801561194d57600080fd5b505af4158015611961573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198591906156cd565b90506000611995866103e8615c30565b905060006119a583898c85612a3d565b905060646119b38582615c7b565b6119bd9083615c5c565b6119c79190615c48565b95505050505050611a96565b6000739953dc76b5e96dfffa0a926aafab93a7c988ad08636d5433e688600f546119fd9190615c7b565b6040516001600160e01b031960e084901b16815260048101919091526002602482015260440160206040518083038186803b158015611a3b57600080fd5b505af4158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7391906156cd565b90506000611a83846103e8615c30565b9050611a9182868984612a3d565b925050505b95945050505050565b6000611aa96137f6565b905090565b604051806060016040528060258152602001615d916025913981565b600954341015611aec5760405162461bcd60e51b8152600401611101906158dd565b600034118015611afe57506000600954115b15611b67576008546009546040516000926001600160a01b031691908381818185875af1925050503d8060008114611b52576040519150601f19603f3d011682016040523d82523d6000602084013e611b57565b606091505b5050905080611b6557600080fd5b505b33600090815260136020908152604091829020825160c08101845281546001600160a01b031681526001820154928101929092526002810154928201929092526003820154606082018190526004830154608083015260059092015460a082015290611bf95760405162461bcd60e51b81526020600482015260016024820152604160f81b6044820152606401611101565b80604001514211611c305760405162461bcd60e51b81526020600482015260016024820152602160f91b6044820152606401611101565b6000611c5382606001518360200151846040015185608001518660a0015161390a565b611c6590670de0b6b3a7640000615c5c565b9050611c713382613651565b600854611c8c906001600160a01b0316611703606484615c48565b611c94613a17565b60405181815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a25050565b600954341015611cf05760405162461bcd60e51b8152600401611101906158dd565b600034118015611d0257506000600954115b15611d6b576008546009546040516000926001600160a01b031691908381818185875af1925050503d8060008114611d56576040519150601f19603f3d011682016040523d82523d6000602084013e611d5b565b606091505b5050905080611d6957600080fd5b505b33600090815260136020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015260658310611dd757600080fd5b6000816060015111611de857600080fd5b80604001514211611df857600080fd5b6000611e1b82606001518360200151846040015185608001518660a0015161390a565b611e2d90670de0b6b3a7640000615c5c565b905060006064611e3d8684615c5c565b611e479190615c48565b90506000611e558284615c7b565b9050611e613382613651565b600854611e7c906001600160a01b0316611703606486615c48565b611e84613a17565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a69060200160405180910390a260008211611ec657600080fd5b6001611ed56201518082615c5c565b611edf9190615c7b565b611eec6201518087615c5c565b11611ef657600080fd5b611f046201518060f4615c5c565b611f0f906001615c30565b611f1c6201518087615c5c565b10611f2657600080fd5b3360009081526014602052604090206002015415611f4357600080fd5b611f4d8286613a6b565b604080518381526020810187905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90910160405180910390a2505050505050565b333014611f9c57600080fd5b6120128686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815289935091508790879081908401838280828437600092019190915250613b0e92505050565b505050505050565b60095434101561203c5760405162461bcd60e51b8152600401611101906158dd565b60003411801561204e57506000600954115b156120b7576008546009546040516000926001600160a01b031691908381818185875af1925050503d80600081146120a2576040519150601f19603f3d011682016040523d82523d6000602084013e6120a7565b606091505b50509050806120b557600080fd5b505b6000600954346120c79190615c7b565b90506112b5868686866120dd6020880188614f94565b6120ed6040890160208a01614f94565b6120fa60408a018a615b95565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b9250613b6f915050565b6121786040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b5033600090815260136020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015290565b6121e361316a565b6121ed6000613c19565b565b6002602052600090815260409020805461220890615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461223490615cd5565b80156122815780601f1061225657610100808354040283529160200191612281565b820191906000526020600020905b81548152906001019060200180831161226457829003601f168201915b505050505081565b6009543410156122ab5760405162461bcd60e51b8152600401611101906158dd565b6000341180156122bd57506000600954115b15612326576008546009546040516000926001600160a01b031691908381818185875af1925050503d8060008114612311576040519150601f19603f3d011682016040523d82523d6000602084013e612316565b606091505b505090508061232457600080fd5b505b6000600954346123369190615c7b565b90506123de8989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b925061238591505060208a018a614f94565b61239560408b0160208c01614f94565b6123a260408c018c615b95565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d9250613c69915050565b50505050505050505050565b60095434101561240c5760405162461bcd60e51b8152600401611101906158dd565b60003411801561241e57506000600954115b15612487576008546009546040516000926001600160a01b031691908381818185875af1925050503d8060008114612472576040519150601f19603f3d011682016040523d82523d6000602084013e612477565b606091505b505090508061248557600080fd5b505b336000908152600a60205260409020548211156124a357600080fd5b600082116124b057600080fd5b60016124bf6201518082615c5c565b6124c99190615c7b565b6124d66201518083615c5c565b116124e057600080fd5b6124ee6201518060f4615c5c565b6124f9906001615c30565b6125066201518083615c5c565b1061251057600080fd5b336000908152601460205260409020600201541561252d57600080fd5b6125373383613d27565b6125418282613a6b565b604080518381526020810183905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909101611cc2565b6000611aa9613e53565b6000611aa9600c5490565b6060600e805461130490615cd5565b6000611aa9613e98565b6000611aa9613f05565b61ffff81166000908152600260205260408120805460609291906125d490615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461260090615cd5565b801561264d5780601f106126225761010080835404028352916020019161264d565b820191906000526020600020905b81548152906001019060200180831161263057829003601f168201915b505050505090508051600014156126a65760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401611101565b6126c16000601483516126b99190615c7b565b839190613ff4565b9392505050565b60006126d76201518083615c5c565b905060016126e86201518082615c5c565b6126f29190615c7b565b81116126fd57600080fd5b6127056137f6565b612710906001615c30565b811061271b57600080fd5b336000908152601360205260409020600301541561273857600080fd5b6040805160c08101825233815260208101849052600091810161275b8442615c30565b8152602001600f548152602001612770613f05565b815260200161277d613e53565b9052336000908152601360209081526040808320845181546001600160a01b0319166001600160a01b039091161781559184015160018301558301516002820155606083015160038201556080830151600482015560a083015160059091015560108054929350906127ee83615d0a565b9091555050600f805433917fc05062aaca3ffe3bd48e1cd6edc912dff77e39ba1a14999b5e00ec68614b311c918691600061282883615d0a565b919050556128346125a7565b60a08681015160408089015181519687526020870195909552858101939093526060850152608084019290925251918290030190a2505050565b6000338161287c8286612d6a565b9050838110156128dc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401611101565b61152082868684036131c4565b6000806000806129788d8d8d8d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061410192505050565b915091506009548261298a9190615c30565b9d909c509a5050505050505050505050565b6129a461316a565b8181306040516020016129b9939291906157f9565b60408051601f1981840301815291815261ffff851660009081526002602090815291902082516129ee93919290910190614df0565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce838383604051612a229392919061594c565b60405180910390a1505050565b600033611402818585613363565b600080612a54612a4c876141b4565b600f0b6141d2565b90506000612a90612a64856141b4565b612a87612a70886141b4565b612a87612a7c8b6141b4565b600f88900b906142b6565b600f0b906142b6565b9050612ab6612aae612aa36103e86141b4565b600f84900b906142ed565b600f0b614353565b6001600160401b0316925050505b949350505050565b612ad461316a565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b906020015b60405180910390a150565b61141a6201518060f4615c5c565b612b3f61316a565b6001546040516332fb62e760e21b81526001600160a01b039091169063cbed8b9c90612b779088908890889088908890600401615b67565b600060405180830381600087803b158015612b9157600080fd5b505af1158015612ba5573d6000803e3d6000fd5b505050505050505050565b61ffff86166000908152600560205260408082209051612bd390889088906157e9565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080612c0457600080fd5b808383604051612c159291906157e9565b604051809103902014612c2757600080fd5b61ffff87166000908152600560205260408082209051612c4a90899089906157e9565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252612ce2918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a935091508890889081908401838280828437600092019190915250613b0e92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051612d1995949392919061596a565b60405180910390a150505050505050565b612d3261316a565b6001546001600160a01b031615612d4857600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b039182166000908152600b6020908152604080832093909416825291909152205490565b612d9d61316a565b60008111612de55760405162461bcd60e51b81526020600482015260156024820152744c7a4170703a20696e76616c6964206d696e47617360581b6044820152606401611101565b61ffff83811660008181526003602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001612a22565b612e4f61316a565b6006805460ff19168215159081179091556040519081527f1584ad594a70cbe1e6515592e1272a987d922b097ead875069cebe8b40c004a490602001612b1e565b333014612e9c57600080fd5b612ea730868661436f565b9350846001600160a01b03168a61ffff167fbf551ec93859b170f9b2141bd9298bf3f64322c6f7beb2543a0cb669834118bf86604051612ee991815260200190565b60405180910390a3604051633fe79aed60e11b81526001600160a01b03861690637fcf35da908390612f2d908e908e908e908e908e908d908d908d906004016159a5565b600060405180830381600088803b158015612f4757600080fd5b5087f1158015612f5b573d6000803e3d6000fd5b505050505050505050505050505050565b612f7461316a565b61ffff83166000908152600260205260409020612f92908383614e70565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab838383604051612a229392919061594c565b6001612fd56201518082615c5c565b61141a9190615c7b565b612fe761316a565b6001600160a01b03811661304c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611101565b61305581613c19565b50565b600154604051633d7b2f6f60e21b815261ffff808716600483015285166024820152306044820152606481018390526060916001600160a01b03169063f5ecbdbc9060840160006040518083038186803b1580156130b557600080fd5b505afa1580156130c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a9691908101906151b5565b6000806131545a60966366ad5c8a60e01b898989896040516024016131199493929190615acc565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152309291906143c1565b9150915081612012576120128686868685614459565b6000546001600160a01b031633146121ed5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611101565b6001600160a01b0383166132265760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401611101565b6001600160a01b0382166132875760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401611101565b6001600160a01b038381166000818152600b602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006132f58484612d6a565b9050600019811461335d57818110156133505760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401611101565b61335d84848484036131c4565b50505050565b6001600160a01b0383166133c75760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401611101565b6001600160a01b0382166134295760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401611101565b6001600160a01b0383166000908152600a6020526040902054818110156134a15760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401611101565b6001600160a01b038085166000818152600a602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906135019086815260200190565b60405180910390a361335d565b600080600061355c87613520886144f6565b6040805160006020820152602181019390935260c09190911b6001600160c01b0319166041830152805160298184030181526049909201905290565b60015460405163040a7bb160e41b81529192506001600160a01b0316906340a7bb1090613595908b90309086908b908b906004016158f8565b604080518083038186803b1580156135ac57600080fd5b505afa1580156135c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e49190615706565b92509250509550959350505050565b60008242111561364657600061016d61360c8685615c5c565b61361990620f4240615c5c565b6136239190615c48565b90506305f5e1006136348288615c5c565b61363e9190615c48565b915050612ac4565b506000949350505050565b6001600160a01b0382166136a75760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401611101565b80600c60008282546136b99190615c30565b90915550506001600160a01b0382166000818152600a60209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6000806137226201518084615c48565b905061373060016007615c7b565b8111156137405750606392915050565b600060016007613751846003615c30565b6001901b61375f9190615c48565b6137699190615c7b565b604051637ae2b5c760e01b81526004810182905260636024820152909150739953dc76b5e96dfffa0a926aafab93a7c988ad0890637ae2b5c79060440160206040518083038186803b1580156137be57600080fd5b505af41580156137d2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac491906156cd565b6000611388600f5411156138fc576000613824612aae613816600f6141b4565b612a87612a4c600f546141b4565b6001600160401b03169050600061383e6201518083615c5c565b61384c620151806064615c5c565b6138569190615c30565b9050739953dc76b5e96dfffa0a926aafab93a7c988ad08637ae2b5c7826138816201518060f4615c5c565b6040516001600160e01b031960e085901b1681526004810192909252602482015260440160206040518083038186803b1580156138bd57600080fd5b505af41580156138d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f591906156cd565b9250505090565b611aa9620151806064615c5c565b6000806139178542615c7b565b9050600061392482613712565b90506000739953dc76b5e96dfffa0a926aafab93a7c988ad08636d5433e68a600f546139509190615c7b565b6040516001600160e01b031960e084901b16815260048101919091526002602482015260440160206040518083038186803b15801561398e57600080fd5b505af41580156139a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139c691906156cd565b905060006139d6866103e8615c30565b905060006139e683898c85612a3d565b905060646139f48582615c7b565b6139fe9083615c5c565b613a089190615c48565b9b9a5050505050505050505050565b33600090815260136020526040812080546001600160a01b0319168155600181018290556002810182905560038101829055600481018290556005018190556010805491613a6483615cbe565b9190505550565b60405180608001604052808281526020016201518083613a8b9190615c5c565b613a959042615c30565b8152602001838152602001613aa8613e98565b90523360009081526014602090815260408083208451815591840151600183015583015160028201556060909201516003909201919091556011805491613aee83615d0a565b91905055508160126000828254613b059190615c30565b90915550505050565b6000613b1a8282614539565b905060ff8116613b3557613b3085858585614595565b6113ed565b60ff811660011415613b4d57613b3085858585614625565b60405162461bcd60e51b81526020600482015260006024820152604401611101565b6000613b7d88828581614833565b613b868661485b565b509050613b958989898461489b565b905060008111613ba457600080fd5b6000613bb388613520846144f6565b9050613bc38982888888886148cd565b878a6001600160a01b03168a61ffff167fd81fc9b8523134ed613870ed029d6170cbb73aa6a6bc311b9a642689fb9df59a85604051613c0491815260200190565b60405180910390a45098975050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000613c818a6001856001600160401b038a16614833565b613c8a8861485b565b509050613c998b8b8b8461489b565b905060008111613ca857600080fd5b6000613cbf338b613cb8856144f6565b8b8b614a4c565b9050613ccf8b82888888886148cd565b898c6001600160a01b03168c61ffff167fd81fc9b8523134ed613870ed029d6170cbb73aa6a6bc311b9a642689fb9df59a85604051613d1091815260200190565b60405180910390a4509a9950505050505050505050565b6001600160a01b038216613d875760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401611101565b6001600160a01b0382166000908152600a602052604090205481811015613dfb5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401611101565b6001600160a01b0383166000818152600a602090815260408083208686039055600c80548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91016132dc565b600080612710600f54600a613e689190615c5c565b613e729190615c48565b90506103e8811115613e8657600091505090565b613e92816103e8615c7b565b91505090565b600080613ea9601462015180615c5c565b613ed37f000000000000000000000000000000000000000000000000000000000000000042615c7b565b613edd9190615c48565b905080613eec60006023615c7b565b1015613efa57600091505090565b613e92816023615c7b565b60008062015180613f367f000000000000000000000000000000000000000000000000000000000000000042615c7b565b613f409190615c48565b90506102da811015613fe857739953dc76b5e96dfffa0a926aafab93a7c988ad08636d5433e6613f72836102da615c7b565b6040516001600160e01b031960e084901b16815260048101919091526001602482015260440160206040518083038186803b158015613fb057600080fd5b505af4158015613fc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e9291906156cd565b600191505090565b5090565b60608161400281601f615c30565b10156140415760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401611101565b61404b8284615c30565b8451101561408f5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401611101565b6060821580156140ae57604051915060008252602082016040526140f8565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156140e75780518352602092830192016140cf565b5050858452601f01601f1916604052505b50949350505050565b600080600061411b338a6141148b6144f6565b8a8a614a4c565b60015460405163040a7bb160e41b81529192506001600160a01b0316906340a7bb1090614154908d90309086908b908b906004016158f8565b604080518083038186803b15801561416b57600080fd5b505afa15801561417f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141a39190615706565b925092505097509795505050505050565b6000677fffffffffffffff8211156141cb57600080fd5b5060401b90565b60008082600f0b136141e357600080fd5b6000600f83900b680100000000000000008112614202576040918201911d5b6401000000008112614216576020918201911d5b620100008112614228576010918201911d5b6101008112614239576008918201911d5b60108112614249576004918201911d5b60048112614259576002918201911d5b60028112614268576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156142ab5790800260ff81901c8281029390930192607f011c9060011d614285565b509095945050505050565b6000600f83810b9083900b0260401d60016001607f1b031981128015906142e4575060016001607f1b038113155b6126c157600080fd5b600081600f0b6000141561430057600080fd5b600082600f0b604085600f0b901b8161432957634e487b7160e01b600052601260045260246000fd5b05905060016001607f1b031981128015906142e4575060016001607f1b038113156126c157600080fd5b60008082600f0b121561436557600080fd5b50600f0b60401d90565b600033306001600160a01b0386161480159061439d5750806001600160a01b0316856001600160a01b031614155b156143ad576143ad8582856132e9565b6143b8858585613363565b50909392505050565b6000606060008060008661ffff166001600160401b038111156143f457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561441e576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115614440578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff1681526020019081526020016000208560405161448a919061581f565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c906144e79087908790879087908790615b15565b60405180910390a15050505050565b6000806145237f000000000000000000000000000000000000000000000000000000000000000084615c48565b90506001600160401b038111156112ef57600080fd5b6000614546826001615c30565b8351101561458c5760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b6044820152606401611101565b50016001015190565b6000806145a183614a8d565b90925090506001600160a01b0382166145ba5761dead91505b60006145c582614ad4565b90506145d2878483614b09565b9050826001600160a01b03168761ffff167fbf551ec93859b170f9b2141bd9298bf3f64322c6f7beb2543a0cb669834118bf8360405161461491815260200190565b60405180910390a350505050505050565b600080600080600061463686614b1c565b945094509450945094506000600760008b61ffff1661ffff1681526020019081526020016000208960405161466b919061581f565b90815260408051602092819003830190206001600160401b038b166000908152925281205460ff16915061469e85614ad4565b90508161470c576146b08b3083614b09565b61ffff8c166000908152600760205260409081902090519192506001916146d8908d9061581f565b90815260408051602092819003830190206001600160401b038d16600090815292529020805460ff19169115159190911790555b6001600160a01b0386163b614763576040516001600160a01b03871681527f9aedf5fdba8716db3b6705ca00150643309995d4f818a249ed6dde6677e7792d9060200160405180910390a15050505050505061335d565b8a8a8a8a8a8a868a60008a614781578b6001600160401b0316614783565b5a5b90506000806147b55a609663eaffd49a60e01b8e8e8e8d8d8d8d8d604051602401613119989796959493929190615a58565b91509150811561480e578751602089012060405161ffff8d16907fb8890edbfc1c74692f527444645f95489c3703cc2df42e4a366f5d06fa6cd88490614800908e908e9086906158af565b60405180910390a25061481b565b61481b8b8b8b8b85614459565b50505050505050505050505050505050505050505050565b60065460ff161561484f5761484a84848484614b95565b61335d565b81511561335d57600080fd5b6000806148887f000000000000000000000000000000000000000000000000000000000000000084615d25565b90506148948184615c7b565b9150915091565b6000336001600160a01b03861681146148b9576148b98682856132e9565b6148c38684613d27565b5090949350505050565b61ffff8616600090815260026020526040812080546148eb90615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461491790615cd5565b80156149645780601f1061493957610100808354040283529160200191614964565b820191906000526020600020905b81548152906001019060200180831161494757829003601f168201915b505050505090508051600014156149d65760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401611101565b60015460405162c5803160e81b81526001600160a01b039091169063c5803100908490614a11908b9086908c908c908c908c906004016159f1565b6000604051808303818588803b158015614a2a57600080fd5b505af1158015614a3e573d6000803e3d6000fd5b505050505050505050505050565b6060600185856001600160a01b0389168587604051602001614a739695949392919061583b565b604051602081830303815290604052905095945050505050565b60008080614a9b8482614539565b60ff16148015614aac575082516029145b614ab557600080fd5b614ac083600d614c74565b9150614acd836021614cd9565b9050915091565b60006112ef7f00000000000000000000000000000000000000000000000000000000000000006001600160401b038416615c5c565b6000614b158383613651565b5092915050565b600080806060816001614b2f8783614539565b60ff1614614b3c57600080fd5b614b4786600d614c74565b9350614b54866021614cd9565b9250614b61866029614d36565b9450614b6e866049614cd9565b9050614b8a6051808851614b829190615c7b565b889190613ff4565b915091939590929450565b6000614ba083614d94565b61ffff808716600090815260036020908152604080832093891683529290529081205491925090614bd2908490615c30565b905060008111614c245760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401611101565b808210156120125760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401611101565b6000614c81826014615c30565b83511015614cc95760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606401611101565b500160200151600160601b900490565b6000614ce6826008615c30565b83511015614d2d5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b6044820152606401611101565b50016008015190565b6000614d43826020615c30565b83511015614d8b5760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b6044820152606401611101565b50016020015190565b6000602282511015614de85760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401611101565b506022015190565b828054614dfc90615cd5565b90600052602060002090601f016020900481019282614e1e5760008555614e64565b82601f10614e3757805160ff1916838001178555614e64565b82800160010185558215614e64579182015b82811115614e64578251825591602001919060010190614e49565b50613ff0929150614ee4565b828054614e7c90615cd5565b90600052602060002090601f016020900481019282614e9e5760008555614e64565b82601f10614eb75782800160ff19823516178555614e64565b82800160010185558215614e64579182015b82811115614e64578235825591602001919060010190614ec9565b5b80821115613ff05760008155600101614ee5565b80358015158114614f0957600080fd5b919050565b60008083601f840112614f1f578182fd5b5081356001600160401b03811115614f35578182fd5b602083019150836020828501011115614f4d57600080fd5b9250929050565b600060608284031215614f65578081fd5b50919050565b803561ffff81168114614f0957600080fd5b80356001600160401b0381168114614f0957600080fd5b600060208284031215614fa5578081fd5b81356126c181615d7b565b60008060408385031215614fc2578081fd5b8235614fcd81615d7b565b91506020830135614fdd81615d7b565b809150509250929050565b600080600060608486031215614ffc578081fd5b833561500781615d7b565b9250602084013561501781615d7b565b929592945050506040919091013590565b60008060008060008060008060e0898b031215615043578384fd5b883561504e81615d7b565b975061505c60208a01614f6b565b9650604089013595506060890135945060808901356001600160401b0380821115615085578586fd5b6150918c838d01614f0e565b90965094508491506150a560a08c01614f7d565b935060c08b01359150808211156150ba578283fd5b506150c78b828c01614f54565b9150509295985092959890939650565b600080600080600060a086880312156150ee578081fd5b85356150f981615d7b565b945061510760208701614f6b565b9350604086013592506060860135915060808601356001600160401b0381111561512f578182fd5b61513b88828901614f54565b9150509295509295909350565b6000806040838503121561515a578182fd5b823561516581615d7b565b946020939093013593505050565b600060208284031215615184578081fd5b6126c182614ef9565b60006020828403121561519e578081fd5b81356001600160e01b0319811681146126c1578182fd5b6000602082840312156151c6578081fd5b81516001600160401b038111156151db578182fd5b8201601f810184136151eb578182fd5b80516151fe6151f982615c09565b615bd9565b818152856020838501011115615212578384fd5b611a96826020830160208601615c92565b600060208284031215615234578081fd5b6126c182614f6b565b60008060008060008060a08789031215615255578384fd5b61525e87614f6b565b9550602087013594506040870135935061527a60608801614ef9565b925060808701356001600160401b03811115615294578283fd5b6152a089828a01614f0e565b979a9699509497509295939492505050565b600080600080600080600080600060e08a8c0312156152cf578283fd5b6152d88a614f6b565b985060208a0135975060408a0135965060608a01356001600160401b0380821115615301578485fd5b61530d8d838e01614f0e565b909850965086915061532160808d01614f7d565b955061532f60a08d01614ef9565b945060c08c0135915080821115615344578283fd5b506153518c828d01614f0e565b915080935050809150509295985092959850929598565b60008060006040848603121561537c578081fd5b61538584614f6b565b925060208401356001600160401b0381111561539f578182fd5b6153ab86828701614f0e565b9497909650939450505050565b6000806000806000806000806000806101008b8d0312156153d7578384fd5b6153e08b614f6b565b995060208b01356001600160401b03808211156153fb578586fd5b6154078e838f01614f0e565b909b50995089915061541b60408e01614f7d565b985060608d0135975060808d0135915061543482615d7b565b90955060a08c0135945060c08c01359080821115615450578283fd5b5061545d8d828e01614f0e565b9150809450508092505060e08b013590509295989b9194979a5092959850565b60008060008060008060808789031215615495578384fd5b61549e87614f6b565b955060208701356001600160401b03808211156154b9578586fd5b6154c58a838b01614f0e565b90975095508591506154d960408a01614f7d565b945060608901359150808211156154ee578384fd5b506152a089828a01614f0e565b60008060006060848603121561550f578081fd5b61551884614f6b565b925060208401356001600160401b03811115615532578182fd5b8401601f81018613615542578182fd5b80356155506151f982615c09565b818152876020838501011115615564578384fd5b816020840160208301379081016020018390529250615587905060408501614f7d565b90509250925092565b600080604083850312156155a2578182fd5b6155ab83614f6b565b91506155b960208401614f6b565b90509250929050565b600080600080608085870312156155d7578182fd5b6155e085614f6b565b93506155ee60208601614f6b565b925060408501356155fe81615d7b565b9396929550929360600135925050565b600080600060608486031215615622578081fd5b61562b84614f6b565b925061563960208501614f6b565b9150604084013590509250925092565b600080600080600060808688031215615660578283fd5b61566986614f6b565b945061567760208701614f6b565b93506040860135925060608601356001600160401b03811115615698578182fd5b6156a488828901614f0e565b969995985093965092949392505050565b6000602082840312156156c6578081fd5b5035919050565b6000602082840312156156de578081fd5b5051919050565b600080604083850312156156f7578182fd5b50508035926020909101359150565b60008060408385031215615718578182fd5b505080516020909101519092909150565b6000806000806080858703121561573e578182fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a08688031215615771578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600081518084526157d5816020860160208601615c92565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251615831818460208701615c92565b9190910192915050565b60ff60f81b8760f81b16815285600182015260006001600160401b0360c01b808760c01b166021840152856029840152808560c01b16604984015250825161588a816051850160208701615c92565b91909101605101979650505050505050565b6020815260006126c160208301846157bd565b6060815260006158c260608301866157bd565b6001600160401b039490941660208301525060400152919050565b6020808252600190820152602360f91b604082015260600190565b61ffff861681526001600160a01b038516602082015260a060408201819052600090615926908301866157bd565b8415156060840152828103608084015261594081856157bd565b98975050505050505050565b61ffff84168152604060208201526000611a96604083018486615794565b61ffff86168152608060208201526000615988608083018688615794565b6001600160401b0394909416604083015250606001529392505050565b61ffff8916815260c0602082015260006159c360c08301898b615794565b6001600160401b038816604084015286606084015285608084015282810360a0840152613a08818587615794565b61ffff8716815260c060208201526000615a0e60c08301886157bd565b8281036040840152615a2081886157bd565b6001600160a01b0387811660608601528616608085015283810360a08501529050615a4b81856157bd565b9998505050505050505050565b600061010061ffff8b168352806020840152615a768184018b6157bd565b6001600160401b038a166040850152606084018990526001600160a01b038816608085015260a0840187905283810360c08501529050615ab681866157bd565b9150508260e08301529998505050505050505050565b61ffff85168152608060208201526000615ae960808301866157bd565b6001600160401b03851660408401528281036060840152615b0a81856157bd565b979650505050505050565b61ffff8616815260a060208201526000615b3260a08301876157bd565b6001600160401b03861660408401528281036060840152615b5381866157bd565b9050828103608084015261594081856157bd565b600061ffff808816835280871660208401525084604083015260806060830152615b0a608083018486615794565b6000808335601e19843603018112615bab578283fd5b8301803591506001600160401b03821115615bc4578283fd5b602001915036819003821315614f4d57600080fd5b604051601f8201601f191681016001600160401b0381118282101715615c0157615c01615d65565b604052919050565b60006001600160401b03821115615c2257615c22615d65565b50601f01601f191660200190565b60008219821115615c4357615c43615d39565b500190565b600082615c5757615c57615d4f565b500490565b6000816000190483118215151615615c7657615c76615d39565b500290565b600082821015615c8d57615c8d615d39565b500390565b60005b83811015615cad578181015183820152602001615c95565b8381111561335d5750506000910152565b600081615ccd57615ccd615d39565b506000190190565b600181811c90821680615ce957607f821691505b60208210811415614f6557634e487b7160e01b600052602260045260246000fd5b6000600019821415615d1e57615d1e615d39565b5060010190565b600082615d3457615d34615d4f565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461305557600080fdfe404d724a61636b4c6576696e20406c62656c79616576206661697263727970746f2e6f7267a2646970667358221220c04f5e54109dac1842efaed37985e140dfcbd21012d4f4416c23a77905f2998864736f6c634300080400330000000000000000000000000000000000000000000000000000082f79cd900000000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd67500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000108b2a2c2802909400000000000000000000000000000000000000000000000000000000000000000000035845580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a5845582043727970746f00000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061050c5760003560e01c80638da5cb5b11610297578063c56f0bab11610165578063e6a20ae6116100cc578063ed629c5c11610085578063ed629c5c1461100a578063f060482914611024578063f2fde38b14611039578063f340faed14611059578063f5ecbdbc1461106f578063fc0c546a1461108f57600080fd5b8063e6a20ae614610f69578063e81917b414610f7e578063eab45d9c14610f94578063eaffd49a14610fb4578063eb8d72b714610fd4578063ed2f236914610ff457600080fd5b8063ddca3f431161011e578063ddca3f4314610e39578063df28233114610e4f578063df2a5b3b14610ee0578063e3af6d0a14610f00578063e520fc7e14610f34578063e54f57c014610f5457600080fd5b8063c56f0bab14610d84578063cbed8b9c14610d99578063ce653d5f14610db9578063d1deba1f14610de6578063dbbb415514610df9578063dd62ed3e14610e1957600080fd5b8063a457c2d711610209578063b21d35f2116101c2578063b21d35f214610cee578063b353aaa714610d04578063b4800cdc14610d24578063baf3292d14610d3a578063bcfe394f14610d5a578063c0c6525914610d6f57600080fd5b8063a457c2d714610c38578063a4c51df514610c58578063a6c3d16514610c78578063a9059cbb14610c98578063b0fc721714610cb8578063b0fd1fc214610cce57600080fd5b806395d89b411161025b57806395d89b4114610b67578063962ca49614610b7c5780639920245414610b915780639bdb981214610ba65780639f38369a14610bf85780639ff054df14610c1857600080fd5b80638da5cb5b14610a885780638da7ad2314610aba578063909a2ff614610b1c5780639358928b14610b32578063950c8a7414610b4757600080fd5b806344770515116103df5780637010d7a1116103465780637b0472f0116102ff5780637b0472f0146109f4578063857749b014610a0757806385eb8321146107f45780638979c87c14610a3b57806389fb998f146107f45780638cfd8f5c14610a5057600080fd5b80637010d7a1146108fc57806370a0823114610961578063715018a61461099757806372475f94146109ac5780637533d788146109c157806376203b48146109e157600080fd5b8063543d365211610398578063543d3652146106ab5780635b8c41e6146108505780635bccb4c41461089f57806361a52a36146108b257806366ad5c8a146108c9578063695ef6bf146108e957600080fd5b806344770515146107f45780634512571514610809578063471191a1146107f45780634c42899a1461081e5780634e2207a41461083357806352c7f8dc1461084857600080fd5b80631c24408211610483578063365260b41161043c578063365260b414610737578063395093511461076c5780633ccfd60b1461078c5780633d8b38f61461079457806342d65a8d146107b45780634411ad04146107d457600080fd5b80631c244082146106955780631c6f212e146106ab5780631d3cd2a6146106c057806323b872dd146106e0578063313ce56714610700578063323ac7d81461072257600080fd5b8063095ea7b3116104d5578063095ea7b3146105ce5780630bfae56b146105ee5780630f2e12281461060357806310ddb1371461061857806316f9c8fd1461063857806318160ddd1461068057600080fd5b80621d35671461051157806301ffc9a714610533578063023789321461056857806306fdde031461058c57806307e0db17146105ae575b600080fd5b34801561051d57600080fd5b5061053161052c36600461547d565b6110a2565b005b34801561053f57600080fd5b5061055361054e36600461518d565b6112be565b60405190151581526020015b60405180910390f35b34801561057457600080fd5b5061057e61016d81565b60405190815260200161055f565b34801561059857600080fd5b506105a16112f5565b60405161055f919061589c565b3480156105ba57600080fd5b506105316105c9366004615223565b611387565b3480156105da57600080fd5b506105536105e9366004615148565b6113f4565b3480156105fa57600080fd5b5061057e61140c565b34801561060f57600080fd5b5061057e606381565b34801561062457600080fd5b50610531610633366004615223565b61141d565b34801561064457600080fd5b5061064d611459565b60405161055f91908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561068c57600080fd5b50600c5461057e565b3480156106a157600080fd5b5061057e600f5481565b3480156106b757600080fd5b5061057e600181565b3480156106cc57600080fd5b506105316106db366004614f94565b6114ca565b3480156106ec57600080fd5b506105536106fb366004614fe8565b611507565b34801561070c57600080fd5b5060125b60405160ff909116815260200161055f565b34801561072e57600080fd5b5061057e602381565b34801561074357600080fd5b5061075761075236600461523d565b61152b565b6040805192835260208301919091520161055f565b34801561077857600080fd5b50610553610787366004615148565b611595565b6105316115b7565b3480156107a057600080fd5b506105536107af366004615368565b61178a565b3480156107c057600080fd5b506105316107cf366004615368565b611856565b3480156107e057600080fd5b5061057e6107ef36600461575a565b6118c0565b34801561080057600080fd5b5061057e600081565b34801561081557600080fd5b5061057e611a9f565b34801561082a57600080fd5b50610710600081565b34801561083f57600080fd5b506105a1611aae565b610531611aca565b34801561085c57600080fd5b5061057e61086b3660046154fb565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b6105316108ad3660046156e5565b611cce565b3480156108be57600080fd5b5061057e6201518081565b3480156108d557600080fd5b506105316108e436600461547d565b611f90565b6105316108f73660046150d7565b61201a565b34801561090857600080fd5b50610911612136565b60405161055f919081516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0918201519181019190915260c00190565b34801561096d57600080fd5b5061057e61097c366004614f94565b6001600160a01b03166000908152600a602052604090205490565b3480156109a357600080fd5b506105316121db565b3480156109b857600080fd5b5061057e600f81565b3480156109cd57600080fd5b506105a16109dc366004615223565b6121ef565b6105316109ef366004615028565b612289565b610531610a023660046156e5565b6123ea565b348015610a1357600080fd5b506107107f000000000000000000000000000000000000000000000000000000000000000881565b348015610a4757600080fd5b5061057e612579565b348015610a5c57600080fd5b5061057e610a6b366004615590565b600360209081526000928352604080842090915290825290205481565b348015610a9457600080fd5b506000546001600160a01b03165b6040516001600160a01b03909116815260200161055f565b348015610ac657600080fd5b50610afc610ad5366004614f94565b60146020526000908152604090208054600182015460028301546003909301549192909184565b60408051948552602085019390935291830152606082015260800161055f565b348015610b2857600080fd5b5061057e6103e881565b348015610b3e57600080fd5b5061057e612583565b348015610b5357600080fd5b50600454610aa2906001600160a01b031681565b348015610b7357600080fd5b506105a161258e565b348015610b8857600080fd5b5061057e61259d565b348015610b9d57600080fd5b5061057e6125a7565b348015610bb257600080fd5b50610553610bc13660046154fb565b6007602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205460ff1681565b348015610c0457600080fd5b506105a1610c13366004615223565b6125b1565b348015610c2457600080fd5b50610531610c333660046156b5565b6126c8565b348015610c4457600080fd5b50610553610c53366004615148565b61286e565b348015610c6457600080fd5b50610757610c733660046152b2565b6128e9565b348015610c8457600080fd5b50610531610c93366004615368565b61299c565b348015610ca457600080fd5b50610553610cb3366004615148565b612a2f565b348015610cc457600080fd5b5061057e60125481565b348015610cda57600080fd5b5061057e610ce9366004615729565b612a3d565b348015610cfa57600080fd5b5061057e61138881565b348015610d1057600080fd5b50600154610aa2906001600160a01b031681565b348015610d3057600080fd5b5061057e60105481565b348015610d4657600080fd5b50610531610d55366004614f94565b612acc565b348015610d6657600080fd5b5061057e600a81565b348015610d7b57600080fd5b5061057e612b29565b348015610d9057600080fd5b5061057e600781565b348015610da557600080fd5b50610531610db4366004615649565b612b37565b348015610dc557600080fd5b5061057e610dd4366004614f94565b60156020526000908152604090205481565b610531610df436600461547d565b612bb0565b348015610e0557600080fd5b50610531610e14366004614f94565b612d2a565b348015610e2557600080fd5b5061057e610e34366004614fb0565b612d6a565b348015610e4557600080fd5b5061057e60095481565b348015610e5b57600080fd5b50610ea9610e6a366004614f94565b6013602052600090815260409020805460018201546002830154600384015460048501546005909501546001600160a01b039094169492939192909186565b604080516001600160a01b0390971687526020870195909552938501929092526060840152608083015260a082015260c00161055f565b348015610eec57600080fd5b50610531610efb36600461560e565b612d95565b348015610f0c57600080fd5b5061057e7f0000000000000000000000000000000000000000000000000000000063d68fbf81565b348015610f4057600080fd5b50600854610aa2906001600160a01b031681565b348015610f6057600080fd5b5061057e601481565b348015610f7557600080fd5b50610710600181565b348015610f8a57600080fd5b5061057e6102da81565b348015610fa057600080fd5b50610531610faf366004615173565b612e47565b348015610fc057600080fd5b50610531610fcf3660046153b8565b612e90565b348015610fe057600080fd5b50610531610fef366004615368565b612f6c565b34801561100057600080fd5b5061057e60115481565b34801561101657600080fd5b506006546105539060ff1681565b34801561103057600080fd5b5061057e612fc6565b34801561104557600080fd5b50610531611054366004614f94565b612fdf565b34801561106557600080fd5b5061057e61271081565b34801561107b57600080fd5b506105a161108a3660046155c2565b613058565b34801561109b57600080fd5b5030610aa2565b6001546001600160a01b0316336001600160a01b03161461110a5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff86166000908152600260205260408120805461112890615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461115490615cd5565b80156111a15780601f10611176576101008083540402835291602001916111a1565b820191906000526020600020905b81548152906001019060200180831161118457829003601f168201915b505050505090508051868690501480156111bc575060008151115b80156111e45750805160208201206040516111da90889088906157e9565b6040518091039020145b61123f5760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401611101565b6112b58787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506130f192505050565b50505050505050565b60006001600160e01b03198216631f7ecdf760e01b14806112ef57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600d805461130490615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461133090615cd5565b801561137d5780601f106113525761010080835404028352916020019161137d565b820191906000526020600020905b81548152906001019060200180831161136057829003601f168201915b5050505050905090565b61138f61316a565b6001546040516307e0db1760e01b815261ffff831660048201526001600160a01b03909116906307e0db17906024015b600060405180830381600087803b1580156113d957600080fd5b505af11580156113ed573d6000803e3d6000fd5b5050505050565b6000336114028185856131c4565b5060019392505050565b61141a620151806064615c5c565b81565b61142561316a565b6001546040516310ddb13760e01b815261ffff831660048201526001600160a01b03909116906310ddb137906024016113bf565b6114846040518060800160405280600081526020016000815260200160008152602001600081525090565b5033600090815260146020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b6114d261316a565b6001600160a01b0381166114e557600080fd5b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6000336115158582856132e9565b611520858585613363565b506001949350505050565b6000806000806115748a8a8a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061350e92505050565b91509150600954826115869190615c30565b9a909950975050505050505050565b6000336114028185856115a88383612d6a565b6115b29190615c30565b6131c4565b6009543410156115d95760405162461bcd60e51b8152600401611101906158dd565b6000341180156115eb57506000600954115b15611654576008546009546040516000926001600160a01b031691908381818185875af1925050503d806000811461163f576040519150601f19603f3d011682016040523d82523d6000602084013e611644565b606091505b505090508061165257600080fd5b505b3360009081526014602090815260409182902082516080810184528154815260018201549281019290925260028101549282018390526003015460608201529061169d57600080fd5b60006116bb82604001518360000151846020015185606001516135f3565b6011805491925060006116cd83615cbe565b91905055508160400151601260008282546116e89190615c7b565b92505081905550611708338284604001516117039190615c30565b613651565b600854611723906001600160a01b0316611703606484615c48565b60408083015181519081526020810183905233917f92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc6910160405180910390a25050336000908152601460205260408120818155600181018290556002810182905560030155565b61ffff8316600090815260026020526040812080548291906117ab90615cd5565b80601f01602080910402602001604051908101604052809291908181526020018280546117d790615cd5565b80156118245780601f106117f957610100808354040283529160200191611824565b820191906000526020600020905b81548152906001019060200180831161180757829003601f168201915b50505050509050838360405161183b9291906157e9565b60405180910390208180519060200120149150509392505050565b61185e61316a565b6001546040516342d65a8d60e01b81526001600160a01b03909116906342d65a8d906118929086908690869060040161594c565b600060405180830381600087803b1580156118ac57600080fd5b505af11580156112b5573d6000803e3d6000fd5b6000834211156119d35760006118d68542615c7b565b905060006118e382613712565b90506000739953dc76b5e96dfffa0a926aafab93a7c988ad08636d5433e68a600f5461190f9190615c7b565b6040516001600160e01b031960e084901b16815260048101919091526002602482015260440160206040518083038186803b15801561194d57600080fd5b505af4158015611961573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198591906156cd565b90506000611995866103e8615c30565b905060006119a583898c85612a3d565b905060646119b38582615c7b565b6119bd9083615c5c565b6119c79190615c48565b95505050505050611a96565b6000739953dc76b5e96dfffa0a926aafab93a7c988ad08636d5433e688600f546119fd9190615c7b565b6040516001600160e01b031960e084901b16815260048101919091526002602482015260440160206040518083038186803b158015611a3b57600080fd5b505af4158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7391906156cd565b90506000611a83846103e8615c30565b9050611a9182868984612a3d565b925050505b95945050505050565b6000611aa96137f6565b905090565b604051806060016040528060258152602001615d916025913981565b600954341015611aec5760405162461bcd60e51b8152600401611101906158dd565b600034118015611afe57506000600954115b15611b67576008546009546040516000926001600160a01b031691908381818185875af1925050503d8060008114611b52576040519150601f19603f3d011682016040523d82523d6000602084013e611b57565b606091505b5050905080611b6557600080fd5b505b33600090815260136020908152604091829020825160c08101845281546001600160a01b031681526001820154928101929092526002810154928201929092526003820154606082018190526004830154608083015260059092015460a082015290611bf95760405162461bcd60e51b81526020600482015260016024820152604160f81b6044820152606401611101565b80604001514211611c305760405162461bcd60e51b81526020600482015260016024820152602160f91b6044820152606401611101565b6000611c5382606001518360200151846040015185608001518660a0015161390a565b611c6590670de0b6b3a7640000615c5c565b9050611c713382613651565b600854611c8c906001600160a01b0316611703606484615c48565b611c94613a17565b60405181815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a25050565b600954341015611cf05760405162461bcd60e51b8152600401611101906158dd565b600034118015611d0257506000600954115b15611d6b576008546009546040516000926001600160a01b031691908381818185875af1925050503d8060008114611d56576040519150601f19603f3d011682016040523d82523d6000602084013e611d5b565b606091505b5050905080611d6957600080fd5b505b33600090815260136020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015260658310611dd757600080fd5b6000816060015111611de857600080fd5b80604001514211611df857600080fd5b6000611e1b82606001518360200151846040015185608001518660a0015161390a565b611e2d90670de0b6b3a7640000615c5c565b905060006064611e3d8684615c5c565b611e479190615c48565b90506000611e558284615c7b565b9050611e613382613651565b600854611e7c906001600160a01b0316611703606486615c48565b611e84613a17565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a69060200160405180910390a260008211611ec657600080fd5b6001611ed56201518082615c5c565b611edf9190615c7b565b611eec6201518087615c5c565b11611ef657600080fd5b611f046201518060f4615c5c565b611f0f906001615c30565b611f1c6201518087615c5c565b10611f2657600080fd5b3360009081526014602052604090206002015415611f4357600080fd5b611f4d8286613a6b565b604080518381526020810187905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90910160405180910390a2505050505050565b333014611f9c57600080fd5b6120128686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815289935091508790879081908401838280828437600092019190915250613b0e92505050565b505050505050565b60095434101561203c5760405162461bcd60e51b8152600401611101906158dd565b60003411801561204e57506000600954115b156120b7576008546009546040516000926001600160a01b031691908381818185875af1925050503d80600081146120a2576040519150601f19603f3d011682016040523d82523d6000602084013e6120a7565b606091505b50509050806120b557600080fd5b505b6000600954346120c79190615c7b565b90506112b5868686866120dd6020880188614f94565b6120ed6040890160208a01614f94565b6120fa60408a018a615b95565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b9250613b6f915050565b6121786040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b5033600090815260136020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015290565b6121e361316a565b6121ed6000613c19565b565b6002602052600090815260409020805461220890615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461223490615cd5565b80156122815780601f1061225657610100808354040283529160200191612281565b820191906000526020600020905b81548152906001019060200180831161226457829003601f168201915b505050505081565b6009543410156122ab5760405162461bcd60e51b8152600401611101906158dd565b6000341180156122bd57506000600954115b15612326576008546009546040516000926001600160a01b031691908381818185875af1925050503d8060008114612311576040519150601f19603f3d011682016040523d82523d6000602084013e612316565b606091505b505090508061232457600080fd5b505b6000600954346123369190615c7b565b90506123de8989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b925061238591505060208a018a614f94565b61239560408b0160208c01614f94565b6123a260408c018c615b95565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d9250613c69915050565b50505050505050505050565b60095434101561240c5760405162461bcd60e51b8152600401611101906158dd565b60003411801561241e57506000600954115b15612487576008546009546040516000926001600160a01b031691908381818185875af1925050503d8060008114612472576040519150601f19603f3d011682016040523d82523d6000602084013e612477565b606091505b505090508061248557600080fd5b505b336000908152600a60205260409020548211156124a357600080fd5b600082116124b057600080fd5b60016124bf6201518082615c5c565b6124c99190615c7b565b6124d66201518083615c5c565b116124e057600080fd5b6124ee6201518060f4615c5c565b6124f9906001615c30565b6125066201518083615c5c565b1061251057600080fd5b336000908152601460205260409020600201541561252d57600080fd5b6125373383613d27565b6125418282613a6b565b604080518381526020810183905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909101611cc2565b6000611aa9613e53565b6000611aa9600c5490565b6060600e805461130490615cd5565b6000611aa9613e98565b6000611aa9613f05565b61ffff81166000908152600260205260408120805460609291906125d490615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461260090615cd5565b801561264d5780601f106126225761010080835404028352916020019161264d565b820191906000526020600020905b81548152906001019060200180831161263057829003601f168201915b505050505090508051600014156126a65760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401611101565b6126c16000601483516126b99190615c7b565b839190613ff4565b9392505050565b60006126d76201518083615c5c565b905060016126e86201518082615c5c565b6126f29190615c7b565b81116126fd57600080fd5b6127056137f6565b612710906001615c30565b811061271b57600080fd5b336000908152601360205260409020600301541561273857600080fd5b6040805160c08101825233815260208101849052600091810161275b8442615c30565b8152602001600f548152602001612770613f05565b815260200161277d613e53565b9052336000908152601360209081526040808320845181546001600160a01b0319166001600160a01b039091161781559184015160018301558301516002820155606083015160038201556080830151600482015560a083015160059091015560108054929350906127ee83615d0a565b9091555050600f805433917fc05062aaca3ffe3bd48e1cd6edc912dff77e39ba1a14999b5e00ec68614b311c918691600061282883615d0a565b919050556128346125a7565b60a08681015160408089015181519687526020870195909552858101939093526060850152608084019290925251918290030190a2505050565b6000338161287c8286612d6a565b9050838110156128dc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401611101565b61152082868684036131c4565b6000806000806129788d8d8d8d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061410192505050565b915091506009548261298a9190615c30565b9d909c509a5050505050505050505050565b6129a461316a565b8181306040516020016129b9939291906157f9565b60408051601f1981840301815291815261ffff851660009081526002602090815291902082516129ee93919290910190614df0565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce838383604051612a229392919061594c565b60405180910390a1505050565b600033611402818585613363565b600080612a54612a4c876141b4565b600f0b6141d2565b90506000612a90612a64856141b4565b612a87612a70886141b4565b612a87612a7c8b6141b4565b600f88900b906142b6565b600f0b906142b6565b9050612ab6612aae612aa36103e86141b4565b600f84900b906142ed565b600f0b614353565b6001600160401b0316925050505b949350505050565b612ad461316a565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b906020015b60405180910390a150565b61141a6201518060f4615c5c565b612b3f61316a565b6001546040516332fb62e760e21b81526001600160a01b039091169063cbed8b9c90612b779088908890889088908890600401615b67565b600060405180830381600087803b158015612b9157600080fd5b505af1158015612ba5573d6000803e3d6000fd5b505050505050505050565b61ffff86166000908152600560205260408082209051612bd390889088906157e9565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080612c0457600080fd5b808383604051612c159291906157e9565b604051809103902014612c2757600080fd5b61ffff87166000908152600560205260408082209051612c4a90899089906157e9565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252612ce2918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a935091508890889081908401838280828437600092019190915250613b0e92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051612d1995949392919061596a565b60405180910390a150505050505050565b612d3261316a565b6001546001600160a01b031615612d4857600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b039182166000908152600b6020908152604080832093909416825291909152205490565b612d9d61316a565b60008111612de55760405162461bcd60e51b81526020600482015260156024820152744c7a4170703a20696e76616c6964206d696e47617360581b6044820152606401611101565b61ffff83811660008181526003602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001612a22565b612e4f61316a565b6006805460ff19168215159081179091556040519081527f1584ad594a70cbe1e6515592e1272a987d922b097ead875069cebe8b40c004a490602001612b1e565b333014612e9c57600080fd5b612ea730868661436f565b9350846001600160a01b03168a61ffff167fbf551ec93859b170f9b2141bd9298bf3f64322c6f7beb2543a0cb669834118bf86604051612ee991815260200190565b60405180910390a3604051633fe79aed60e11b81526001600160a01b03861690637fcf35da908390612f2d908e908e908e908e908e908d908d908d906004016159a5565b600060405180830381600088803b158015612f4757600080fd5b5087f1158015612f5b573d6000803e3d6000fd5b505050505050505050505050505050565b612f7461316a565b61ffff83166000908152600260205260409020612f92908383614e70565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab838383604051612a229392919061594c565b6001612fd56201518082615c5c565b61141a9190615c7b565b612fe761316a565b6001600160a01b03811661304c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611101565b61305581613c19565b50565b600154604051633d7b2f6f60e21b815261ffff808716600483015285166024820152306044820152606481018390526060916001600160a01b03169063f5ecbdbc9060840160006040518083038186803b1580156130b557600080fd5b505afa1580156130c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a9691908101906151b5565b6000806131545a60966366ad5c8a60e01b898989896040516024016131199493929190615acc565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152309291906143c1565b9150915081612012576120128686868685614459565b6000546001600160a01b031633146121ed5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611101565b6001600160a01b0383166132265760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401611101565b6001600160a01b0382166132875760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401611101565b6001600160a01b038381166000818152600b602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006132f58484612d6a565b9050600019811461335d57818110156133505760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401611101565b61335d84848484036131c4565b50505050565b6001600160a01b0383166133c75760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401611101565b6001600160a01b0382166134295760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401611101565b6001600160a01b0383166000908152600a6020526040902054818110156134a15760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401611101565b6001600160a01b038085166000818152600a602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906135019086815260200190565b60405180910390a361335d565b600080600061355c87613520886144f6565b6040805160006020820152602181019390935260c09190911b6001600160c01b0319166041830152805160298184030181526049909201905290565b60015460405163040a7bb160e41b81529192506001600160a01b0316906340a7bb1090613595908b90309086908b908b906004016158f8565b604080518083038186803b1580156135ac57600080fd5b505afa1580156135c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e49190615706565b92509250509550959350505050565b60008242111561364657600061016d61360c8685615c5c565b61361990620f4240615c5c565b6136239190615c48565b90506305f5e1006136348288615c5c565b61363e9190615c48565b915050612ac4565b506000949350505050565b6001600160a01b0382166136a75760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401611101565b80600c60008282546136b99190615c30565b90915550506001600160a01b0382166000818152600a60209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6000806137226201518084615c48565b905061373060016007615c7b565b8111156137405750606392915050565b600060016007613751846003615c30565b6001901b61375f9190615c48565b6137699190615c7b565b604051637ae2b5c760e01b81526004810182905260636024820152909150739953dc76b5e96dfffa0a926aafab93a7c988ad0890637ae2b5c79060440160206040518083038186803b1580156137be57600080fd5b505af41580156137d2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac491906156cd565b6000611388600f5411156138fc576000613824612aae613816600f6141b4565b612a87612a4c600f546141b4565b6001600160401b03169050600061383e6201518083615c5c565b61384c620151806064615c5c565b6138569190615c30565b9050739953dc76b5e96dfffa0a926aafab93a7c988ad08637ae2b5c7826138816201518060f4615c5c565b6040516001600160e01b031960e085901b1681526004810192909252602482015260440160206040518083038186803b1580156138bd57600080fd5b505af41580156138d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f591906156cd565b9250505090565b611aa9620151806064615c5c565b6000806139178542615c7b565b9050600061392482613712565b90506000739953dc76b5e96dfffa0a926aafab93a7c988ad08636d5433e68a600f546139509190615c7b565b6040516001600160e01b031960e084901b16815260048101919091526002602482015260440160206040518083038186803b15801561398e57600080fd5b505af41580156139a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139c691906156cd565b905060006139d6866103e8615c30565b905060006139e683898c85612a3d565b905060646139f48582615c7b565b6139fe9083615c5c565b613a089190615c48565b9b9a5050505050505050505050565b33600090815260136020526040812080546001600160a01b0319168155600181018290556002810182905560038101829055600481018290556005018190556010805491613a6483615cbe565b9190505550565b60405180608001604052808281526020016201518083613a8b9190615c5c565b613a959042615c30565b8152602001838152602001613aa8613e98565b90523360009081526014602090815260408083208451815591840151600183015583015160028201556060909201516003909201919091556011805491613aee83615d0a565b91905055508160126000828254613b059190615c30565b90915550505050565b6000613b1a8282614539565b905060ff8116613b3557613b3085858585614595565b6113ed565b60ff811660011415613b4d57613b3085858585614625565b60405162461bcd60e51b81526020600482015260006024820152604401611101565b6000613b7d88828581614833565b613b868661485b565b509050613b958989898461489b565b905060008111613ba457600080fd5b6000613bb388613520846144f6565b9050613bc38982888888886148cd565b878a6001600160a01b03168a61ffff167fd81fc9b8523134ed613870ed029d6170cbb73aa6a6bc311b9a642689fb9df59a85604051613c0491815260200190565b60405180910390a45098975050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000613c818a6001856001600160401b038a16614833565b613c8a8861485b565b509050613c998b8b8b8461489b565b905060008111613ca857600080fd5b6000613cbf338b613cb8856144f6565b8b8b614a4c565b9050613ccf8b82888888886148cd565b898c6001600160a01b03168c61ffff167fd81fc9b8523134ed613870ed029d6170cbb73aa6a6bc311b9a642689fb9df59a85604051613d1091815260200190565b60405180910390a4509a9950505050505050505050565b6001600160a01b038216613d875760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401611101565b6001600160a01b0382166000908152600a602052604090205481811015613dfb5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401611101565b6001600160a01b0383166000818152600a602090815260408083208686039055600c80548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91016132dc565b600080612710600f54600a613e689190615c5c565b613e729190615c48565b90506103e8811115613e8657600091505090565b613e92816103e8615c7b565b91505090565b600080613ea9601462015180615c5c565b613ed37f0000000000000000000000000000000000000000000000000000000063d68fbf42615c7b565b613edd9190615c48565b905080613eec60006023615c7b565b1015613efa57600091505090565b613e92816023615c7b565b60008062015180613f367f0000000000000000000000000000000000000000000000000000000063d68fbf42615c7b565b613f409190615c48565b90506102da811015613fe857739953dc76b5e96dfffa0a926aafab93a7c988ad08636d5433e6613f72836102da615c7b565b6040516001600160e01b031960e084901b16815260048101919091526001602482015260440160206040518083038186803b158015613fb057600080fd5b505af4158015613fc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e9291906156cd565b600191505090565b5090565b60608161400281601f615c30565b10156140415760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401611101565b61404b8284615c30565b8451101561408f5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401611101565b6060821580156140ae57604051915060008252602082016040526140f8565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156140e75780518352602092830192016140cf565b5050858452601f01601f1916604052505b50949350505050565b600080600061411b338a6141148b6144f6565b8a8a614a4c565b60015460405163040a7bb160e41b81529192506001600160a01b0316906340a7bb1090614154908d90309086908b908b906004016158f8565b604080518083038186803b15801561416b57600080fd5b505afa15801561417f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141a39190615706565b925092505097509795505050505050565b6000677fffffffffffffff8211156141cb57600080fd5b5060401b90565b60008082600f0b136141e357600080fd5b6000600f83900b680100000000000000008112614202576040918201911d5b6401000000008112614216576020918201911d5b620100008112614228576010918201911d5b6101008112614239576008918201911d5b60108112614249576004918201911d5b60048112614259576002918201911d5b60028112614268576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156142ab5790800260ff81901c8281029390930192607f011c9060011d614285565b509095945050505050565b6000600f83810b9083900b0260401d60016001607f1b031981128015906142e4575060016001607f1b038113155b6126c157600080fd5b600081600f0b6000141561430057600080fd5b600082600f0b604085600f0b901b8161432957634e487b7160e01b600052601260045260246000fd5b05905060016001607f1b031981128015906142e4575060016001607f1b038113156126c157600080fd5b60008082600f0b121561436557600080fd5b50600f0b60401d90565b600033306001600160a01b0386161480159061439d5750806001600160a01b0316856001600160a01b031614155b156143ad576143ad8582856132e9565b6143b8858585613363565b50909392505050565b6000606060008060008661ffff166001600160401b038111156143f457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561441e576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115614440578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff1681526020019081526020016000208560405161448a919061581f565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c906144e79087908790879087908790615b15565b60405180910390a15050505050565b6000806145237f00000000000000000000000000000000000000000000000000000002540be40084615c48565b90506001600160401b038111156112ef57600080fd5b6000614546826001615c30565b8351101561458c5760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b6044820152606401611101565b50016001015190565b6000806145a183614a8d565b90925090506001600160a01b0382166145ba5761dead91505b60006145c582614ad4565b90506145d2878483614b09565b9050826001600160a01b03168761ffff167fbf551ec93859b170f9b2141bd9298bf3f64322c6f7beb2543a0cb669834118bf8360405161461491815260200190565b60405180910390a350505050505050565b600080600080600061463686614b1c565b945094509450945094506000600760008b61ffff1661ffff1681526020019081526020016000208960405161466b919061581f565b90815260408051602092819003830190206001600160401b038b166000908152925281205460ff16915061469e85614ad4565b90508161470c576146b08b3083614b09565b61ffff8c166000908152600760205260409081902090519192506001916146d8908d9061581f565b90815260408051602092819003830190206001600160401b038d16600090815292529020805460ff19169115159190911790555b6001600160a01b0386163b614763576040516001600160a01b03871681527f9aedf5fdba8716db3b6705ca00150643309995d4f818a249ed6dde6677e7792d9060200160405180910390a15050505050505061335d565b8a8a8a8a8a8a868a60008a614781578b6001600160401b0316614783565b5a5b90506000806147b55a609663eaffd49a60e01b8e8e8e8d8d8d8d8d604051602401613119989796959493929190615a58565b91509150811561480e578751602089012060405161ffff8d16907fb8890edbfc1c74692f527444645f95489c3703cc2df42e4a366f5d06fa6cd88490614800908e908e9086906158af565b60405180910390a25061481b565b61481b8b8b8b8b85614459565b50505050505050505050505050505050505050505050565b60065460ff161561484f5761484a84848484614b95565b61335d565b81511561335d57600080fd5b6000806148887f00000000000000000000000000000000000000000000000000000002540be40084615d25565b90506148948184615c7b565b9150915091565b6000336001600160a01b03861681146148b9576148b98682856132e9565b6148c38684613d27565b5090949350505050565b61ffff8616600090815260026020526040812080546148eb90615cd5565b80601f016020809104026020016040519081016040528092919081815260200182805461491790615cd5565b80156149645780601f1061493957610100808354040283529160200191614964565b820191906000526020600020905b81548152906001019060200180831161494757829003601f168201915b505050505090508051600014156149d65760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401611101565b60015460405162c5803160e81b81526001600160a01b039091169063c5803100908490614a11908b9086908c908c908c908c906004016159f1565b6000604051808303818588803b158015614a2a57600080fd5b505af1158015614a3e573d6000803e3d6000fd5b505050505050505050505050565b6060600185856001600160a01b0389168587604051602001614a739695949392919061583b565b604051602081830303815290604052905095945050505050565b60008080614a9b8482614539565b60ff16148015614aac575082516029145b614ab557600080fd5b614ac083600d614c74565b9150614acd836021614cd9565b9050915091565b60006112ef7f00000000000000000000000000000000000000000000000000000002540be4006001600160401b038416615c5c565b6000614b158383613651565b5092915050565b600080806060816001614b2f8783614539565b60ff1614614b3c57600080fd5b614b4786600d614c74565b9350614b54866021614cd9565b9250614b61866029614d36565b9450614b6e866049614cd9565b9050614b8a6051808851614b829190615c7b565b889190613ff4565b915091939590929450565b6000614ba083614d94565b61ffff808716600090815260036020908152604080832093891683529290529081205491925090614bd2908490615c30565b905060008111614c245760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401611101565b808210156120125760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401611101565b6000614c81826014615c30565b83511015614cc95760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606401611101565b500160200151600160601b900490565b6000614ce6826008615c30565b83511015614d2d5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b6044820152606401611101565b50016008015190565b6000614d43826020615c30565b83511015614d8b5760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b6044820152606401611101565b50016020015190565b6000602282511015614de85760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401611101565b506022015190565b828054614dfc90615cd5565b90600052602060002090601f016020900481019282614e1e5760008555614e64565b82601f10614e3757805160ff1916838001178555614e64565b82800160010185558215614e64579182015b82811115614e64578251825591602001919060010190614e49565b50613ff0929150614ee4565b828054614e7c90615cd5565b90600052602060002090601f016020900481019282614e9e5760008555614e64565b82601f10614eb75782800160ff19823516178555614e64565b82800160010185558215614e64579182015b82811115614e64578235825591602001919060010190614ec9565b5b80821115613ff05760008155600101614ee5565b80358015158114614f0957600080fd5b919050565b60008083601f840112614f1f578182fd5b5081356001600160401b03811115614f35578182fd5b602083019150836020828501011115614f4d57600080fd5b9250929050565b600060608284031215614f65578081fd5b50919050565b803561ffff81168114614f0957600080fd5b80356001600160401b0381168114614f0957600080fd5b600060208284031215614fa5578081fd5b81356126c181615d7b565b60008060408385031215614fc2578081fd5b8235614fcd81615d7b565b91506020830135614fdd81615d7b565b809150509250929050565b600080600060608486031215614ffc578081fd5b833561500781615d7b565b9250602084013561501781615d7b565b929592945050506040919091013590565b60008060008060008060008060e0898b031215615043578384fd5b883561504e81615d7b565b975061505c60208a01614f6b565b9650604089013595506060890135945060808901356001600160401b0380821115615085578586fd5b6150918c838d01614f0e565b90965094508491506150a560a08c01614f7d565b935060c08b01359150808211156150ba578283fd5b506150c78b828c01614f54565b9150509295985092959890939650565b600080600080600060a086880312156150ee578081fd5b85356150f981615d7b565b945061510760208701614f6b565b9350604086013592506060860135915060808601356001600160401b0381111561512f578182fd5b61513b88828901614f54565b9150509295509295909350565b6000806040838503121561515a578182fd5b823561516581615d7b565b946020939093013593505050565b600060208284031215615184578081fd5b6126c182614ef9565b60006020828403121561519e578081fd5b81356001600160e01b0319811681146126c1578182fd5b6000602082840312156151c6578081fd5b81516001600160401b038111156151db578182fd5b8201601f810184136151eb578182fd5b80516151fe6151f982615c09565b615bd9565b818152856020838501011115615212578384fd5b611a96826020830160208601615c92565b600060208284031215615234578081fd5b6126c182614f6b565b60008060008060008060a08789031215615255578384fd5b61525e87614f6b565b9550602087013594506040870135935061527a60608801614ef9565b925060808701356001600160401b03811115615294578283fd5b6152a089828a01614f0e565b979a9699509497509295939492505050565b600080600080600080600080600060e08a8c0312156152cf578283fd5b6152d88a614f6b565b985060208a0135975060408a0135965060608a01356001600160401b0380821115615301578485fd5b61530d8d838e01614f0e565b909850965086915061532160808d01614f7d565b955061532f60a08d01614ef9565b945060c08c0135915080821115615344578283fd5b506153518c828d01614f0e565b915080935050809150509295985092959850929598565b60008060006040848603121561537c578081fd5b61538584614f6b565b925060208401356001600160401b0381111561539f578182fd5b6153ab86828701614f0e565b9497909650939450505050565b6000806000806000806000806000806101008b8d0312156153d7578384fd5b6153e08b614f6b565b995060208b01356001600160401b03808211156153fb578586fd5b6154078e838f01614f0e565b909b50995089915061541b60408e01614f7d565b985060608d0135975060808d0135915061543482615d7b565b90955060a08c0135945060c08c01359080821115615450578283fd5b5061545d8d828e01614f0e565b9150809450508092505060e08b013590509295989b9194979a5092959850565b60008060008060008060808789031215615495578384fd5b61549e87614f6b565b955060208701356001600160401b03808211156154b9578586fd5b6154c58a838b01614f0e565b90975095508591506154d960408a01614f7d565b945060608901359150808211156154ee578384fd5b506152a089828a01614f0e565b60008060006060848603121561550f578081fd5b61551884614f6b565b925060208401356001600160401b03811115615532578182fd5b8401601f81018613615542578182fd5b80356155506151f982615c09565b818152876020838501011115615564578384fd5b816020840160208301379081016020018390529250615587905060408501614f7d565b90509250925092565b600080604083850312156155a2578182fd5b6155ab83614f6b565b91506155b960208401614f6b565b90509250929050565b600080600080608085870312156155d7578182fd5b6155e085614f6b565b93506155ee60208601614f6b565b925060408501356155fe81615d7b565b9396929550929360600135925050565b600080600060608486031215615622578081fd5b61562b84614f6b565b925061563960208501614f6b565b9150604084013590509250925092565b600080600080600060808688031215615660578283fd5b61566986614f6b565b945061567760208701614f6b565b93506040860135925060608601356001600160401b03811115615698578182fd5b6156a488828901614f0e565b969995985093965092949392505050565b6000602082840312156156c6578081fd5b5035919050565b6000602082840312156156de578081fd5b5051919050565b600080604083850312156156f7578182fd5b50508035926020909101359150565b60008060408385031215615718578182fd5b505080516020909101519092909150565b6000806000806080858703121561573e578182fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a08688031215615771578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600081518084526157d5816020860160208601615c92565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251615831818460208701615c92565b9190910192915050565b60ff60f81b8760f81b16815285600182015260006001600160401b0360c01b808760c01b166021840152856029840152808560c01b16604984015250825161588a816051850160208701615c92565b91909101605101979650505050505050565b6020815260006126c160208301846157bd565b6060815260006158c260608301866157bd565b6001600160401b039490941660208301525060400152919050565b6020808252600190820152602360f91b604082015260600190565b61ffff861681526001600160a01b038516602082015260a060408201819052600090615926908301866157bd565b8415156060840152828103608084015261594081856157bd565b98975050505050505050565b61ffff84168152604060208201526000611a96604083018486615794565b61ffff86168152608060208201526000615988608083018688615794565b6001600160401b0394909416604083015250606001529392505050565b61ffff8916815260c0602082015260006159c360c08301898b615794565b6001600160401b038816604084015286606084015285608084015282810360a0840152613a08818587615794565b61ffff8716815260c060208201526000615a0e60c08301886157bd565b8281036040840152615a2081886157bd565b6001600160a01b0387811660608601528616608085015283810360a08501529050615a4b81856157bd565b9998505050505050505050565b600061010061ffff8b168352806020840152615a768184018b6157bd565b6001600160401b038a166040850152606084018990526001600160a01b038816608085015260a0840187905283810360c08501529050615ab681866157bd565b9150508260e08301529998505050505050505050565b61ffff85168152608060208201526000615ae960808301866157bd565b6001600160401b03851660408401528281036060840152615b0a81856157bd565b979650505050505050565b61ffff8616815260a060208201526000615b3260a08301876157bd565b6001600160401b03861660408401528281036060840152615b5381866157bd565b9050828103608084015261594081856157bd565b600061ffff808816835280871660208401525084604083015260806060830152615b0a608083018486615794565b6000808335601e19843603018112615bab578283fd5b8301803591506001600160401b03821115615bc4578283fd5b602001915036819003821315614f4d57600080fd5b604051601f8201601f191681016001600160401b0381118282101715615c0157615c01615d65565b604052919050565b60006001600160401b03821115615c2257615c22615d65565b50601f01601f191660200190565b60008219821115615c4357615c43615d39565b500190565b600082615c5757615c57615d4f565b500490565b6000816000190483118215151615615c7657615c76615d39565b500290565b600082821015615c8d57615c8d615d39565b500390565b60005b83811015615cad578181015183820152602001615c95565b8381111561335d5750506000910152565b600081615ccd57615ccd615d39565b506000190190565b600181811c90821680615ce957607f821691505b60208210811415614f6557634e487b7160e01b600052602260045260246000fd5b6000600019821415615d1e57615d1e615d39565b5060010190565b600082615d3457615d34615d4f565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461305557600080fdfe404d724a61636b4c6576696e20406c62656c79616576206661697263727970746f2e6f7267a2646970667358221220c04f5e54109dac1842efaed37985e140dfcbd21012d4f4416c23a77905f2998864736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000082f79cd900000000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd67500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000108b2a2c2802909400000000000000000000000000000000000000000000000000000000000000000000035845580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a5845582043727970746f00000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _fee (uint256): 9000000000000
Arg [1] : _endpoint (address): 0x66A71Dcef29A0fFBDBE3c6a460a3B5BC225Cd675
Arg [2] : _symbol (string): XEX
Arg [3] : _name (string): XEX Crypto
Arg [4] : _initialMint (uint256): 20000000000000000000000000
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000082f79cd9000
Arg [1] : 00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [4] : 000000000000000000000000000000000000000000108b2a2c28029094000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [6] : 5845580000000000000000000000000000000000000000000000000000000000
Arg [7] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [8] : 5845582043727970746f00000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.