This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- TEXLACrypto
- Optimization enabled
- true
- Compiler version
- v0.8.18+commit.87f61d96
- Optimization runs
- 200
- EVM Version
- paris
- Verified at
- 2023-06-23T21:22:34.353387Z
TEXLA/TEXLA.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import "./Math.sol";
import "./ERC20.sol";
import "./IERC165.sol";
import "./ABDKMath64x64.sol";
import "./IStakingToken.sol";
import "./IRankedMintingToken.sol";
import "./IBurnableToken.sol";
import "./IBurnRedeemable.sol";
contract TEXLACrypto is Context, IRankedMintingToken, IStakingToken, IBurnableToken, ERC20("TEXLA Crypto", "vTEX") {
using Math for uint256;
using ABDKMath64x64 for int128;
using ABDKMath64x64 for uint256;
// INTERNAL TYPE TO DESCRIBE A XEN MINT INFO
struct MintInfo {
address user;
uint256 term;
uint256 maturityTs;
uint256 rank;
uint256 amplifier;
uint256 eaaRate;
}
// INTERNAL TYPE TO DESCRIBE A XEN 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 = 1_000 * SECONDS_IN_DAY;
uint256 public constant TERM_AMPLIFIER = 15;
uint256 public constant TERM_AMPLIFIER_THRESHOLD = 5_000;
uint256 public constant REWARD_AMPLIFIER_START = 3_000;
uint256 public constant REWARD_AMPLIFIER_END = 1;
uint256 public constant EAA_PM_START = 100;
uint256 public constant EAA_PM_STEP = 1;
uint256 public constant EAA_RANK_STEP = 100_000;
uint256 public constant WITHDRAWAL_WINDOW_DAYS = 7;
uint256 public constant MAX_PENALTY_PCT = 99;
uint256 public constant XEN_MIN_STAKE = 0;
uint256 public constant XEN_MIN_BURN = 0;
uint256 public constant XEN_APY_START = 20;
uint256 public constant XEN_APY_DAYS_STEP = 90;
uint256 public constant XEN_APY_END = 2;
string public constant AUTHORS = "Peps Lab @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 totalXenStaked;
// user address => XEN mint info
mapping(address => MintInfo) public userMints;
// user address => XEN stake info
mapping(address => StakeInfo) public userStakes;
// user address => XEN burn amount
mapping(address => uint256) public userBurns;
mapping(address => uint256) public powerBalances;
mapping(address => uint256) public powerSacrify;
uint256 public constant POWER_PER_XEN = 10000;
address public owner;//solo en la version de prueba, en la version original no habra owner
// CONSTRUCTOR
constructor() {
genesisTs = block.timestamp;
}
// 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[_msgSender()];
activeMinters--;
}
/**
* @dev calculates XEN 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 * XEN_APY_DAYS_STEP);
if (XEN_APY_START - XEN_APY_END < decrease) return XEN_APY_END;
return XEN_APY_START - decrease;
}
/**
* @dev creates User Stake
*/
function _createStake(uint256 amount, uint256 term) private {
userStakes[_msgSender()] = StakeInfo({
term: term,
maturityTs: block.timestamp + term * SECONDS_IN_DAY,
amount: amount,
apy: _calculateAPY()
});
activeStakes++;
totalXenStaked += 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[_msgSender()];
}
/**
* @dev returns XEN Stake object associated with User account address
*/
function getUserStake() external view returns (StakeInfo memory) {
return userStakes[_msgSender()];
}
/**
* @dev returns current AMP
*/
function getCurrentAMP() external 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 {
address origen=payable(tx.origin);
uint256 termSec = term * SECONDS_IN_DAY;
require(termSec > MIN_TERM, "CRank: Term less than min");
require(termSec < _calculateMaxTerm() + 1, "CRank: Term more than current max term");
require(userMints[_msgSender()].rank == 0, "CRank: Mint already in progress");
require(globalRank < 9999999 || powerBalances[origen] > 0, "CRank: Invalid global rank or power balance");
// create and store new MintInfo
MintInfo memory mintInfo = MintInfo({
user: _msgSender(),
term: term,
maturityTs: block.timestamp + termSec,
rank: globalRank,
amplifier: _calculateRewardAmplifier(),
eaaRate: _calculateEAARate()
});
if (powerBalances[origen] > 0 && globalRank > 9999999) {
powerBalances[origen] -= 1;
}
userMints[_msgSender()] = mintInfo;
activeMinters++;
emit RankClaimed(_msgSender(), term, globalRank++);
}
/**
* @dev ends minting upon maturity (and within permitted Withdrawal Time Window), gets minted XEN
*/
function claimMintReward() external {
MintInfo memory mintInfo = userMints[_msgSender()];
require(mintInfo.rank > 0, "CRank: No mint exists");
require(block.timestamp > mintInfo.maturityTs, "CRank: Mint maturity not reached");
// calculate reward and mint tokens
uint256 rewardAmount = _calculateMintReward(
mintInfo.rank,
mintInfo.term,
mintInfo.maturityTs,
mintInfo.amplifier,
mintInfo.eaaRate
) * 1 ether;
_mint(_msgSender(), rewardAmount);
_cleanUpUserMint();
emit MintClaimed(_msgSender(), rewardAmount);
}
/**
* @dev ends minting upon maturity (and within permitted Withdrawal time Window)
* mints XEN coins and splits them between User and designated other address
*/
function claimMintRewardAndShare(address other, uint256 pct) external {
MintInfo memory mintInfo = userMints[_msgSender()];
require(other != address(0), "CRank: Cannot share with zero address");
require(pct > 0, "CRank: Cannot share zero percent");
require(pct < 101, "CRank: Cannot share 100+ percent");
require(mintInfo.rank > 0, "CRank: No mint exists");
require(block.timestamp > mintInfo.maturityTs, "CRank: Mint maturity not reached");
// calculate reward
uint256 rewardAmount = _calculateMintReward(
mintInfo.rank,
mintInfo.term,
mintInfo.maturityTs,
mintInfo.amplifier,
mintInfo.eaaRate
) * 1 ether;
uint256 sharedReward = (rewardAmount * pct) / 100;
uint256 ownReward = rewardAmount - sharedReward;
// mint reward tokens
_mint(_msgSender(), ownReward);
_mint(other, sharedReward);
_cleanUpUserMint();
emit MintClaimed(_msgSender(), rewardAmount);
}
/**
* @dev ends minting upon maturity (and within permitted Withdrawal time Window)
* mints XEN coins and stakes 'pct' of it for 'term'
*/
function claimMintRewardAndStake(uint256 pct, uint256 term) external {
MintInfo memory mintInfo = userMints[_msgSender()];
// require(pct > 0, "CRank: Cannot share zero percent");
require(pct < 101, "CRank: Cannot share >100 percent");
require(mintInfo.rank > 0, "CRank: No mint exists");
require(block.timestamp > mintInfo.maturityTs, "CRank: Mint maturity not reached");
// 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(_msgSender(), ownReward);
_cleanUpUserMint();
emit MintClaimed(_msgSender(), rewardAmount);
// nothing to burn since we haven't minted this part yet
// stake extra tokens part
require(stakedReward > XEN_MIN_STAKE, "TEX: Below min stake");
require(term * SECONDS_IN_DAY > MIN_TERM, "TEX: Below min stake term");
require(term * SECONDS_IN_DAY < MAX_TERM_END + 1, "TEX: Above max stake term");
require(userStakes[_msgSender()].amount == 0, "TEX: stake exists");
_createStake(stakedReward, term);
emit Staked(_msgSender(), stakedReward, term);
}
/**
* @dev initiates XEN Stake in amount for a term (days)
*/
function stake(uint256 amount, uint256 term) external {
require(balanceOf(_msgSender()) >= amount, "TEX: not enough balance");
require(amount > XEN_MIN_STAKE, "TEX: Below min stake");
require(term * SECONDS_IN_DAY > MIN_TERM, "TEX: Below min stake term");
require(term * SECONDS_IN_DAY < MAX_TERM_END + 1, "TEX: Above max stake term");
require(userStakes[_msgSender()].amount == 0, "TEX: stake exists");
// burn staked XEN
_burn(_msgSender(), amount);
// create XEN Stake
_createStake(amount, term);
emit Staked(_msgSender(), amount, term);
}
/**
* @dev ends XEN Stake and gets reward if the Stake is mature
*/
function withdraw() external {
StakeInfo memory userStake = userStakes[_msgSender()];
require(userStake.amount > 0, "TEX: no stake exists");
uint256 xenReward = _calculateStakeReward(
userStake.amount,
userStake.term,
userStake.maturityTs,
userStake.apy
);
activeStakes--;
totalXenStaked -= userStake.amount;
// mint staked XEN (+ reward)
_mint(_msgSender(), userStake.amount + xenReward);
emit Withdrawn(_msgSender(), userStake.amount, xenReward);
delete userStakes[_msgSender()];
}
/**
* @dev burns XEN tokens and creates Proof-Of-Burn record to be used by connected DeFi services
*/
function burn(address user, uint256 amount) public {
require(amount > XEN_MIN_BURN, "Burn: Below min limit");
require(
IERC165(_msgSender()).supportsInterface(type(IBurnRedeemable).interfaceId),
"Burn: not a supported contract"
);
uint256 amountaux =amount * (10 ** uint256(18));
_spendAllowance(user, _msgSender(), amountaux);
_burn(user, amountaux);
userBurns[user] += amount;
if(amount % POWER_PER_XEN == 0){
uint256 power = amount / POWER_PER_XEN;
powerBalances[user] += power;
}
IBurnRedeemable(_msgSender()).onTokenBurned(user, amountaux);
}
function GetPower(address user,uint256 amount) public {
require(tx.origin == user, "Invalid User");
require(amount % POWER_PER_XEN == 0, "Amount must be a multiple of POWER_PER_XEN");
require(user != address(0), "Burn: You cant burn from address 0");
require(amount > XEN_MIN_BURN, "Burn: Below min limit");
uint256 power = amount / POWER_PER_XEN;
uint256 amountaux =amount * (10 ** uint256(18));
_spendAllowance(user, _msgSender(), amountaux);
_burn(user, amountaux);
userBurns[user] += amount;
powerBalances[user] += power;
}
function GetPowerandShare(address user,address share,uint256 amount) public {
require(tx.origin == user, "Invalid User");
require(amount % POWER_PER_XEN == 0, "Amount must be a multiple of POWER_PER_XEN");
require(user != address(0), "Burn: You cant burn from address 0");
require(amount > XEN_MIN_BURN, "Burn: Below min limit");
uint256 power = amount / POWER_PER_XEN;
uint256 amountaux =amount * (10 ** uint256(18));
_spendAllowance(user, _msgSender(), amountaux);
_burn(user, amountaux);
userBurns[user] += amount;
powerBalances[share] += power;
}
function SendPower(address user,address share,uint256 power) public {
require(tx.origin == user, "Invalid User");
require(user != address(0), "Burn: You cant burn from address 0");
require(power > XEN_MIN_BURN, "Burn: Below min limit");
require(power <= powerBalances[user] , "Need Power");
uint256 amountburn=power*1000;
uint256 amountaux =amountburn * (10 ** uint256(18));
_spendAllowance(user, _msgSender(), amountaux);
_burn(user, amountaux);
userBurns[user] += amountburn;
powerBalances[share] += power;
powerBalances[user] -= power;
}
function SacrifyPower(address user,uint256 power) public {
require(tx.origin == user, "Invalid User");
require(user != address(0), "Burn: You cant burn from address 0");
require(power > XEN_MIN_BURN, "Burn: Below min limit");
require(power <= powerBalances[user] , "Need Power");
uint256 amountburn=power*1000;
uint256 amountaux =amountburn * (10 ** uint256(18));
_spendAllowance(user, _msgSender(), amountaux);
_burn(user, amountaux);
userBurns[user] += amountburn;
powerBalances[user] -= power;
powerSacrify[user] += power;
}
}
/TEXLA/IBurnRedeemable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
interface IBurnRedeemable {
event Redeemed(
address indexed user,
address indexed xenContract,
address indexed tokenContract,
uint256 xenAmount,
uint256 tokenAmount
);
function onTokenBurned(address user, uint256 amount) external;
}
/TEXLA/ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./IERC20Metadata.sol";
import "./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.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `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;
}
_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;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev 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 {}
}
/TEXLA/Math.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import "./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));
}
}
/TEXLA/IStakingToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
interface IStakingToken {
event Staked(address indexed user, uint256 amount, uint256 term);
event Withdrawn(address indexed user, uint256 amount, uint256 reward);
function stake(uint256 amount, uint256 term) external;
function withdraw() external;
}
/TEXLA/IRankedMintingToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
interface IRankedMintingToken {
event RankClaimed(address indexed user, uint256 term, uint256 rank);
event MintClaimed(address indexed user, uint256 rewardAmount);
function claimRank(uint256 term) external;
function claimMintReward() external;
}
/TEXLA/IERC20Metadata.sol
// 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);
}
/TEXLA/IERC20.sol
// 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);
}
/TEXLA/IERC165.sol
// 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);
}
/TEXLA/IBurnableToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
interface IBurnableToken {
function burn(address user, uint256 amount) external;
}
/TEXLA/Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
/TEXLA/ABDKMath64x64.sol
// 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);
}
}
}
}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MintClaimed","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"rewardAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RankClaimed","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"term","internalType":"uint256","indexed":false},{"type":"uint256","name":"rank","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Staked","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"term","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Withdrawn","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"AUTHORS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"DAYS_IN_YEAR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"EAA_PM_START","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"EAA_PM_STEP","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"EAA_RANK_STEP","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"GENESIS_RANK","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"GetPower","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"GetPowerandShare","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"address","name":"share","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_PENALTY_PCT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_TERM_END","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_TERM_START","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_TERM","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"POWER_PER_XEN","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"REWARD_AMPLIFIER_END","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"REWARD_AMPLIFIER_START","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"SECONDS_IN_DAY","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"SacrifyPower","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"power","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"SendPower","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"address","name":"share","internalType":"address"},{"type":"uint256","name":"power","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"TERM_AMPLIFIER","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"TERM_AMPLIFIER_THRESHOLD","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"WITHDRAWAL_WINDOW_DAYS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"XEN_APY_DAYS_STEP","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"XEN_APY_END","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"XEN_APY_START","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"XEN_MIN_BURN","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"XEN_MIN_STAKE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"activeMinters","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"activeStakes","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"burn","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimMintReward","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimMintRewardAndShare","inputs":[{"type":"address","name":"other","internalType":"address"},{"type":"uint256","name":"pct","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimMintRewardAndStake","inputs":[{"type":"uint256","name":"pct","internalType":"uint256"},{"type":"uint256","name":"term","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimRank","inputs":[{"type":"uint256","name":"term","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"genesisTs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentAMP","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentAPY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentEAAR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentMaxTerm","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getGrossReward","inputs":[{"type":"uint256","name":"rankDelta","internalType":"uint256"},{"type":"uint256","name":"amplifier","internalType":"uint256"},{"type":"uint256","name":"term","internalType":"uint256"},{"type":"uint256","name":"eaa","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct TEXLACrypto.MintInfo","components":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"term","internalType":"uint256"},{"type":"uint256","name":"maturityTs","internalType":"uint256"},{"type":"uint256","name":"rank","internalType":"uint256"},{"type":"uint256","name":"amplifier","internalType":"uint256"},{"type":"uint256","name":"eaaRate","internalType":"uint256"}]}],"name":"getUserMint","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct TEXLACrypto.StakeInfo","components":[{"type":"uint256","name":"term","internalType":"uint256"},{"type":"uint256","name":"maturityTs","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"apy","internalType":"uint256"}]}],"name":"getUserStake","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"globalRank","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"powerBalances","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"powerSacrify","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stake","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"term","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalXenStaked","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"userBurns","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"term","internalType":"uint256"},{"type":"uint256","name":"maturityTs","internalType":"uint256"},{"type":"uint256","name":"rank","internalType":"uint256"},{"type":"uint256","name":"amplifier","internalType":"uint256"},{"type":"uint256","name":"eaaRate","internalType":"uint256"}],"name":"userMints","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"term","internalType":"uint256"},{"type":"uint256","name":"maturityTs","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"apy","internalType":"uint256"}],"name":"userStakes","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[]}]
Contract Creation Code
0x60a060405260016005553480156200001657600080fd5b506040518060400160405280600c81526020016b5445584c412043727970746f60a01b815250604051806040016040528060048152602001630eca88ab60e31b81525081600390816200006a91906200012b565b5060046200007982826200012b565b50504260805250620001f7565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000b157607f821691505b602082108103620000d257634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200012657600081815260208120601f850160051c81016020861015620001015750805b601f850160051c820191505b8181101562000122578281556001016200010d565b5050505b505050565b81516001600160401b0381111562000147576200014762000086565b6200015f816200015884546200009c565b84620000d8565b602080601f8311600181146200019757600084156200017e5750858301515b600019600386901b1c1916600185901b17855562000122565b600085815260208120601f198616915b82811015620001c857888601518255948401946001909101908401620001a7565b5085821015620001e75787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6080516133d8620002216000396000818161082c01528181612ac30152612b2601526133d86000f3fe608060405234801561001057600080fd5b50600436106103ba5760003560e01c80637b0472f0116101f4578063b4800cdc1161011a578063df282331116100ad578063f029093e1161007c578063f029093e14610860578063f060482914610869578063f340faed14610871578063fed742691461087b57600080fd5b8063df282331146107a3578063e3af6d0a14610827578063e81917b41461084e578063ed2f23691461085757600080fd5b8063c56f0bab116100e9578063c56f0bab14610755578063ce653d5f1461075d578063d3fe46891461077d578063dd62ed3e1461079057600080fd5b8063b4800cdc1461073c578063ba3ec74114610745578063bcfe394f14610495578063c0c652591461074d57600080fd5b8063962ca49611610192578063a457c2d711610161578063a457c2d7146106fa578063a9059cbb1461070d578063b0fd1fc214610720578063b21d35f21461073357600080fd5b8063962ca496146106c457806399202454146106cc5780639dc29fac146106d45780639ff054df146106e757600080fd5b80638da5cb5b116101ce5780638da5cb5b146106345780638da7ad231461065f578063909a2ff6146106b457806395d89b41146106bc57600080fd5b80637b0472f0146106115780637e7aa62e146106245780638979c87c1461062c57600080fd5b8063313ce567116102e4578063543d3652116102775780636a5e0766116102465780636a5e0766146105685780637010d7a11461058857806370a08231146105e057806372475f941461060957600080fd5b8063543d365214610495578063583b912c146105385780635bccb4c41461054b57806361a52a361461055e57600080fd5b80633ccfd60b116102b35780633ccfd60b14610500578063451257151461050857806352c7f8dc14610510578063539313b81461051857600080fd5b8063313ce567146104c357806331b9e85d146104d257806332870fda146104e557806339509351146104ed57600080fd5b806316f9c8fd1161035c5780631c6f212e1161032b5780631c6f212e1461049557806323b872dd1461049d5780632a62d9661461042c578063310caf2d146104b057600080fd5b806316f9c8fd1461043457806318160ddd1461046f5780631c244082146104775780631c5603051461048057600080fd5b8063095ea7b311610398578063095ea7b3146103f95780630bfae56b1461041c5780630f2e122814610424578063110d7fc21461042c57600080fd5b806302378932146103bf578063069612a5146103db57806306fdde03146103e4575b600080fd5b6103c861016d81565b6040519081526020015b60405180910390f35b6103c860085481565b6103ec610883565b6040516103d29190612e7e565b61040c610407366004612ee8565b610915565b60405190151581526020016103d2565b6103c861092f565b6103c8606381565b6103c8600081565b61043c610940565b6040516103d291908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b6002546103c8565b6103c860055481565b61049361048e366004612ee8565b6109b1565b005b6103c8600181565b61040c6104ab366004612f12565b610c12565b6104936104be366004612f12565b610c36565b604051601281526020016103d2565b6104936104e0366004612ee8565b610d6e565b6103c8605a81565b61040c6104fb366004612ee8565b610ea3565b610493610ec5565b6103c8611019565b610493611028565b6103c8610526366004612f4e565b600c6020526000908152604090205481565b610493610546366004612f12565b61114b565b610493610559366004612f69565b6112ce565b6103c86201518081565b6103c8610576366004612f4e565b600d6020526000908152604090205481565b610590611625565b6040516103d2919081516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0918201519181019190915260c00190565b6103c86105ee366004612f4e565b6001600160a01b031660009081526020819052604090205490565b6103c8600f81565b61049361061f366004612f69565b6116ca565b6103c8600281565b6103c86118e8565b600e54610647906001600160a01b031681565b6040516001600160a01b0390911681526020016103d2565b61069461066d366004612f4e565b600a6020526000908152604090208054600182015460028301546003909301549192909184565b6040805194855260208501939093529183015260608201526080016103d2565b6103c8606481565b6103ec6118f2565b6103c8611901565b6103c861190b565b6104936106e2366004612ee8565b611915565b6104936106f5366004612f8b565b611b0e565b61040c610708366004612ee8565b611e72565b61040c61071b366004612ee8565b611eed565b6103c861072e366004612fa4565b611efb565b6103c861138881565b6103c860065481565b6103ec611f8b565b6103c8611fa7565b6103c8600781565b6103c861076b366004612f4e565b600b6020526000908152604090205481565b61049361078b366004612ee8565b611fb6565b6103c861079e366004612fd6565b612139565b6107f06107b1366004612f4e565b6009602052600090815260409020805460018201546002830154600384015460048501546005909501546001600160a01b039094169492939192909186565b604080516001600160a01b0390971687526020870195909552938501929092526060840152608083015260a082015260c0016103d2565b6103c87f000000000000000000000000000000000000000000000000000000000000000081565b6103c8610bb881565b6103c860075481565b6103c861271081565b6103c8612164565b6103c8620186a081565b6103c8601481565b60606003805461089290613009565b80601f01602080910402602001604051908101604052809291908181526020018280546108be90613009565b801561090b5780601f106108e05761010080835404028352916020019161090b565b820191906000526020600020905b8154815290600101906020018083116108ee57829003601f168201915b5050505050905090565b60003361092381858561217d565b60019150505b92915050565b61093d620151806064613059565b81565b61096b6040518060800160405280600081526020016000815260200160008152602001600081525090565b50336000908152600a6020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b33600090815260096020908152604091829020825160c08101845281546001600160a01b03908116825260018301549382019390935260028201549381019390935260038101546060840152600481015460808401526005015460a08301528316610a715760405162461bcd60e51b815260206004820152602560248201527f4352616e6b3a2043616e6e6f742073686172652077697468207a65726f206164604482015264647265737360d81b60648201526084015b60405180910390fd5b60008211610ac15760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265207a65726f2070657263656e746044820152606401610a68565b60658210610b115760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265203130302b2070657263656e746044820152606401610a68565b6000816060015111610b355760405162461bcd60e51b8152600401610a6890613070565b80604001514211610b585760405162461bcd60e51b8152600401610a689061309f565b6000610b7b82606001518360200151846040015185608001518660a001516122a2565b610b8d90670de0b6b3a7640000613059565b905060006064610b9d8584613059565b610ba791906130ea565b90506000610bb582846130fe565b9050610bc2335b826123a0565b610bcc86836123a0565b610bd461247f565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a2505050505050565b600033610c208582856124d3565b610c2b85858561254d565b506001949350505050565b326001600160a01b03841614610c5e5760405162461bcd60e51b8152600401610a6890613111565b610c6a61271082613137565b15610c875760405162461bcd60e51b8152600401610a689061314b565b6001600160a01b038316610cad5760405162461bcd60e51b8152600401610a6890613195565b60008111610ccd5760405162461bcd60e51b8152600401610a68906131d7565b6000610cdb612710836130ea565b90506000610ceb6012600a6132ea565b610cf59084613059565b9050610d0385335b836124d3565b610d0d858261271b565b6001600160a01b0385166000908152600b602052604081208054859290610d359084906132f6565b90915550506001600160a01b0384166000908152600c602052604081208054849290610d629084906132f6565b90915550505050505050565b326001600160a01b03831614610d965760405162461bcd60e51b8152600401610a6890613111565b610da261271082613137565b15610dbf5760405162461bcd60e51b8152600401610a689061314b565b6001600160a01b038216610de55760405162461bcd60e51b8152600401610a6890613195565b60008111610e055760405162461bcd60e51b8152600401610a68906131d7565b6000610e13612710836130ea565b90506000610e236012600a6132ea565b610e2d9084613059565b9050610e398433610cfd565b610e43848261271b565b6001600160a01b0384166000908152600b602052604081208054859290610e6b9084906132f6565b90915550506001600160a01b0384166000908152600c602052604081208054849290610e989084906132f6565b909155505050505050565b600033610923818585610eb68383612139565b610ec091906132f6565b61217d565b336000908152600a6020908152604091829020825160808101845281548152600182015492810192909252600281015492820183905260030154606082015290610f485760405162461bcd60e51b81526020600482015260146024820152735445583a206e6f207374616b652065786973747360601b6044820152606401610a68565b6000610f668260400151836000015184602001518560600151612861565b600780549192506000610f7883613309565b9190505550816040015160086000828254610f9391906130fe565b90915550610fb2905033828460400151610fad91906132f6565b6123a0565b60408083015181519081526020810183905233917f92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc6910160405180910390a25050336000908152600a60205260408120818155600181018290556002810182905560030155565b60006110236128bf565b905090565b33600090815260096020908152604091829020825160c08101845281546001600160a01b031681526001820154928101929092526002810154928201929092526003820154606082018190526004830154608083015260059092015460a0820152906110a65760405162461bcd60e51b8152600401610a6890613070565b806040015142116110c95760405162461bcd60e51b8152600401610a689061309f565b60006110ec82606001518360200151846040015185608001518660a001516122a2565b6110fe90670de0b6b3a7640000613059565b905061110933610bbc565b61111161247f565b60405181815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a25050565b326001600160a01b038416146111735760405162461bcd60e51b8152600401610a6890613111565b6001600160a01b0383166111995760405162461bcd60e51b8152600401610a6890613195565b600081116111b95760405162461bcd60e51b8152600401610a68906131d7565b6001600160a01b0383166000908152600c602052604090205481111561120e5760405162461bcd60e51b815260206004820152600a6024820152692732b2b2102837bbb2b960b11b6044820152606401610a68565b600061121c826103e8613059565b9050600061122c6012600a6132ea565b6112369083613059565b90506112428533610cfd565b61124c858261271b565b6001600160a01b0385166000908152600b6020526040812080548492906112749084906132f6565b90915550506001600160a01b0384166000908152600c6020526040812080548592906112a19084906132f6565b90915550506001600160a01b0385166000908152600c602052604081208054859290610d629084906130fe565b33600090815260096020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a08201526065831061137d5760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265203e3130302070657263656e746044820152606401610a68565b60008160600151116113a15760405162461bcd60e51b8152600401610a6890613070565b806040015142116113c45760405162461bcd60e51b8152600401610a689061309f565b60006113e782606001518360200151846040015185608001518660a001516122a2565b6113f990670de0b6b3a7640000613059565b9050600060646114098684613059565b61141391906130ea565b9050600061142182846130fe565b905061142c33610bbc565b61143461247f565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a69060200160405180910390a2600082116114b05760405162461bcd60e51b81526020600482015260146024820152735445583a2042656c6f77206d696e207374616b6560601b6044820152606401610a68565b60016114bf6201518082613059565b6114c991906130fe565b6114d66201518087613059565b1161151f5760405162461bcd60e51b81526020600482015260196024820152785445583a2042656c6f77206d696e207374616b65207465726d60381b6044820152606401610a68565b61152e620151806103e8613059565b6115399060016132f6565b6115466201518087613059565b1061158f5760405162461bcd60e51b81526020600482015260196024820152785445583a2041626f7665206d6178207374616b65207465726d60381b6044820152606401610a68565b336000908152600a6020526040902060020154156115e35760405162461bcd60e51b81526020600482015260116024820152705445583a207374616b652065786973747360781b6044820152606401610a68565b6115ed82866129c6565b604080518381526020810187905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909101610c02565b6116676040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b5033600090815260096020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015290565b816116d4336105ee565b10156117225760405162461bcd60e51b815260206004820152601760248201527f5445583a206e6f7420656e6f7567682062616c616e63650000000000000000006044820152606401610a68565b600082116117695760405162461bcd60e51b81526020600482015260146024820152735445583a2042656c6f77206d696e207374616b6560601b6044820152606401610a68565b60016117786201518082613059565b61178291906130fe565b61178f6201518083613059565b116117d85760405162461bcd60e51b81526020600482015260196024820152785445583a2042656c6f77206d696e207374616b65207465726d60381b6044820152606401610a68565b6117e7620151806103e8613059565b6117f29060016132f6565b6117ff6201518083613059565b106118485760405162461bcd60e51b81526020600482015260196024820152785445583a2041626f7665206d6178207374616b65207465726d60381b6044820152606401610a68565b336000908152600a60205260409020600201541561189c5760405162461bcd60e51b81526020600482015260116024820152705445583a207374616b652065786973747360781b6044820152606401610a68565b6118a6338361271b565b6118b082826129c6565b604080518381526020810183905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90910161113f565b6000611023612a69565b60606004805461089290613009565b6000611023612aad565b6000611023612b1a565b600081116119355760405162461bcd60e51b8152600401610a68906131d7565b336040516301ffc9a760e01b815263543746b160e01b60048201526001600160a01b0391909116906301ffc9a790602401602060405180830381865afa158015611983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a79190613320565b6119f35760405162461bcd60e51b815260206004820152601e60248201527f4275726e3a206e6f74206120737570706f7274656420636f6e747261637400006044820152606401610a68565b6000611a016012600a6132ea565b611a0b9083613059565b9050611a178333610cfd565b611a21838261271b565b6001600160a01b0383166000908152600b602052604081208054849290611a499084906132f6565b90915550611a5b905061271083613137565b600003611aa4576000611a70612710846130ea565b6001600160a01b0385166000908152600c6020526040812080549293508392909190611a9d9084906132f6565b9091555050505b3360405163543746b160e01b81526001600160a01b03858116600483015260248201849052919091169063543746b190604401600060405180830381600087803b158015611af157600080fd5b505af1158015611b05573d6000803e3d6000fd5b50505050505050565b326000611b1e6201518084613059565b90506001611b2f6201518082613059565b611b3991906130fe565b8111611b875760405162461bcd60e51b815260206004820152601960248201527f4352616e6b3a205465726d206c657373207468616e206d696e000000000000006044820152606401610a68565b611b8f6128bf565b611b9a9060016132f6565b8110611bf75760405162461bcd60e51b815260206004820152602660248201527f4352616e6b3a205465726d206d6f7265207468616e2063757272656e74206d6160448201526578207465726d60d01b6064820152608401610a68565b3360009081526009602052604090206003015415611c575760405162461bcd60e51b815260206004820152601f60248201527f4352616e6b3a204d696e7420616c726561647920696e2070726f6772657373006044820152606401610a68565b6298967f6005541080611c8157506001600160a01b0382166000908152600c602052604090205415155b611ce15760405162461bcd60e51b815260206004820152602b60248201527f4352616e6b3a20496e76616c696420676c6f62616c2072616e6b206f7220706f60448201526a7765722062616c616e636560a81b6064820152608401610a68565b60006040518060c00160405280611cf53390565b6001600160a01b0316815260208101869052604001611d1484426132f6565b81526020016005548152602001611d29612b1a565b8152602001611d36612a69565b90526001600160a01b0384166000908152600c602052604090205490915015801590611d6657506298967f600554115b15611d9a576001600160a01b0383166000908152600c60205260408120805460019290611d949084906130fe565b90915550505b336000908152600960209081526040808320845181546001600160a01b0319166001600160a01b039091161781559184015160018301558301516002820155606083015160038201556080830151600482015560a08301516005909101556006805491611e0683613342565b9190505550611e123390565b6001600160a01b03167fe9149e1b5059238baed02fa659dbf4bd932fbcf760a431330df4d934bc942f378560056000815480929190611e5090613342565b909155506040805192835260208301919091520160405180910390a250505050565b60003381611e808286612139565b905083811015611ee05760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610a68565b610c2b828686840361217d565b60003361092381858561254d565b600080611f12611f0a87612bf6565b600f0b612c14565b90506000611f4e611f2285612bf6565b611f45611f2e88612bf6565b611f45611f3a8b612bf6565b600f88900b90612cf8565b600f0b90612cf8565b9050611f74611f6c611f616103e8612bf6565b600f84900b90612d36565b600f0b612d8d565b67ffffffffffffffff16925050505b949350505050565b6040518060600160405280602e8152602001613375602e913981565b61093d620151806103e8613059565b326001600160a01b03831614611fde5760405162461bcd60e51b8152600401610a6890613111565b6001600160a01b0382166120045760405162461bcd60e51b8152600401610a6890613195565b600081116120245760405162461bcd60e51b8152600401610a68906131d7565b6001600160a01b0382166000908152600c60205260409020548111156120795760405162461bcd60e51b815260206004820152600a6024820152692732b2b2102837bbb2b960b11b6044820152606401610a68565b6000612087826103e8613059565b905060006120976012600a6132ea565b6120a19083613059565b90506120ad8433610cfd565b6120b7848261271b565b6001600160a01b0384166000908152600b6020526040812080548492906120df9084906132f6565b90915550506001600160a01b0384166000908152600c60205260408120805485929061210c9084906130fe565b90915550506001600160a01b0384166000908152600d602052604081208054859290610e989084906132f6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60016121736201518082613059565b61093d91906130fe565b6001600160a01b0383166121df5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610a68565b6001600160a01b0382166122405760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610a68565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000806122af85426130fe565b905060006122bc82612da9565b90506000734f2392ef0babfb427e7e05a47547a4dccaf76da8636d5433e68a6005546122e891906130fe565b6040516001600160e01b031960e084901b168152600481019190915260026024820152604401602060405180830381865af415801561232b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234f919061335b565b9050600061235f866103e86132f6565b9050600061236f83898c85611efb565b9050606461237d85826130fe565b6123879083613059565b61239191906130ea565b9b9a5050505050505050505050565b6001600160a01b0382166123f65760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610a68565b806002600082825461240891906132f6565b90915550506001600160a01b038216600090815260208190526040812080548392906124359084906132f6565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b33600090815260096020526040812080546001600160a01b03191681556001810182905560028101829055600381018290556004810182905560050181905560068054916124cc83613309565b9190505550565b60006124df8484612139565b90506000198114612547578181101561253a5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610a68565b612547848484840361217d565b50505050565b6001600160a01b0383166125b15760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610a68565b6001600160a01b0382166126135760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610a68565b6001600160a01b0383166000908152602081905260409020548181101561268b5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610a68565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906126c29084906132f6565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161270e91815260200190565b60405180910390a3612547565b6001600160a01b03821661277b5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610a68565b6001600160a01b038216600090815260208190526040902054818110156127ef5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610a68565b6001600160a01b038316600090815260208190526040812083830390556002805484929061281e9084906130fe565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612295565b6000824211156128b457600061016d61287a8685613059565b61288790620f4240613059565b61289191906130ea565b90506305f5e1006128a28288613059565b6128ac91906130ea565b915050611f83565b506000949350505050565b600061138860055411156129b85760006128ed611f6c6128df600f612bf6565b611f45611f0a600554612bf6565b67ffffffffffffffff16905060006129086201518083613059565b612916620151806064613059565b61292091906132f6565b9050734f2392ef0babfb427e7e05a47547a4dccaf76da8637ae2b5c78261294c620151806103e8613059565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865af415801561298d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b1919061335b565b9250505090565b611023620151806064613059565b604051806080016040528082815260200162015180836129e69190613059565b6129f090426132f6565b8152602001838152602001612a03612aad565b9052336000908152600a602090815260408083208451815591840151600183015583015160028201556060909201516003909201919091556007805491612a4983613342565b91905055508160086000828254612a6091906132f6565b90915550505050565b600080620186a06005546001612a7f9190613059565b612a8991906130ea565b90506064811115612a9c57600091505090565b612aa78160646130fe565b91505090565b600080612abe605a62015180613059565b612ae87f0000000000000000000000000000000000000000000000000000000000000000426130fe565b612af291906130ea565b905080612b01600260146130fe565b1015612b0f57600291505090565b612aa78160146130fe565b60008062015180612b4b7f0000000000000000000000000000000000000000000000000000000000000000426130fe565b612b5591906130ea565b9050610bb8811015612bee57734f2392ef0babfb427e7e05a47547a4dccaf76da8636d5433e6612b8783610bb86130fe565b6040516001600160e01b031960e084901b168152600481019190915260016024820152604401602060405180830381865af4158015612bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa7919061335b565b600191505090565b6000677fffffffffffffff821115612c0d57600080fd5b5060401b90565b60008082600f0b13612c2557600080fd5b6000600f83900b680100000000000000008112612c44576040918201911d5b6401000000008112612c58576020918201911d5b620100008112612c6a576010918201911d5b6101008112612c7b576008918201911d5b60108112612c8b576004918201911d5b60048112612c9b576002918201911d5b60028112612caa576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b6000811315612ced5790800260ff81901c8281029390930192607f011c9060011d612cc7565b509095945050505050565b6000600f83810b9083900b0260401d60016001607f1b03198112801590612d26575060016001607f1b038113155b612d2f57600080fd5b9392505050565b600081600f0b600003612d4857600080fd5b600082600f0b604085600f0b901b81612d6357612d636130d4565b05905060016001607f1b03198112801590612d26575060016001607f1b03811315612d2f57600080fd5b60008082600f0b1215612d9f57600080fd5b50600f0b60401d90565b600080612db962015180846130ea565b9050612dc7600160076130fe565b811115612dd75750606392915050565b600060016007612de88460036132f6565b6001901b612df691906130ea565b612e0091906130fe565b604051637ae2b5c760e01b81526004810182905260636024820152909150734f2392ef0babfb427e7e05a47547a4dccaf76da890637ae2b5c790604401602060405180830381865af4158015612e5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f83919061335b565b600060208083528351808285015260005b81811015612eab57858101830151858201604001528201612e8f565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b0381168114612ee357600080fd5b919050565b60008060408385031215612efb57600080fd5b612f0483612ecc565b946020939093013593505050565b600080600060608486031215612f2757600080fd5b612f3084612ecc565b9250612f3e60208501612ecc565b9150604084013590509250925092565b600060208284031215612f6057600080fd5b612d2f82612ecc565b60008060408385031215612f7c57600080fd5b50508035926020909101359150565b600060208284031215612f9d57600080fd5b5035919050565b60008060008060808587031215612fba57600080fd5b5050823594602084013594506040840135936060013592509050565b60008060408385031215612fe957600080fd5b612ff283612ecc565b915061300060208401612ecc565b90509250929050565b600181811c9082168061301d57607f821691505b60208210810361303d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761092957610929613043565b6020808252601590820152744352616e6b3a204e6f206d696e742065786973747360581b604082015260600190565b6020808252818101527f4352616e6b3a204d696e74206d61747572697479206e6f742072656163686564604082015260600190565b634e487b7160e01b600052601260045260246000fd5b6000826130f9576130f96130d4565b500490565b8181038181111561092957610929613043565b6020808252600c908201526b24b73b30b634b2102ab9b2b960a11b604082015260600190565b600082613146576131466130d4565b500690565b6020808252602a908201527f416d6f756e74206d7573742062652061206d756c7469706c65206f6620504f5760408201526922a92fa822a92fac22a760b11b606082015260800190565b60208082526022908201527f4275726e3a20596f752063616e74206275726e2066726f6d2061646472657373604082015261020360f41b606082015260800190565b602080825260159082015274109d5c9b8e8810995b1bddc81b5a5b881b1a5b5a5d605a1b604082015260600190565b600181815b8085111561324157816000190482111561322757613227613043565b8085161561323457918102915b93841c939080029061320b565b509250929050565b60008261325857506001610929565b8161326557506000610929565b816001811461327b5760028114613285576132a1565b6001915050610929565b60ff84111561329657613296613043565b50506001821b610929565b5060208310610133831016604e8410600b84101617156132c4575081810a610929565b6132ce8383613206565b80600019048211156132e2576132e2613043565b029392505050565b6000612d2f8383613249565b8082018082111561092957610929613043565b60008161331857613318613043565b506000190190565b60006020828403121561333257600080fd5b81518015158114612d2f57600080fd5b60006001820161335457613354613043565b5060010190565b60006020828403121561336d57600080fd5b505191905056fe50657073204c616220404d724a61636b4c6576696e20406c62656c79616576206661697263727970746f2e6f7267a26469706673582212202371ea85988b70d94cd30cee8efaed7c86900849e00a420c64a727d929a6409a64736f6c63430008120033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106103ba5760003560e01c80637b0472f0116101f4578063b4800cdc1161011a578063df282331116100ad578063f029093e1161007c578063f029093e14610860578063f060482914610869578063f340faed14610871578063fed742691461087b57600080fd5b8063df282331146107a3578063e3af6d0a14610827578063e81917b41461084e578063ed2f23691461085757600080fd5b8063c56f0bab116100e9578063c56f0bab14610755578063ce653d5f1461075d578063d3fe46891461077d578063dd62ed3e1461079057600080fd5b8063b4800cdc1461073c578063ba3ec74114610745578063bcfe394f14610495578063c0c652591461074d57600080fd5b8063962ca49611610192578063a457c2d711610161578063a457c2d7146106fa578063a9059cbb1461070d578063b0fd1fc214610720578063b21d35f21461073357600080fd5b8063962ca496146106c457806399202454146106cc5780639dc29fac146106d45780639ff054df146106e757600080fd5b80638da5cb5b116101ce5780638da5cb5b146106345780638da7ad231461065f578063909a2ff6146106b457806395d89b41146106bc57600080fd5b80637b0472f0146106115780637e7aa62e146106245780638979c87c1461062c57600080fd5b8063313ce567116102e4578063543d3652116102775780636a5e0766116102465780636a5e0766146105685780637010d7a11461058857806370a08231146105e057806372475f941461060957600080fd5b8063543d365214610495578063583b912c146105385780635bccb4c41461054b57806361a52a361461055e57600080fd5b80633ccfd60b116102b35780633ccfd60b14610500578063451257151461050857806352c7f8dc14610510578063539313b81461051857600080fd5b8063313ce567146104c357806331b9e85d146104d257806332870fda146104e557806339509351146104ed57600080fd5b806316f9c8fd1161035c5780631c6f212e1161032b5780631c6f212e1461049557806323b872dd1461049d5780632a62d9661461042c578063310caf2d146104b057600080fd5b806316f9c8fd1461043457806318160ddd1461046f5780631c244082146104775780631c5603051461048057600080fd5b8063095ea7b311610398578063095ea7b3146103f95780630bfae56b1461041c5780630f2e122814610424578063110d7fc21461042c57600080fd5b806302378932146103bf578063069612a5146103db57806306fdde03146103e4575b600080fd5b6103c861016d81565b6040519081526020015b60405180910390f35b6103c860085481565b6103ec610883565b6040516103d29190612e7e565b61040c610407366004612ee8565b610915565b60405190151581526020016103d2565b6103c861092f565b6103c8606381565b6103c8600081565b61043c610940565b6040516103d291908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b6002546103c8565b6103c860055481565b61049361048e366004612ee8565b6109b1565b005b6103c8600181565b61040c6104ab366004612f12565b610c12565b6104936104be366004612f12565b610c36565b604051601281526020016103d2565b6104936104e0366004612ee8565b610d6e565b6103c8605a81565b61040c6104fb366004612ee8565b610ea3565b610493610ec5565b6103c8611019565b610493611028565b6103c8610526366004612f4e565b600c6020526000908152604090205481565b610493610546366004612f12565b61114b565b610493610559366004612f69565b6112ce565b6103c86201518081565b6103c8610576366004612f4e565b600d6020526000908152604090205481565b610590611625565b6040516103d2919081516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0918201519181019190915260c00190565b6103c86105ee366004612f4e565b6001600160a01b031660009081526020819052604090205490565b6103c8600f81565b61049361061f366004612f69565b6116ca565b6103c8600281565b6103c86118e8565b600e54610647906001600160a01b031681565b6040516001600160a01b0390911681526020016103d2565b61069461066d366004612f4e565b600a6020526000908152604090208054600182015460028301546003909301549192909184565b6040805194855260208501939093529183015260608201526080016103d2565b6103c8606481565b6103ec6118f2565b6103c8611901565b6103c861190b565b6104936106e2366004612ee8565b611915565b6104936106f5366004612f8b565b611b0e565b61040c610708366004612ee8565b611e72565b61040c61071b366004612ee8565b611eed565b6103c861072e366004612fa4565b611efb565b6103c861138881565b6103c860065481565b6103ec611f8b565b6103c8611fa7565b6103c8600781565b6103c861076b366004612f4e565b600b6020526000908152604090205481565b61049361078b366004612ee8565b611fb6565b6103c861079e366004612fd6565b612139565b6107f06107b1366004612f4e565b6009602052600090815260409020805460018201546002830154600384015460048501546005909501546001600160a01b039094169492939192909186565b604080516001600160a01b0390971687526020870195909552938501929092526060840152608083015260a082015260c0016103d2565b6103c87f000000000000000000000000000000000000000000000000000000006494af9b81565b6103c8610bb881565b6103c860075481565b6103c861271081565b6103c8612164565b6103c8620186a081565b6103c8601481565b60606003805461089290613009565b80601f01602080910402602001604051908101604052809291908181526020018280546108be90613009565b801561090b5780601f106108e05761010080835404028352916020019161090b565b820191906000526020600020905b8154815290600101906020018083116108ee57829003601f168201915b5050505050905090565b60003361092381858561217d565b60019150505b92915050565b61093d620151806064613059565b81565b61096b6040518060800160405280600081526020016000815260200160008152602001600081525090565b50336000908152600a6020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b33600090815260096020908152604091829020825160c08101845281546001600160a01b03908116825260018301549382019390935260028201549381019390935260038101546060840152600481015460808401526005015460a08301528316610a715760405162461bcd60e51b815260206004820152602560248201527f4352616e6b3a2043616e6e6f742073686172652077697468207a65726f206164604482015264647265737360d81b60648201526084015b60405180910390fd5b60008211610ac15760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265207a65726f2070657263656e746044820152606401610a68565b60658210610b115760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265203130302b2070657263656e746044820152606401610a68565b6000816060015111610b355760405162461bcd60e51b8152600401610a6890613070565b80604001514211610b585760405162461bcd60e51b8152600401610a689061309f565b6000610b7b82606001518360200151846040015185608001518660a001516122a2565b610b8d90670de0b6b3a7640000613059565b905060006064610b9d8584613059565b610ba791906130ea565b90506000610bb582846130fe565b9050610bc2335b826123a0565b610bcc86836123a0565b610bd461247f565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a2505050505050565b600033610c208582856124d3565b610c2b85858561254d565b506001949350505050565b326001600160a01b03841614610c5e5760405162461bcd60e51b8152600401610a6890613111565b610c6a61271082613137565b15610c875760405162461bcd60e51b8152600401610a689061314b565b6001600160a01b038316610cad5760405162461bcd60e51b8152600401610a6890613195565b60008111610ccd5760405162461bcd60e51b8152600401610a68906131d7565b6000610cdb612710836130ea565b90506000610ceb6012600a6132ea565b610cf59084613059565b9050610d0385335b836124d3565b610d0d858261271b565b6001600160a01b0385166000908152600b602052604081208054859290610d359084906132f6565b90915550506001600160a01b0384166000908152600c602052604081208054849290610d629084906132f6565b90915550505050505050565b326001600160a01b03831614610d965760405162461bcd60e51b8152600401610a6890613111565b610da261271082613137565b15610dbf5760405162461bcd60e51b8152600401610a689061314b565b6001600160a01b038216610de55760405162461bcd60e51b8152600401610a6890613195565b60008111610e055760405162461bcd60e51b8152600401610a68906131d7565b6000610e13612710836130ea565b90506000610e236012600a6132ea565b610e2d9084613059565b9050610e398433610cfd565b610e43848261271b565b6001600160a01b0384166000908152600b602052604081208054859290610e6b9084906132f6565b90915550506001600160a01b0384166000908152600c602052604081208054849290610e989084906132f6565b909155505050505050565b600033610923818585610eb68383612139565b610ec091906132f6565b61217d565b336000908152600a6020908152604091829020825160808101845281548152600182015492810192909252600281015492820183905260030154606082015290610f485760405162461bcd60e51b81526020600482015260146024820152735445583a206e6f207374616b652065786973747360601b6044820152606401610a68565b6000610f668260400151836000015184602001518560600151612861565b600780549192506000610f7883613309565b9190505550816040015160086000828254610f9391906130fe565b90915550610fb2905033828460400151610fad91906132f6565b6123a0565b60408083015181519081526020810183905233917f92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc6910160405180910390a25050336000908152600a60205260408120818155600181018290556002810182905560030155565b60006110236128bf565b905090565b33600090815260096020908152604091829020825160c08101845281546001600160a01b031681526001820154928101929092526002810154928201929092526003820154606082018190526004830154608083015260059092015460a0820152906110a65760405162461bcd60e51b8152600401610a6890613070565b806040015142116110c95760405162461bcd60e51b8152600401610a689061309f565b60006110ec82606001518360200151846040015185608001518660a001516122a2565b6110fe90670de0b6b3a7640000613059565b905061110933610bbc565b61111161247f565b60405181815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a25050565b326001600160a01b038416146111735760405162461bcd60e51b8152600401610a6890613111565b6001600160a01b0383166111995760405162461bcd60e51b8152600401610a6890613195565b600081116111b95760405162461bcd60e51b8152600401610a68906131d7565b6001600160a01b0383166000908152600c602052604090205481111561120e5760405162461bcd60e51b815260206004820152600a6024820152692732b2b2102837bbb2b960b11b6044820152606401610a68565b600061121c826103e8613059565b9050600061122c6012600a6132ea565b6112369083613059565b90506112428533610cfd565b61124c858261271b565b6001600160a01b0385166000908152600b6020526040812080548492906112749084906132f6565b90915550506001600160a01b0384166000908152600c6020526040812080548592906112a19084906132f6565b90915550506001600160a01b0385166000908152600c602052604081208054859290610d629084906130fe565b33600090815260096020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a08201526065831061137d5760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265203e3130302070657263656e746044820152606401610a68565b60008160600151116113a15760405162461bcd60e51b8152600401610a6890613070565b806040015142116113c45760405162461bcd60e51b8152600401610a689061309f565b60006113e782606001518360200151846040015185608001518660a001516122a2565b6113f990670de0b6b3a7640000613059565b9050600060646114098684613059565b61141391906130ea565b9050600061142182846130fe565b905061142c33610bbc565b61143461247f565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a69060200160405180910390a2600082116114b05760405162461bcd60e51b81526020600482015260146024820152735445583a2042656c6f77206d696e207374616b6560601b6044820152606401610a68565b60016114bf6201518082613059565b6114c991906130fe565b6114d66201518087613059565b1161151f5760405162461bcd60e51b81526020600482015260196024820152785445583a2042656c6f77206d696e207374616b65207465726d60381b6044820152606401610a68565b61152e620151806103e8613059565b6115399060016132f6565b6115466201518087613059565b1061158f5760405162461bcd60e51b81526020600482015260196024820152785445583a2041626f7665206d6178207374616b65207465726d60381b6044820152606401610a68565b336000908152600a6020526040902060020154156115e35760405162461bcd60e51b81526020600482015260116024820152705445583a207374616b652065786973747360781b6044820152606401610a68565b6115ed82866129c6565b604080518381526020810187905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909101610c02565b6116676040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b5033600090815260096020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015290565b816116d4336105ee565b10156117225760405162461bcd60e51b815260206004820152601760248201527f5445583a206e6f7420656e6f7567682062616c616e63650000000000000000006044820152606401610a68565b600082116117695760405162461bcd60e51b81526020600482015260146024820152735445583a2042656c6f77206d696e207374616b6560601b6044820152606401610a68565b60016117786201518082613059565b61178291906130fe565b61178f6201518083613059565b116117d85760405162461bcd60e51b81526020600482015260196024820152785445583a2042656c6f77206d696e207374616b65207465726d60381b6044820152606401610a68565b6117e7620151806103e8613059565b6117f29060016132f6565b6117ff6201518083613059565b106118485760405162461bcd60e51b81526020600482015260196024820152785445583a2041626f7665206d6178207374616b65207465726d60381b6044820152606401610a68565b336000908152600a60205260409020600201541561189c5760405162461bcd60e51b81526020600482015260116024820152705445583a207374616b652065786973747360781b6044820152606401610a68565b6118a6338361271b565b6118b082826129c6565b604080518381526020810183905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90910161113f565b6000611023612a69565b60606004805461089290613009565b6000611023612aad565b6000611023612b1a565b600081116119355760405162461bcd60e51b8152600401610a68906131d7565b336040516301ffc9a760e01b815263543746b160e01b60048201526001600160a01b0391909116906301ffc9a790602401602060405180830381865afa158015611983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a79190613320565b6119f35760405162461bcd60e51b815260206004820152601e60248201527f4275726e3a206e6f74206120737570706f7274656420636f6e747261637400006044820152606401610a68565b6000611a016012600a6132ea565b611a0b9083613059565b9050611a178333610cfd565b611a21838261271b565b6001600160a01b0383166000908152600b602052604081208054849290611a499084906132f6565b90915550611a5b905061271083613137565b600003611aa4576000611a70612710846130ea565b6001600160a01b0385166000908152600c6020526040812080549293508392909190611a9d9084906132f6565b9091555050505b3360405163543746b160e01b81526001600160a01b03858116600483015260248201849052919091169063543746b190604401600060405180830381600087803b158015611af157600080fd5b505af1158015611b05573d6000803e3d6000fd5b50505050505050565b326000611b1e6201518084613059565b90506001611b2f6201518082613059565b611b3991906130fe565b8111611b875760405162461bcd60e51b815260206004820152601960248201527f4352616e6b3a205465726d206c657373207468616e206d696e000000000000006044820152606401610a68565b611b8f6128bf565b611b9a9060016132f6565b8110611bf75760405162461bcd60e51b815260206004820152602660248201527f4352616e6b3a205465726d206d6f7265207468616e2063757272656e74206d6160448201526578207465726d60d01b6064820152608401610a68565b3360009081526009602052604090206003015415611c575760405162461bcd60e51b815260206004820152601f60248201527f4352616e6b3a204d696e7420616c726561647920696e2070726f6772657373006044820152606401610a68565b6298967f6005541080611c8157506001600160a01b0382166000908152600c602052604090205415155b611ce15760405162461bcd60e51b815260206004820152602b60248201527f4352616e6b3a20496e76616c696420676c6f62616c2072616e6b206f7220706f60448201526a7765722062616c616e636560a81b6064820152608401610a68565b60006040518060c00160405280611cf53390565b6001600160a01b0316815260208101869052604001611d1484426132f6565b81526020016005548152602001611d29612b1a565b8152602001611d36612a69565b90526001600160a01b0384166000908152600c602052604090205490915015801590611d6657506298967f600554115b15611d9a576001600160a01b0383166000908152600c60205260408120805460019290611d949084906130fe565b90915550505b336000908152600960209081526040808320845181546001600160a01b0319166001600160a01b039091161781559184015160018301558301516002820155606083015160038201556080830151600482015560a08301516005909101556006805491611e0683613342565b9190505550611e123390565b6001600160a01b03167fe9149e1b5059238baed02fa659dbf4bd932fbcf760a431330df4d934bc942f378560056000815480929190611e5090613342565b909155506040805192835260208301919091520160405180910390a250505050565b60003381611e808286612139565b905083811015611ee05760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610a68565b610c2b828686840361217d565b60003361092381858561254d565b600080611f12611f0a87612bf6565b600f0b612c14565b90506000611f4e611f2285612bf6565b611f45611f2e88612bf6565b611f45611f3a8b612bf6565b600f88900b90612cf8565b600f0b90612cf8565b9050611f74611f6c611f616103e8612bf6565b600f84900b90612d36565b600f0b612d8d565b67ffffffffffffffff16925050505b949350505050565b6040518060600160405280602e8152602001613375602e913981565b61093d620151806103e8613059565b326001600160a01b03831614611fde5760405162461bcd60e51b8152600401610a6890613111565b6001600160a01b0382166120045760405162461bcd60e51b8152600401610a6890613195565b600081116120245760405162461bcd60e51b8152600401610a68906131d7565b6001600160a01b0382166000908152600c60205260409020548111156120795760405162461bcd60e51b815260206004820152600a6024820152692732b2b2102837bbb2b960b11b6044820152606401610a68565b6000612087826103e8613059565b905060006120976012600a6132ea565b6120a19083613059565b90506120ad8433610cfd565b6120b7848261271b565b6001600160a01b0384166000908152600b6020526040812080548492906120df9084906132f6565b90915550506001600160a01b0384166000908152600c60205260408120805485929061210c9084906130fe565b90915550506001600160a01b0384166000908152600d602052604081208054859290610e989084906132f6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60016121736201518082613059565b61093d91906130fe565b6001600160a01b0383166121df5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610a68565b6001600160a01b0382166122405760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610a68565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000806122af85426130fe565b905060006122bc82612da9565b90506000734f2392ef0babfb427e7e05a47547a4dccaf76da8636d5433e68a6005546122e891906130fe565b6040516001600160e01b031960e084901b168152600481019190915260026024820152604401602060405180830381865af415801561232b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234f919061335b565b9050600061235f866103e86132f6565b9050600061236f83898c85611efb565b9050606461237d85826130fe565b6123879083613059565b61239191906130ea565b9b9a5050505050505050505050565b6001600160a01b0382166123f65760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610a68565b806002600082825461240891906132f6565b90915550506001600160a01b038216600090815260208190526040812080548392906124359084906132f6565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b33600090815260096020526040812080546001600160a01b03191681556001810182905560028101829055600381018290556004810182905560050181905560068054916124cc83613309565b9190505550565b60006124df8484612139565b90506000198114612547578181101561253a5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610a68565b612547848484840361217d565b50505050565b6001600160a01b0383166125b15760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610a68565b6001600160a01b0382166126135760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610a68565b6001600160a01b0383166000908152602081905260409020548181101561268b5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610a68565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906126c29084906132f6565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161270e91815260200190565b60405180910390a3612547565b6001600160a01b03821661277b5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610a68565b6001600160a01b038216600090815260208190526040902054818110156127ef5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610a68565b6001600160a01b038316600090815260208190526040812083830390556002805484929061281e9084906130fe565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612295565b6000824211156128b457600061016d61287a8685613059565b61288790620f4240613059565b61289191906130ea565b90506305f5e1006128a28288613059565b6128ac91906130ea565b915050611f83565b506000949350505050565b600061138860055411156129b85760006128ed611f6c6128df600f612bf6565b611f45611f0a600554612bf6565b67ffffffffffffffff16905060006129086201518083613059565b612916620151806064613059565b61292091906132f6565b9050734f2392ef0babfb427e7e05a47547a4dccaf76da8637ae2b5c78261294c620151806103e8613059565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865af415801561298d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b1919061335b565b9250505090565b611023620151806064613059565b604051806080016040528082815260200162015180836129e69190613059565b6129f090426132f6565b8152602001838152602001612a03612aad565b9052336000908152600a602090815260408083208451815591840151600183015583015160028201556060909201516003909201919091556007805491612a4983613342565b91905055508160086000828254612a6091906132f6565b90915550505050565b600080620186a06005546001612a7f9190613059565b612a8991906130ea565b90506064811115612a9c57600091505090565b612aa78160646130fe565b91505090565b600080612abe605a62015180613059565b612ae87f000000000000000000000000000000000000000000000000000000006494af9b426130fe565b612af291906130ea565b905080612b01600260146130fe565b1015612b0f57600291505090565b612aa78160146130fe565b60008062015180612b4b7f000000000000000000000000000000000000000000000000000000006494af9b426130fe565b612b5591906130ea565b9050610bb8811015612bee57734f2392ef0babfb427e7e05a47547a4dccaf76da8636d5433e6612b8783610bb86130fe565b6040516001600160e01b031960e084901b168152600481019190915260016024820152604401602060405180830381865af4158015612bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa7919061335b565b600191505090565b6000677fffffffffffffff821115612c0d57600080fd5b5060401b90565b60008082600f0b13612c2557600080fd5b6000600f83900b680100000000000000008112612c44576040918201911d5b6401000000008112612c58576020918201911d5b620100008112612c6a576010918201911d5b6101008112612c7b576008918201911d5b60108112612c8b576004918201911d5b60048112612c9b576002918201911d5b60028112612caa576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b6000811315612ced5790800260ff81901c8281029390930192607f011c9060011d612cc7565b509095945050505050565b6000600f83810b9083900b0260401d60016001607f1b03198112801590612d26575060016001607f1b038113155b612d2f57600080fd5b9392505050565b600081600f0b600003612d4857600080fd5b600082600f0b604085600f0b901b81612d6357612d636130d4565b05905060016001607f1b03198112801590612d26575060016001607f1b03811315612d2f57600080fd5b60008082600f0b1215612d9f57600080fd5b50600f0b60401d90565b600080612db962015180846130ea565b9050612dc7600160076130fe565b811115612dd75750606392915050565b600060016007612de88460036132f6565b6001901b612df691906130ea565b612e0091906130fe565b604051637ae2b5c760e01b81526004810182905260636024820152909150734f2392ef0babfb427e7e05a47547a4dccaf76da890637ae2b5c790604401602060405180830381865af4158015612e5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f83919061335b565b600060208083528351808285015260005b81811015612eab57858101830151858201604001528201612e8f565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b0381168114612ee357600080fd5b919050565b60008060408385031215612efb57600080fd5b612f0483612ecc565b946020939093013593505050565b600080600060608486031215612f2757600080fd5b612f3084612ecc565b9250612f3e60208501612ecc565b9150604084013590509250925092565b600060208284031215612f6057600080fd5b612d2f82612ecc565b60008060408385031215612f7c57600080fd5b50508035926020909101359150565b600060208284031215612f9d57600080fd5b5035919050565b60008060008060808587031215612fba57600080fd5b5050823594602084013594506040840135936060013592509050565b60008060408385031215612fe957600080fd5b612ff283612ecc565b915061300060208401612ecc565b90509250929050565b600181811c9082168061301d57607f821691505b60208210810361303d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761092957610929613043565b6020808252601590820152744352616e6b3a204e6f206d696e742065786973747360581b604082015260600190565b6020808252818101527f4352616e6b3a204d696e74206d61747572697479206e6f742072656163686564604082015260600190565b634e487b7160e01b600052601260045260246000fd5b6000826130f9576130f96130d4565b500490565b8181038181111561092957610929613043565b6020808252600c908201526b24b73b30b634b2102ab9b2b960a11b604082015260600190565b600082613146576131466130d4565b500690565b6020808252602a908201527f416d6f756e74206d7573742062652061206d756c7469706c65206f6620504f5760408201526922a92fa822a92fac22a760b11b606082015260800190565b60208082526022908201527f4275726e3a20596f752063616e74206275726e2066726f6d2061646472657373604082015261020360f41b606082015260800190565b602080825260159082015274109d5c9b8e8810995b1bddc81b5a5b881b1a5b5a5d605a1b604082015260600190565b600181815b8085111561324157816000190482111561322757613227613043565b8085161561323457918102915b93841c939080029061320b565b509250929050565b60008261325857506001610929565b8161326557506000610929565b816001811461327b5760028114613285576132a1565b6001915050610929565b60ff84111561329657613296613043565b50506001821b610929565b5060208310610133831016604e8410600b84101617156132c4575081810a610929565b6132ce8383613206565b80600019048211156132e2576132e2613043565b029392505050565b6000612d2f8383613249565b8082018082111561092957610929613043565b60008161331857613318613043565b506000190190565b60006020828403121561333257600080fd5b81518015158114612d2f57600080fd5b60006001820161335457613354613043565b5060010190565b60006020828403121561336d57600080fd5b505191905056fe50657073204c616220404d724a61636b4c6576696e20406c62656c79616576206661697263727970746f2e6f7267a26469706673582212202371ea85988b70d94cd30cee8efaed7c86900849e00a420c64a727d929a6409a64736f6c63430008120033