Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- CD
- Optimization enabled
- true
- Compiler version
- v0.8.16+commit.07a7930e
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2025-09-13T00:07:53.828057Z
Contract source code
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: contracts/lib/Ownable.sol
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender() || owner() == address(0), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: contracts/interfaces/BankXInterface.sol
pragma solidity 0.8.16;
interface BankXInterface {
function balanceOf(address account) external view returns (uint256);
function pool_mint(address _entity, uint _amount) external;
function pool_burn_from(address _entity, uint _amount) external;
function genesis_supply() external returns (uint);
function totalSupply() external view returns (uint);
function updateTVLReached() external;
}
// File: contracts/interfaces/NFTBonusInterface.sol
pragma solidity 0.8.16;
interface NFTBonusInterface {
function getNftsCount(uint _stakeId) external view returns (uint);
function assignStakeId(address _owner, uint _stakeId) external returns (bool);
function stakeEnd(address _owner, uint _stakeId) external;
function nftIdStakedToEntity(uint _nftId) external view returns (address);
}
// File: contracts/interfaces/CollateralPoolInterface.sol
pragma solidity 0.8.16;
interface CollateralPoolInterface {
function bankx_minted_count() external view returns (uint);
function collatDollarBalance() external view returns (uint);
}
// File: contracts/GlobalsAndStats.sol
pragma solidity 0.8.16;
contract GlobalsAndStats is Ownable {
/* DailyDataUpdate
uint40 timestamp --> data0 [ 39: 0]
uint16 beginDay --> data0 [ 55: 40]
uint16 endDay --> data0 [ 71: 56]
bool isAutoUpdate --> data0 [ 79: 72]
address indexed updaterAddr
*/
event DailyDataUpdate(
uint256 data0,
address indexed updaterAddr
);
/* StakeStart
uint40 timestamp --> data0 [ 39: 0]
address indexed stakerAddr
uint40 indexed stakeId
uint72 stakedXs --> data0 [111: 40]
uint72 stakeShares --> data0 [183:112]
uint16 stakedDays --> data0 [199:184]
bool isAutoStake --> data0 [207:200]
*/
event StakeStart(
uint256 data0,
address indexed stakerAddr,
uint40 indexed stakeId
);
/* StakeGoodAccounting
uint40 timestamp --> data0 [ 39: 0]
address indexed stakerAddr
uint40 indexed stakeId
uint72 stakedXs --> data0 [111: 40]
uint72 stakeShares --> data0 [183:112]
uint72 payout --> data0 [255:184]
uint72 penalty --> data1 [ 71: 0]
address indexed senderAddr
*/
event StakeGoodAccounting(
uint256 data0,
uint256 data1,
address indexed stakerAddr,
uint40 indexed stakeId,
address indexed senderAddr
);
/* StakeEnd
uint40 timestamp --> data0 [ 39: 0]
address indexed stakerAddr
uint40 indexed stakeId
uint72 stakedXs --> data0 [111: 40]
uint72 stakeShares --> data0 [183:112]
uint72 payout --> data0 [255:184]
uint72 penalty --> data1 [ 71: 0]
uint16 servedDays --> data1 [ 87: 72]
bool prevUnlocked --> data1 [ 95: 88]
*/
event StakeEnd(
uint256 data0,
uint256 data1,
address indexed stakerAddr,
uint40 indexed stakeId
);
/* CDRateChange
// pricing control CD rate - requires BankX to make price go up.
// keeps staking ahead of inflation
uint40 timestamp --> data0 [ 39: 0]
uint40 CDRate --> data0 [ 79: 40]
uint40 indexed stakeId
*/
event CDRateChange(uint256 data0, uint40 indexed stakeId);
/* Origin BankX address */
address internal constant ORIGIN_ADDR = 0xC0C607cF29852476311B4C17328D18A2D02A845c;
BankXInterface public bankXContract;
NFTBonusInterface public nftBonusContract;
CollateralPoolInterface public collateralPoolContract;
/* Size of a Xs or CD uint */
uint256 internal constant X_UINT_SIZE = 72;
/* Stake timing parameters */
uint256 internal constant MIN_STAKE_DAYS = 1;
uint256 internal constant MAX_STAKE_DAYS = 5555; // Approx 15 years
uint256 internal constant EARLY_PENALTY_MIN_DAYS = 90;
uint256 internal constant LATE_PENALTY_GRACE_DAYS = 2 * 7;
uint256 internal constant LATE_PENALTY_SCALE_DAYS = 100 * 7;
/* Time of contract launch */
uint256 internal launchTime;
/* Stake shares Longer Pays Better bonus constants used by _stakeStartBonusXs() */
uint256 public LPBBonusPercent;
uint256 public LPB;
uint256 public constant LPB_MAX_DAYS = 3640;
uint256 public LPBLastUpdated;
/* Stake shares Bigger Pays Better bonus constants used by _stakeStartBonusXs() */
uint256 private constant XS_PER_BANKX = 1e8;
uint256 private constant BPB_BONUS_PERCENT = 10;
uint256 private constant BPB_MAX_BANKX = 150 * 1e6;
uint256 internal constant BPB_MAX_XS = BPB_MAX_BANKX * XS_PER_BANKX;
uint256 internal constant BPB = BPB_MAX_XS * 100 / BPB_BONUS_PERCENT;
/* Share rate is scaled to increase precision */
uint256 internal constant CD_RATE_SCALE = 1e5;
/* Share rate max (after scaling) */
uint256 internal constant CD_RATE_UINT_SIZE = 40;
uint256 internal constant CD_RATE_MAX = (1 << CD_RATE_UINT_SIZE) - 1;
/* Globals expanded for memory (except _latestStakeId) and compact for storage */
struct GlobalsCache {
// 1
uint256 _lockedXsTotal;
uint256 _nextStakeSharesTotal;
uint256 _cdRate;
uint256 _stakePenaltyTotal;
// 2
uint256 _dailyDataCount;
uint256 _stakeSharesTotal;
uint40 _latestStakeId;
//
uint256 _currentDay;
}
struct GlobalsStore {
// 1
uint72 lockedXsTotal;
uint72 nextStakeSharesTotal;
uint40 cdRate;
uint72 stakePenaltyTotal;
// 2
uint16 dailyDataCount;
uint72 stakeSharesTotal;
uint40 latestStakeId;
}
GlobalsStore public globals;
/* Daily data */
struct DailyDataStore {
uint72 dayPayoutTotal;
uint72 dayStakeSharesTotal;
uint56 dayUnclaimedSatoshisTotal;
}
mapping(uint256 => DailyDataStore) public dailyData;
/* Stake expanded for memory (except _stakeId) and compact for storage */
struct StakeCache {
uint40 _stakeId;
uint256 _stakedXs;
uint256 _stakeShares;
uint256 _lockedDay;
uint256 _stakedDays;
uint256 _unlockedDay;
}
struct StakeStore {
uint40 stakeId;
uint72 stakedXs;
uint72 stakeShares;
uint16 lockedDay;
uint16 stakedDays;
uint16 unlockedDay;
}
mapping(address => StakeStore[]) public stakeLists;
/* Temporary state for calculating daily rounds */
struct DailyRoundState {
uint256 _allocSupplyCached;
uint256 _mintOriginBatch;
uint256 _payoutTotal;
}
/**
* @dev PUBLIC FACING: Optionally update daily data for a smaller
* range to reduce gas cost for a subsequent operation
* @param beforeDay Only update days before this day number (optional; 0 for current day)
*/
function dailyDataUpdate(uint256 beforeDay) external
{
GlobalsCache memory g;
GlobalsCache memory gSnapshot;
_globalsLoad(g, gSnapshot);
if (beforeDay != 0) {
require(beforeDay <= g._currentDay, "beforeDay cannot be in the future");
_dailyDataUpdate(g, beforeDay, false);
} else {
/* Default to updating before current day */
_dailyDataUpdate(g, g._currentDay, false);
}
_globalsSync(g, gSnapshot);
}
/**
* @dev PUBLIC FACING: Helper to return multiple values of daily data with a single call.
* @param beginDay First day of data range
* @param endDay Last day (non-inclusive) of data range
* @return list Fixed array of packed values
*/
function dailyDataRange(uint256 beginDay, uint256 endDay) external view returns (uint256[] memory list)
{
require(beginDay < endDay && endDay <= globals.dailyDataCount, "range invalid");
list = new uint256[](endDay - beginDay);
uint256 src = beginDay;
uint256 dst = 0;
uint256 v;
do {
v = uint256(dailyData[src].dayUnclaimedSatoshisTotal) << (X_UINT_SIZE * 2);
v |= uint256(dailyData[src].dayStakeSharesTotal) << X_UINT_SIZE;
v |= uint256(dailyData[src].dayPayoutTotal);
list[dst++] = v;
}
while (++src < endDay);
return list;
}
/**
* @dev PUBLIC FACING: External helper to return most global info with a single call.
* @return Fixed array of values
*/
function globalInfo() external view returns (uint256[9] memory) {
return [
// 1
globals.lockedXsTotal,
globals.nextStakeSharesTotal,
globals.cdRate,
globals.stakePenaltyTotal,
// 2
globals.dailyDataCount,
globals.stakeSharesTotal,
globals.latestStakeId,
block.timestamp,
bankXContract.totalSupply() / 1e10
];
}
/**
* @dev PUBLIC FACING: ERC20 totalSupply() is the circulating supply and does not include any
* staked Xs. allocatedSupply() includes both.
* @return Allocated Supply in Xs
*/
function allocatedSupply() external view returns (uint256){
return bankXContract.totalSupply() / 1e10 + collateralPoolContract.bankx_minted_count() / 1e10 + globals.lockedXsTotal;
}
/**
* @dev PUBLIC FACING: External helper for the current day number since launch time
* @return Current day number (zero-based)
*/
function currentDay() external view returns (uint256) {
return _currentDay();
}
function _currentDay() internal view returns (uint256) {
return (block.timestamp - launchTime) / 1 days;
}
function _dailyDataUpdateAuto(GlobalsCache memory g) internal {
_dailyDataUpdate(g, g._currentDay, true);
}
function _globalsLoad(GlobalsCache memory g, GlobalsCache memory gSnapshot) internal view {
// 1
g._lockedXsTotal = globals.lockedXsTotal;
g._nextStakeSharesTotal = globals.nextStakeSharesTotal;
g._cdRate = globals.cdRate;
g._stakePenaltyTotal = globals.stakePenaltyTotal;
// 2
g._dailyDataCount = globals.dailyDataCount;
g._stakeSharesTotal = globals.stakeSharesTotal;
g._latestStakeId = globals.latestStakeId;
g._currentDay = _currentDay();
_globalsCacheSnapshot(g, gSnapshot);
}
function _globalsCacheSnapshot(GlobalsCache memory g, GlobalsCache memory gSnapshot) internal pure
{
// 1
gSnapshot._lockedXsTotal = g._lockedXsTotal;
gSnapshot._nextStakeSharesTotal = g._nextStakeSharesTotal;
gSnapshot._cdRate = g._cdRate;
gSnapshot._stakePenaltyTotal = g._stakePenaltyTotal;
// 2
gSnapshot._dailyDataCount = g._dailyDataCount;
gSnapshot._stakeSharesTotal = g._stakeSharesTotal;
gSnapshot._latestStakeId = g._latestStakeId;
}
function _globalsSync(GlobalsCache memory g, GlobalsCache memory gSnapshot) internal {
if (g._lockedXsTotal != gSnapshot._lockedXsTotal
|| g._nextStakeSharesTotal != gSnapshot._nextStakeSharesTotal
|| g._cdRate != gSnapshot._cdRate
|| g._stakePenaltyTotal != gSnapshot._stakePenaltyTotal) {
// 1
globals.lockedXsTotal = uint72(g._lockedXsTotal);
globals.nextStakeSharesTotal = uint72(g._nextStakeSharesTotal);
globals.cdRate = uint40(g._cdRate);
globals.stakePenaltyTotal = uint72(g._stakePenaltyTotal);
}
if (g._dailyDataCount != gSnapshot._dailyDataCount
|| g._stakeSharesTotal != gSnapshot._stakeSharesTotal
|| g._latestStakeId != gSnapshot._latestStakeId) {
// 2
globals.dailyDataCount = uint16(g._dailyDataCount);
globals.stakeSharesTotal = uint72(g._stakeSharesTotal);
globals.latestStakeId = g._latestStakeId;
}
}
function _stakeLoad(StakeStore storage stRef, uint40 stakeIdParam, StakeCache memory st) internal view
{
/* Ensure caller's stakeIndex is still current */
require(stakeIdParam == stRef.stakeId, "stakeIdParam not in stake");
st._stakeId = stRef.stakeId;
st._stakedXs = stRef.stakedXs;
st._stakeShares = stRef.stakeShares;
st._lockedDay = stRef.lockedDay;
st._stakedDays = stRef.stakedDays;
st._unlockedDay = stRef.unlockedDay;
}
function _stakeUpdate(StakeStore storage stRef, StakeCache memory st) internal
{
stRef.stakeId = st._stakeId;
stRef.stakedXs = uint72(st._stakedXs);
stRef.stakeShares = uint72(st._stakeShares);
stRef.lockedDay = uint16(st._lockedDay);
stRef.stakedDays = uint16(st._stakedDays);
stRef.unlockedDay = uint16(st._unlockedDay);
}
function _stakeAdd(
StakeStore[] storage stakeListRef,
uint40 newStakeId,
uint256 newStakedXs,
uint256 newStakeShares,
uint256 newLockedDay,
uint256 newStakedDays
)
internal
{
stakeListRef.push(
StakeStore(
newStakeId,
uint72(newStakedXs),
uint72(newStakeShares),
uint16(newLockedDay),
uint16(newStakedDays),
uint16(0) // unlockedDay
)
);
}
/**
* @dev Efficiently delete from an unordered array by moving the last element
* to the "hole" and reducing the array length. Can change the order of the list
* and invalidate previously held indexes.
* @notice stakeListRef length and stakeIndex are already ensured valid in stakeEnd()
* @param stakeListRef Reference to stakeLists[stakerAddr] array in storage
* @param stakeIndex Index of the element to delete
*/
function _stakeRemove(StakeStore[] storage stakeListRef, uint256 stakeIndex) internal
{
uint256 lastIndex = stakeListRef.length - 1;
/* Skip the copy if element to be removed is already the last element */
if (stakeIndex != lastIndex) {
/* Copy last element to the requested element's "hole" */
stakeListRef[stakeIndex] = stakeListRef[lastIndex];
}
/*
Reduce the array length now that the array is contiguous.
Surprisingly, 'pop()' uses less gas than 'stakeListRef.length = lastIndex'
*/
stakeListRef.pop();
}
/**
* @dev Estimate the stake payout for an incomplete day
* @param g Cache of stored globals
* @param stakeSharesParam Param from stake to calculate bonuses for
* @param day Day to calculate bonuses for
* @return payout Payout in Xs
*/
function _estimatePayoutRewardsDay(GlobalsCache memory g, uint256 stakeSharesParam, uint256 day)
internal view returns (uint256 payout)
{
/* Prevent updating state for this estimation */
GlobalsCache memory gTmp;
_globalsCacheSnapshot(g, gTmp);
DailyRoundState memory rs;
rs._allocSupplyCached = bankXContract.totalSupply() / 1e10 + g._lockedXsTotal;
_dailyRoundCalc(gTmp, rs, day);
/* Stake is no longer locked so it must be added to total as if it were */
gTmp._stakeSharesTotal += stakeSharesParam;
payout = rs._payoutTotal * stakeSharesParam / gTmp._stakeSharesTotal;
return payout;
}
function _dailyRoundCalc(GlobalsCache memory g, DailyRoundState memory rs, uint256 day) private pure
{
/*
Calculate payout round
Inflation of 5.28% inflation per 364 days (approx 1 year)
dailyInterestRate = exp(log(1 + 5.28%) / 364) - 1
= exp(log(1 + 0.0528) / 364) - 1
= exp(log(1.0528) / 364) - 1
= 0.000141365 (approx)
payout = allocSupply * dailyInterestRate
= allocSupply / (1 / dailyInterestRate)
= allocSupply / (1 / 0.000141365)
= allocSupply / 7073.88674707 (approx)
= allocSupply * 10000 / 70738867 (* 10000/10000 for int precision)
*/
rs._payoutTotal = rs._allocSupplyCached * 10000 / 70738867;
if (g._stakePenaltyTotal != 0) {
rs._payoutTotal += g._stakePenaltyTotal;
g._stakePenaltyTotal = 0;
}
}
function _dailyRoundCalcAndStore(GlobalsCache memory g, DailyRoundState memory rs, uint256 day) private
{
_dailyRoundCalc(g, rs, day);
dailyData[day].dayPayoutTotal = uint72(rs._payoutTotal);
dailyData[day].dayStakeSharesTotal = uint72(g._stakeSharesTotal);
}
function _dailyDataUpdate(GlobalsCache memory g, uint256 beforeDay, bool isAutoUpdate) private
{
if (g._dailyDataCount >= beforeDay) {
/* Already up-to-date */
return;
}
DailyRoundState memory rs;
rs._allocSupplyCached = bankXContract.totalSupply() / 1e10 + g._lockedXsTotal;
uint256 day = g._dailyDataCount;
_dailyRoundCalcAndStore(g, rs, day);
/* Stakes started during this day are added to the total the next day */
if (g._nextStakeSharesTotal != 0) {
g._stakeSharesTotal += g._nextStakeSharesTotal;
g._nextStakeSharesTotal = 0;
}
while (++day < beforeDay) {
_dailyRoundCalcAndStore(g, rs, day);
}
_emitDailyDataUpdate(g._dailyDataCount, day, isAutoUpdate);
g._dailyDataCount = day;
if (rs._mintOriginBatch != 0) {
bankXContract.pool_mint(ORIGIN_ADDR, rs._mintOriginBatch * 1e10);
}
}
function _emitDailyDataUpdate(uint256 beginDay, uint256 endDay, bool isAutoUpdate) private
{
emit DailyDataUpdate(
uint256(uint40(block.timestamp))
| (uint256(uint16(beginDay)) << 40)
| (uint256(uint16(endDay)) << 56)
| (isAutoUpdate ? (1 << 72) : 0),
msg.sender
);
}
function updateBankXContract(address _bankXContract) public onlyOwner() {
bankXContract = BankXInterface(_bankXContract);
}
function updateNFTBonusContract(address _nftBonusContract) public onlyOwner() {
nftBonusContract = NFTBonusInterface(_nftBonusContract);
}
function updateCollateralPoolContract(address _collateralPoolContract) public onlyOwner() {
collateralPoolContract = CollateralPoolInterface(_collateralPoolContract);
}
}
// File: contracts/CD.sol
//BBBBBBBBBBBBBBBBB kkkkkkkk XXXXXXX XXXXXXX
//B::::::::::::::::B k::::::k X:::::X X:::::X
//B::::::BBBBBB:::::B k::::::k X:::::X X:::::X
//BB:::::B B:::::B k::::::k X::::::X X::::::X
// B::::B B:::::B aaaaaaaaaaaaa nnnn nnnnnnnn k:::::k kkkkkkk XXX:::::X X:::::XXX
// B::::B B:::::B a::::::::::::a n:::nn::::::::nn k:::::k k:::::k X:::::X X:::::X
// B::::BBBBBB:::::B aaaaaaaaa:::::a n::::::::::::::nn k:::::k k:::::k X:::::X:::::X
// B:::::::::::::BB a::::a nn:::::::::::::::n k:::::k k:::::k X:::::::::X
// B::::BBBBBB:::::B aaaaaaa:::::a n:::::nnnn:::::n k::::::k:::::k X:::::::::X
// B::::B B:::::B aa::::::::::::a n::::n n::::n k:::::::::::k X:::::X:::::X
// B::::B B:::::B a::::aaaa::::::a n::::n n::::n k:::::::::::k X:::::X X:::::X
// B::::B B:::::B a::::a a:::::a n::::n n::::n k::::::k:::::k XXX:::::X X:::::XXX
//BB:::::BBBBBB::::::B a::::a a:::::a n::::n n::::n k::::::k k:::::k X::::::X X::::::X
//B:::::::::::::::::B a:::::aaaa::::::a n::::n n::::n k::::::k k:::::k X:::::X X:::::X
//B::::::::::::::::B a::::::::::aa:::a n::::n n::::n k::::::k k:::::k X:::::X X:::::X
//BBBBBBBBBBBBBBBBB aaaaaaaaaa aaaa nnnnnn nnnnnn kkkkkkkk kkkkkkk XXXXXXX XXXXXXX
//
//Currency Creators Manifesto
//
//Our world faces an urgent crisis of currency manipulation, theft and inflation. Under the current system,
// currency is controlled by and benefits elite families, governments and large banking institutions. We believe
// currencies should be minted by and benefit the individual, not the establishment. It is time to take back the
// control of and the freedom that money can provide.
//
//BankX is rebuilding the legacy banking system from the ground up by providing you with the capability to create
// currency and be in complete control of wealth creation with a concept we call ‘Individual Created Digital Currency’
// (ICDC). You own the collateral. You mint currency. You earn interest. You leverage without the risk of liquidation.
// You stake to earn even more returns. All of this is done with complete autonomy and decentralization. BankX has
// built a stablecoin for Individual Freedom.
//
//BankX is the antidote for the malevolent financial system bringing in a new future of freedom where you are in
// complete control with no middlemen, bank or central bank between you and your finances. This capability to create
// currency and be in complete control of wealth creation will be in the hands of every individual that uses BankX.
//
//By 2030, we will rid the world of the corrupt, tyrannical and incompetent banking system replacing it with a system
// where billions of people will be in complete control of their financial future. Everyone will be given ultimate
// freedom to use their assets to create currency, earn interest and multiply returns to accomplish their individual
// goals. The mission of BankX is to be the first to mint $1 trillion in stablecoin.
//
//We will bring about this transformation by attracting people that believe what we believe. We will partner with
// other blockchain protocols and build decentralized applications that drive even more usage. Finally, we will deploy
// a private network that is never connected to the Internet to communicate between counterparties, that allows for
// blockchain-to-blockchain interoperability and stores private keys and cryptocurrency wallets. Our ecosystem,
// network and platform has never been seen in the market and provides us with a long term sustainable competitive advantage.
//
//We value individual freedom.
//We believe in financial autonomy.
//We are anti-establishment.
//We envision a future of self-empowerment.
pragma solidity 0.8.16;
//import "hardhat/console.sol";
contract CD is GlobalsAndStats {
bool public initiated;
function init() external {
require(initiated == false, "initiated");
_transferOwnership(_msgSender());
/* Initialize global cdRate to 1 */
globals.cdRate = uint40(1 * CD_RATE_SCALE);
globals.dailyDataCount = 1;
launchTime = block.timestamp;
LPBBonusPercent = 20;
LPB = 364 * 100 / LPBBonusPercent; // 1820
initiated = true;
}
/**
* @dev PUBLIC FACING: Open a stake.
* @param newStakedXs Number of Xs to stake
* @param newStakedDays Number of days to stake
*/
function stakeStart(uint256 newStakedXs, uint256 newStakedDays) external
{
GlobalsCache memory g;
GlobalsCache memory gSnapshot;
_globalsLoad(g, gSnapshot);
updateLPB();
/* Enforce the minimum stake time */
require(newStakedDays >= MIN_STAKE_DAYS, "newStakedDays low");
/* Check if log data needs to be updated */
_dailyDataUpdateAuto(g);
_stakeStart(g, newStakedXs, newStakedDays);
/* Remove staked Xs from balance of staker */
bankXContract.pool_burn_from(msg.sender, newStakedXs * 1e10);
_globalsSync(g, gSnapshot);
}
/**
* @dev PUBLIC FACING: Unlocks a completed stake, distributing the proceeds of any penalty
* immediately. The staker must still call stakeEnd() to retrieve their stake return (if any).
* @param stakerAddr Address of staker
* @param stakeIndex Index of stake within stake list
* @param stakeIdParam The stake's id
*/
function stakeGoodAccounting(address stakerAddr, uint256 stakeIndex, uint40 stakeIdParam)
external
{
GlobalsCache memory g;
GlobalsCache memory gSnapshot;
_globalsLoad(g, gSnapshot);
require(stakeLists[stakerAddr].length != 0, "empty stake list");
require(stakeIndex < stakeLists[stakerAddr].length, "stakeIndex invalid");
StakeStore storage stRef = stakeLists[stakerAddr][stakeIndex];
/* Get stake copy */
StakeCache memory st;
_stakeLoad(stRef, stakeIdParam, st);
/* Stake must have served full term */
require(g._currentDay >= st._lockedDay + st._stakedDays, "Stake not fully served");
/* Stake must still be locked */
require(st._unlockedDay == 0, "Stake already unlocked");
/* Check if log data needs to be updated */
_dailyDataUpdateAuto(g);
/* Unlock the completed stake */
_stakeUnlock(g, st);
/* stakeReturn value is unused here */
(, uint256 payout, uint256 penalty, uint256 cappedPenalty) = _stakePerformance(
g,
st,
st._stakedDays
);
_emitStakeGoodAccounting(
stakerAddr,
stakeIdParam,
st._stakedXs,
st._stakeShares,
payout,
penalty
);
if (cappedPenalty != 0) {
_splitPenaltyProceeds(g, cappedPenalty);
}
/* st._unlockedDay has changed */
_stakeUpdate(stRef, st);
_globalsSync(g, gSnapshot);
}
/**
* @dev PUBLIC FACING: Closes a stake. The order of the stake list can change so
* a stake id is used to reject stale indexes.
* @param stakeIndex Index of stake within stake list
* @param stakeId The stake's id
*/
function stakeEnd(uint256 stakeIndex, uint40 stakeId) external {
GlobalsCache memory g;
GlobalsCache memory gSnapshot;
_globalsLoad(g, gSnapshot);
updateLPB();
StakeStore[] storage stakeListRef = stakeLists[msg.sender];
require(stakeListRef.length != 0, "empty stake list");
require(stakeIndex < stakeListRef.length, "stakeIndex invalid");
/* Get stake copy */
StakeCache memory st;
_stakeLoad(stakeListRef[stakeIndex], stakeId, st);
/* Check if log data needs to be updated */
_dailyDataUpdateAuto(g);
uint256 servedDays = 0;
bool prevUnlocked = (st._unlockedDay != 0);
uint256 stakeReturn;
uint256 payout = 0;
uint256 penalty = 0;
uint256 cappedPenalty = 0;
if (g._currentDay >= st._lockedDay) {
if (prevUnlocked) {
/* Previously unlocked in stakeGoodAccounting(), so must have served full term */
servedDays = st._stakedDays;
} else {
_stakeUnlock(g, st);
servedDays = g._currentDay - st._lockedDay;
if (servedDays > st._stakedDays) {
servedDays = st._stakedDays;
}
}
(stakeReturn, payout, penalty, cappedPenalty) = _stakePerformance(g, st, servedDays);
} else {
/* Stake hasn't been added to the total yet, so no penalties or rewards apply */
g._nextStakeSharesTotal -= st._stakeShares;
stakeReturn = st._stakedXs;
}
_emitStakeEnd(
stakeId,
st._stakedXs,
st._stakeShares,
payout,
penalty,
servedDays,
prevUnlocked
);
if (cappedPenalty != 0 && !prevUnlocked) {
/* Split penalty proceeds only if not previously unlocked by stakeGoodAccounting() */
_splitPenaltyProceeds(g, cappedPenalty);
}
/* Pay the stake return, if any, to the staker */
if (stakeReturn != 0) {
bankXContract.pool_mint(msg.sender, stakeReturn * 1e10);
/* Update the share rate if necessary */
_cdRateUpdate(g, st, stakeReturn);
}
g._lockedXsTotal -= st._stakedXs;
nftBonusContract.stakeEnd(msg.sender, stakeId);
_stakeRemove(stakeListRef, stakeIndex);
_globalsSync(g, gSnapshot);
}
/**
* @dev PUBLIC FACING: Return the current stake count for a staker address
* @param stakerAddr Address of staker
*/
function stakeCount(address stakerAddr) external view returns (uint256)
{
return stakeLists[stakerAddr].length;
}
/**
* @dev Open a stake.
* @param g Cache of stored globals
* @param newStakedXs Number of Xs to stake
* @param newStakedDays Number of days to stake
*/
function _stakeStart(GlobalsCache memory g, uint256 newStakedXs, uint256 newStakedDays) internal
{
/* Enforce the maximum stake time */
require(newStakedDays <= MAX_STAKE_DAYS, "newStakedDays high");
uint40 newStakeId = ++g._latestStakeId;
nftBonusContract.assignStakeId(msg.sender, newStakeId);
uint256 bonusXs = _stakeStartBonusXs(newStakedXs, newStakedDays, newStakeId);
uint256 newStakeShares = (newStakedXs + bonusXs) * CD_RATE_SCALE / g._cdRate;
// console.log("bonusXs", bonusXs);
// console.log("newStakedXs", newStakedXs);
// console.log("newStakeShares", newStakeShares);
/* Ensure newStakedXs is enough for at least one stake share */
require(newStakeShares != 0, "newStakedXs must be >= min cdRate");
/*
The stakeStart timestamp will always be part-way through the current
day, so it needs to be rounded-up to the next day to ensure all
stakes align with the same fixed calendar days. The current day is
already rounded-down, so rounded-up is current day + 1.
*/
uint256 newLockedDay = g._currentDay + 1;
/* Create Stake */
_stakeAdd(
stakeLists[msg.sender],
newStakeId,
newStakedXs,
newStakeShares,
newLockedDay,
newStakedDays
);
_emitStakeStart(newStakeId, newStakedXs, newStakeShares, newStakedDays);
/* Stake is added to total in the next round, not the current round */
g._nextStakeSharesTotal += newStakeShares;
/* Track total staked Xs for inflation calculations */
g._lockedXsTotal += newStakedXs;
}
/**
* @dev Calculates total stake payout including rewards for a multi-day range
* @param stakeSharesParam Param from stake to calculate bonuses for
* @param beginDay First day to calculate bonuses for
* @param endDay Last day (non-inclusive) of range to calculate bonuses for
* @return payout Payout in Xs
*/
function _calcPayoutRewards(uint256 stakeSharesParam, uint256 beginDay, uint256 endDay)
private view returns (uint256 payout)
{
for (uint256 day = beginDay; day < endDay; day++) {
payout += dailyData[day].dayPayoutTotal * stakeSharesParam
/ dailyData[day].dayStakeSharesTotal;
}
return payout;
}
/**
* @dev Calculate bonus Xs for a new stake, if any
* @param newStakedXs Number of Xs to stake
* @param newStakedDays Number of days to stake
*/
function _stakeStartBonusXs(uint256 newStakedXs, uint256 newStakedDays, uint40 newStakeId) private view returns (uint256 bonusXs)
{
/*
LONGER PAYS BETTER:
If longer than 1 day stake is committed to, each extra day
gives bonus shares of approximately 0.0548%, which is approximately 20%
extra per year of increased stake length committed to, but capped to a
maximum of 200% extra.
extraDays = stakedDays - 1
longerBonus% = (extraDays / 364) * 33.33%
= (extraDays / 364) / 3
= extraDays / 1092
= extraDays / LPB
extraDays = longerBonus% * 1092
extraDaysMax = longerBonusMax% * 1092
= 200% * 1092
= 2184
= LPB_MAX_DAYS
BIGGER PAYS BETTER:
Bonus percentage scaled 0% to 10% for the first 150M BankX of stake.
biggerBonus% = (cappedXs / BPB_MAX_XS) * 10%
= (cappedXs / BPB_MAX_XS) / 10
= cappedXs / (BPB_MAX_XS * 10)
= cappedXs / BPB
COMBINED:
combinedBonus% = longerBonus% + biggerBonus%
cappedExtraDays cappedXs
= --------------- + ------------
LPB BPB
cappedExtraDays * BPB cappedXs * LPB
= --------------------- + ------------------
LPB * BPB LPB * BPB
cappedExtraDays * BPB + cappedXs * LPB
= --------------------------------------------
LPB * BPB
bonusXs = Xs * combinedBonus%
= Xs * (cappedExtraDays * BPB + cappedXs * LPB) / (LPB * BPB)
*/
uint256 cappedExtraDays = 0;
/* Must be more than 1 day for Longer-Pays-Better */
if (newStakedDays > 1) {
cappedExtraDays = newStakedDays <= LPB_MAX_DAYS ? newStakedDays - 1 : LPB_MAX_DAYS;
}
uint256 cappedStakedXs = newStakedXs <= BPB_MAX_XS ? newStakedXs : BPB_MAX_XS;
// console.log("newStakedXs", newStakedXs);
// console.log("cappedStakedXs", cappedStakedXs);
bonusXs = cappedExtraDays * BPB + cappedStakedXs * LPB;
// console.log("LPB", LPB);
// console.log("cappedStakedXs * LPB", cappedStakedXs * LPB);
// console.log("BPB", BPB);
// console.log("cappedExtraDays * BPB", cappedExtraDays * BPB);
// console.log("cappedExtraDays * BPB + cappedStakedXs * LPB", bonusXs);
bonusXs = newStakedXs * bonusXs / (LPB * BPB);
// console.log("newStakedXs * bonusXs / (LPB * BPB)", bonusXs);
return bonusXs + bonusXs * nftBonusContract.getNftsCount(newStakeId) / 10;
}
function updateLPB() public {
bool lastUpdatedWeekAgo = (block.timestamp - LPBLastUpdated) >= 7 days;
bool positiveInflation = bankXContract.totalSupply() > bankXContract.genesis_supply();
if (positiveInflation && LPBBonusPercent < 40 && lastUpdatedWeekAgo) {
LPBBonusPercent = LPBBonusPercent + 5;
LPBLastUpdated = block.timestamp;
}
else if (!positiveInflation && LPBBonusPercent > 20) {
LPBBonusPercent = 20;
LPBLastUpdated = block.timestamp;
}
LPB = 36400 / LPBBonusPercent;
}
function _stakeUnlock(GlobalsCache memory g, StakeCache memory st) private pure {
g._stakeSharesTotal -= st._stakeShares;
st._unlockedDay = g._currentDay;
}
function _stakePerformance(GlobalsCache memory g, StakeCache memory st, uint256 servedDays) private view
returns (uint256 stakeReturn, uint256 payout, uint256 penalty, uint256 cappedPenalty){
if (servedDays < st._stakedDays) {
(payout, penalty) = _calcPayoutAndEarlyPenalty(
g,
st._lockedDay,
st._stakedDays,
servedDays,
st._stakeShares
);
stakeReturn = st._stakedXs + payout;
} else {
// servedDays must == stakedDays here
payout = _calcPayoutRewards(
st._stakeShares,
st._lockedDay,
st._lockedDay + servedDays
);
stakeReturn = st._stakedXs + payout;
penalty = _calcLatePenalty(st._lockedDay, st._stakedDays, st._unlockedDay, stakeReturn);
}
if (penalty != 0) {
if (penalty > stakeReturn) {
/* Cannot have a negative stake return */
cappedPenalty = stakeReturn;
stakeReturn = 0;
} else {
/* Remove penalty from the stake return */
cappedPenalty = penalty;
stakeReturn -= cappedPenalty;
}
}
return (stakeReturn, payout, penalty, cappedPenalty);
}
function _calcPayoutAndEarlyPenalty(GlobalsCache memory g, uint256 lockedDay, uint256 stakedDays, uint256 servedDays, uint256 stakeShares)
private view returns (uint256 payout, uint256 penalty) {
uint256 servedEndDay = lockedDay + servedDays;
/* 50% of stakedDays (rounded up) with a minimum applied */
uint256 penaltyDays = (stakedDays + 1) / 2;
if (penaltyDays < EARLY_PENALTY_MIN_DAYS) {
penaltyDays = EARLY_PENALTY_MIN_DAYS;
}
if (servedDays == 0) {
/* Fill penalty days with the estimated average payout */
uint256 expected = _estimatePayoutRewardsDay(g, stakeShares, lockedDay);
penalty = expected * penaltyDays;
return (payout, penalty);
// Actual payout was 0
}
if (penaltyDays < servedDays) {
/*
Simplified explanation of intervals where end-day is non-inclusive:
penalty: [lockedDay ... penaltyEndDay)
delta: [penaltyEndDay ... servedEndDay)
payout: [lockedDay ....................... servedEndDay)
*/
uint256 penaltyEndDay = lockedDay + penaltyDays;
penalty = _calcPayoutRewards(stakeShares, lockedDay, penaltyEndDay);
uint256 delta = _calcPayoutRewards(stakeShares, penaltyEndDay, servedEndDay);
payout = penalty + delta;
return (payout, penalty);
}
/* penaltyDays >= servedDays */
payout = _calcPayoutRewards(stakeShares, lockedDay, servedEndDay);
if (penaltyDays == servedDays) {
penalty = payout;
} else {
/*
(penaltyDays > servedDays) means not enough days served, so fill the
penalty days with the average payout from only the days that were served.
*/
penalty = payout * penaltyDays / servedDays;
if (LPBBonusPercent > 20) {
penalty += calculateLPBPenalty(payout, stakedDays, servedDays);
}
}
return (payout, penalty);
}
function calculateLPBPenalty(uint payout, uint stakedDays, uint servedDays) public view returns (uint) {
return payout * (((LPBBonusPercent - 20) * (stakedDays - servedDays)) / 10) * 11;
}
function _calcLatePenalty(uint256 lockedDay, uint256 stakedDays, uint256 unlockedDay, uint256 rawStakeReturn)
private pure returns (uint256){
/* Allow grace time before penalties accrue */
uint256 maxUnlockedDay = lockedDay + stakedDays + LATE_PENALTY_GRACE_DAYS;
if (unlockedDay <= maxUnlockedDay) {
return 0;
}
/* Calculate penalty as a percentage of stake return based on time */
return rawStakeReturn * (unlockedDay - maxUnlockedDay) / LATE_PENALTY_SCALE_DAYS;
}
function _splitPenaltyProceeds(GlobalsCache memory g, uint256 penalty) private
{
/* Split a penalty 50:50 between Origin and stakePenaltyTotal */
uint256 splitPenalty = penalty / 2;
if (splitPenalty != 0) {
bankXContract.pool_mint(ORIGIN_ADDR, splitPenalty * 1e10);
}
/* Use the other half of the penalty to account for an odd-numbered penalty */
splitPenalty = penalty - splitPenalty;
g._stakePenaltyTotal += splitPenalty;
}
function _cdRateUpdate(GlobalsCache memory g, StakeCache memory st, uint256 stakeReturn) private
{
if (stakeReturn > st._stakedXs) {
/*
Calculate the new cdRate that would yield the same number of shares if
the user re-staked this stakeReturn, factoring in any bonuses they would
receive in stakeStart().
*/
uint256 bonusXs = _stakeStartBonusXs(stakeReturn, st._stakedDays, st._stakeId);
uint256 newCDRate = (stakeReturn + bonusXs) * CD_RATE_SCALE / st._stakeShares;
// Realistically this can't happen, but capped to prevent anyway.
if (newCDRate > CD_RATE_MAX) {
newCDRate = CD_RATE_MAX;
}
if (newCDRate > g._cdRate) {
g._cdRate = newCDRate;
_emitCDRateChange(newCDRate, st._stakeId);
}
}
}
function _emitStakeStart(uint40 stakeId, uint256 stakedXs, uint256 stakeShares, uint256 stakedDays) private
{
emit StakeStart(
uint256(uint40(block.timestamp))
| (uint256(uint72(stakedXs)) << 40)
| (uint256(uint72(stakeShares)) << 112)
| (uint256(uint16(stakedDays)) << 184)
| 0,
msg.sender,
stakeId
);
}
function _emitStakeGoodAccounting(
address stakerAddr,
uint40 stakeId,
uint256 stakedXs,
uint256 stakeShares,
uint256 payout,
uint256 penalty
)
private
{
emit StakeGoodAccounting(
uint256(uint40(block.timestamp))
| (uint256(uint72(stakedXs)) << 40)
| (uint256(uint72(stakeShares)) << 112)
| (uint256(uint72(payout)) << 184),
uint256(uint72(penalty)),
stakerAddr,
stakeId,
msg.sender
);
}
function _emitStakeEnd(
uint40 stakeId,
uint256 stakedXs,
uint256 stakeShares,
uint256 payout,
uint256 penalty,
uint256 servedDays,
bool prevUnlocked
)
private
{
emit StakeEnd(
uint256(uint40(block.timestamp))
| (uint256(uint72(stakedXs)) << 40)
| (uint256(uint72(stakeShares)) << 112)
| (uint256(uint72(payout)) << 184),
uint256(uint72(penalty))
| (uint256(uint16(servedDays)) << 72)
| (prevUnlocked ? (1 << 88) : 0),
msg.sender,
stakeId
);
}
function _emitCDRateChange(uint256 cdRate, uint40 stakeId)
private
{
emit CDRateChange(
uint256(uint40(block.timestamp))
| (uint256(uint40(cdRate)) << 40),
stakeId
);
}
}
Contract ABI
[{"type":"event","name":"CDRateChange","inputs":[{"type":"uint256","name":"data0","internalType":"uint256","indexed":false},{"type":"uint40","name":"stakeId","internalType":"uint40","indexed":true}],"anonymous":false},{"type":"event","name":"DailyDataUpdate","inputs":[{"type":"uint256","name":"data0","internalType":"uint256","indexed":false},{"type":"address","name":"updaterAddr","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"StakeEnd","inputs":[{"type":"uint256","name":"data0","internalType":"uint256","indexed":false},{"type":"uint256","name":"data1","internalType":"uint256","indexed":false},{"type":"address","name":"stakerAddr","internalType":"address","indexed":true},{"type":"uint40","name":"stakeId","internalType":"uint40","indexed":true}],"anonymous":false},{"type":"event","name":"StakeGoodAccounting","inputs":[{"type":"uint256","name":"data0","internalType":"uint256","indexed":false},{"type":"uint256","name":"data1","internalType":"uint256","indexed":false},{"type":"address","name":"stakerAddr","internalType":"address","indexed":true},{"type":"uint40","name":"stakeId","internalType":"uint40","indexed":true},{"type":"address","name":"senderAddr","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"StakeStart","inputs":[{"type":"uint256","name":"data0","internalType":"uint256","indexed":false},{"type":"address","name":"stakerAddr","internalType":"address","indexed":true},{"type":"uint40","name":"stakeId","internalType":"uint40","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"LPB","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"LPBBonusPercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"LPBLastUpdated","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"LPB_MAX_DAYS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allocatedSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract BankXInterface"}],"name":"bankXContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"calculateLPBPenalty","inputs":[{"type":"uint256","name":"payout","internalType":"uint256"},{"type":"uint256","name":"stakedDays","internalType":"uint256"},{"type":"uint256","name":"servedDays","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract CollateralPoolInterface"}],"name":"collateralPoolContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentDay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint72","name":"dayPayoutTotal","internalType":"uint72"},{"type":"uint72","name":"dayStakeSharesTotal","internalType":"uint72"},{"type":"uint56","name":"dayUnclaimedSatoshisTotal","internalType":"uint56"}],"name":"dailyData","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"list","internalType":"uint256[]"}],"name":"dailyDataRange","inputs":[{"type":"uint256","name":"beginDay","internalType":"uint256"},{"type":"uint256","name":"endDay","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"dailyDataUpdate","inputs":[{"type":"uint256","name":"beforeDay","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[9]","name":"","internalType":"uint256[9]"}],"name":"globalInfo","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint72","name":"lockedXsTotal","internalType":"uint72"},{"type":"uint72","name":"nextStakeSharesTotal","internalType":"uint72"},{"type":"uint40","name":"cdRate","internalType":"uint40"},{"type":"uint72","name":"stakePenaltyTotal","internalType":"uint72"},{"type":"uint16","name":"dailyDataCount","internalType":"uint16"},{"type":"uint72","name":"stakeSharesTotal","internalType":"uint72"},{"type":"uint40","name":"latestStakeId","internalType":"uint40"}],"name":"globals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"init","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"initiated","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract NFTBonusInterface"}],"name":"nftBonusContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"stakeCount","inputs":[{"type":"address","name":"stakerAddr","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stakeEnd","inputs":[{"type":"uint256","name":"stakeIndex","internalType":"uint256"},{"type":"uint40","name":"stakeId","internalType":"uint40"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stakeGoodAccounting","inputs":[{"type":"address","name":"stakerAddr","internalType":"address"},{"type":"uint256","name":"stakeIndex","internalType":"uint256"},{"type":"uint40","name":"stakeIdParam","internalType":"uint40"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint40","name":"stakeId","internalType":"uint40"},{"type":"uint72","name":"stakedXs","internalType":"uint72"},{"type":"uint72","name":"stakeShares","internalType":"uint72"},{"type":"uint16","name":"lockedDay","internalType":"uint16"},{"type":"uint16","name":"stakedDays","internalType":"uint16"},{"type":"uint16","name":"unlockedDay","internalType":"uint16"}],"name":"stakeLists","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stakeStart","inputs":[{"type":"uint256","name":"newStakedXs","internalType":"uint256"},{"type":"uint256","name":"newStakedDays","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateBankXContract","inputs":[{"type":"address","name":"_bankXContract","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateCollateralPoolContract","inputs":[{"type":"address","name":"_collateralPoolContract","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateLPB","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateNFTBonusContract","inputs":[{"type":"address","name":"_nftBonusContract","internalType":"address"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50612c58806100206000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063715018a6116101045780639f118536116100a2578063f04b5fa011610071578063f04b5fa0146104fe578063f1fcd72714610513578063f2fde38b1461051c578063f9b6baa11461052f57600080fd5b80639f1185361461041f578063c31245251461043c578063cc0911bf146104e3578063e1c7392a146104f657600080fd5b80638f1c65c0116100de5780638f1c65c01461037a57806390adafc71461038d57806390de6871146103a05780639d463cee1461041657600080fd5b8063715018a614610359578063789f07b1146103615780638da5cb5b1461036957600080fd5b80634a144516116101715780635c9302c91161014b5780635c9302c91461030b57806365cf71b2146103135780636a210a0e146103265780636de6e9321461034657600080fd5b80634a144516146102dc5780634e812b30146102ef57806352a438b8146102f857600080fd5b806333060d90116101ad57806333060d901461025f578063343009a2146102965780633a70a5ca146102a957806348f5d087146102b157600080fd5b80632607443b146101d4578063265622c4146102375780632fd9678d1461024c575b600080fd5b6101e76101e2366004612945565b610538565b6040805164ffffffffff90971687526001600160481b039586166020880152949093169385019390935261ffff908116606085015291821660808401521660a082015260c0015b60405180910390f35b61024a61024536600461296f565b6105a9565b005b61024a61025a36600461296f565b6105d3565b61028861026d36600461296f565b6001600160a01b03166000908152600b602052604090205490565b60405190815260200161022e565b61024a6102a43660046129a6565b6105fd565b610288610939565b6002546102c4906001600160a01b031681565b6040516001600160a01b03909116815260200161022e565b6001546102c4906001600160a01b031681565b61028860055481565b61024a6103063660046129d2565b610a5d565b610288610b67565b61024a6103213660046129f4565b610b71565b6103396103343660046129d2565b610e7e565b60405161022e9190612a30565b610288610354366004612a74565b610fc4565b61024a611012565b61024a611026565b6000546001600160a01b03166102c4565b61024a610388366004612aa0565b61119e565b6003546102c4906001600160a01b031681565b6103e76103ae366004612aa0565b600a602052600090815260409020546001600160481b0380821691600160481b810490911690600160901b900466ffffffffffffff1683565b604080516001600160481b03948516815293909216602084015266ffffffffffffff169082015260600161022e565b61028860075481565b600c5461042c9060ff1681565b604051901515815260200161022e565b600854600954610491916001600160481b0380821692600160481b830482169264ffffffffff600160901b8204811693600160b81b90920482169261ffff8116926201000082041691600160581b9091041687565b604080516001600160481b039889168152968816602088015264ffffffffff95861690870152928616606086015261ffff90911660808501529390931660a083015290911660c082015260e00161022e565b61024a6104f136600461296f565b61124c565b61024a611276565b61050661132a565b60405161022e9190612ab9565b610288610e3881565b61024a61052a36600461296f565b611439565b61028860065481565b600b602052816000526040600020818154811061055457600080fd5b60009182526020909120015464ffffffffff811692506001600160481b03600160281b820481169250600160701b8204169061ffff600160b81b8204811691600160c81b8104821691600160d81b9091041686565b6105b16114b2565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6105db6114b2565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6106056128be565b61060d6128be565b6106178282611520565b61061f611026565b336000908152600b6020526040812080549091036106775760405162461bcd60e51b815260206004820152601060248201526f195b5c1d1e481cdd185ad9481b1a5cdd60821b60448201526064015b60405180910390fd5b805485106106bc5760405162461bcd60e51b81526020600482015260126024820152711cdd185ad9525b99195e081a5b9d985b1a5960721b604482015260640161066e565b6106fc6040518060c00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b61072282878154811061071157610711612aeb565b9060005260206000200186836115a4565b61072b84611661565b6000808260a001516000141590506000806000905060008086606001518a60e00151106107b25784156107645786608001519550610798565b61076e8a88611671565b86606001518a60e001516107829190612b17565b9550866080015186111561079857866080015195505b6107a38a8888611698565b929650909450925090506107d3565b86604001518a6020018181516107c89190612b17565b905250602087015193505b6107ea8b8860200151896040015186868b8b61175b565b80158015906107f7575084155b15610806576108068a82611820565b8315610896576001546001600160a01b031663b4f56b263361082d876402540be400612b2a565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561087357600080fd5b505af1158015610887573d6000803e3d6000fd5b505050506108968a88866118ef565b60208701518a518b906108aa908390612b17565b90525060025460405163a9db026960e01b815233600482015264ffffffffff8d1660248201526001600160a01b039091169063a9db026990604401600060405180830381600087803b1580156108ff57600080fd5b505af1158015610913573d6000803e3d6000fd5b50505050610921888d61198e565b61092b8a8a611b03565b505050505050505050505050565b600854600354604080516361bf897b60e11b815290516000936001600160481b0316926402540be400926001600160a01b039091169163c37f12f6916004808201926020929091908290030181865afa15801561099a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109be9190612b49565b6109c89190612b62565b600154604080516318160ddd60e01b815290516402540be400926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa158015610a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3a9190612b49565b610a449190612b62565b610a4e9190612b84565b610a589190612b84565b905090565b610a656128be565b610a6d6128be565b610a778282611520565b610a7f611026565b6001831015610ac45760405162461bcd60e51b81526020600482015260116024820152706e65775374616b656444617973206c6f7760781b604482015260640161066e565b610acd82611661565b610ad8828585611c6d565b6001546001600160a01b031663a8a778ae33610af9876402540be400612b2a565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610b3f57600080fd5b505af1158015610b53573d6000803e3d6000fd5b50505050610b618282611b03565b50505050565b6000610a58611f3e565b610b796128be565b610b816128be565b610b8b8282611520565b6001600160a01b0385166000908152600b60205260408120549003610be55760405162461bcd60e51b815260206004820152601060248201526f195b5c1d1e481cdd185ad9481b1a5cdd60821b604482015260640161066e565b6001600160a01b0385166000908152600b60205260409020548410610c415760405162461bcd60e51b81526020600482015260126024820152711cdd185ad9525b99195e081a5b9d985b1a5960721b604482015260640161066e565b6001600160a01b0385166000908152600b60205260408120805486908110610c6b57610c6b612aeb565b906000526020600020019050610cb76040518060c00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b610cc28286836115a4565b80608001518160600151610cd69190612b84565b8460e001511015610d225760405162461bcd60e51b815260206004820152601660248201527514dd185ad9481b9bdd08199d5b1b1e481cd95c9d995960521b604482015260640161066e565b60a081015115610d6d5760405162461bcd60e51b815260206004820152601660248201527514dd185ad948185b1c9958591e481d5b9b1bd8dad95960521b604482015260640161066e565b610d7684611661565b610d808482611671565b6000806000610d9487858660800151611698565b93509350935050610db18a89866020015187604001518787611f5c565b8015610dc157610dc18782611820565b83518554602086015160408701516060880151608089015160a08a015164ffffffffff9096166001600160701b031990951694909417600160281b6001600160481b039485160217600160701b600160c81b031916600160701b939092169290920261ffff60b81b191617600160b81b61ffff928316021763ffffffff60c81b1916600160c81b9282169290920261ffff60d81b191691909117600160d81b9190921602178555610e728787611b03565b50505050505050505050565b60608183108015610e95575060095461ffff168211155b610ed15760405162461bcd60e51b815260206004820152600d60248201526c1c985b99d9481a5b9d985b1a59609a1b604482015260640161066e565b610edb8383612b17565b67ffffffffffffffff811115610ef357610ef3612b97565b604051908082528060200260200182016040528015610f1c578160200160208202803683370190505b509050826000805b610f3060486002612b2a565b6000848152600a6020526040902054600160901b810466ffffffffffffff1690911b600160481b820460481b71ffffffffffffffffff00000000000000000016176001600160481b03909116179050808483610f8b81612bad565b945081518110610f9d57610f9d612aeb565b602090810291909101015284610fb284612bad565b93508310610f24575050505b92915050565b6000600a610fd28385612b17565b6014600554610fe19190612b17565b610feb9190612b2a565b610ff59190612b62565b610fff9085612b2a565b61100a90600b612b2a565b949350505050565b61101a6114b2565b6110246000611ff9565b565b600062093a806007544261103a9190612b17565b101590506000600160009054906101000a90046001600160a01b03166001600160a01b03166351e238e36040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190612b49565b600160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561110c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111309190612b49565b11905080801561114257506028600554105b801561114b5750815b15611169576005805461115d91612b84565b60055542600755611188565b8015801561117957506014600554115b15611188576014600555426007555b60055461119790618e30612b62565b6006555050565b6111a66128be565b6111ae6128be565b6111b88282611520565b821561122d578160e0015183111561121c5760405162461bcd60e51b815260206004820152602160248201527f6265666f72654461792063616e6e6f7420626520696e207468652066757475726044820152606560f81b606482015260840161066e565b61122882846000612049565b61123d565b61123d828360e001516000612049565b6112478282611b03565b505050565b6112546114b2565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b600c5460ff16156112b55760405162461bcd60e51b81526020600482015260096024820152681a5b9a5d1a585d195960ba1b604482015260640161066e565b6112be33611ff9565b6112cc620186a06001612b2a565b6008805464ffffffffff92909216600160901b0264ffffffffff60901b199092169190911790556009805461ffff19166001179055426004556014600581905561131890618e30612b62565b600655600c805460ff19166001179055565b61133261290a565b60408051610120810182526008546001600160481b038082168352600160481b8204811660208085019190915264ffffffffff600160901b8404811685870152600160b81b9093048216606085015260095461ffff8116608086015262010000810490921660a0850152600160581b90910490911660c08301524260e083015260015483516318160ddd60e01b8152935192936101008501936402540be400936001600160a01b03909316926318160ddd92600480820193918290030181865afa158015611404573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114289190612b49565b6114329190612b62565b9052919050565b6114416114b2565b6001600160a01b0381166114a65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161066e565b6114af81611ff9565b50565b6000546001600160a01b03163314806114d457506000546001600160a01b0316155b6110245760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066e565b6008546001600160481b038082168452600160481b82048116602085015264ffffffffff600160901b830481166040860152600160b81b9092048116606085015260095461ffff8116608086015262010000810490911660a0850152600160581b90041660c0830152611591611f3e565b60e08301526115a08282612229565b5050565b825464ffffffffff8381169116146115fe5760405162461bcd60e51b815260206004820152601960248201527f7374616b654964506172616d206e6f7420696e207374616b6500000000000000604482015260640161066e565b915464ffffffffff811683526001600160481b03600160281b820481166020850152600160701b820416604084015261ffff600160b81b820481166060850152600160c81b820481166080850152600160d81b9091041660a09092019190915250565b6114af818260e001516001612049565b80604001518260a0018181516116879190612b17565b90525060e09091015160a090910152565b60008060008085608001518510156116df576116c38787606001518860800151888a60400151612271565b602088015191945092506116d8908490612b84565b935061172c565b604086015160608701516116fd91906116f88882612b84565b61237e565b925082866020015161170f9190612b84565b9350611729866060015187608001518860a00151876123e7565b91505b811561175257838211156117435750600092611752565b508061174f8185612b17565b93505b93509350935093565b8664ffffffffff16336001600160a01b03167f72d9c5a7ab13846e08d9c838f9e866a1bb4a66a2fd3ba3c9e7da3cf9e394dfd760b8876001600160481b0316901b6070896001600160481b0316901b60288b6001600160481b0316901b4264ffffffffff16171717846117cf5760006117d5565b600160581b5b6bffffffffffffffffffffffff1660488761ffff16901b886001600160481b0316171760405161180f929190918252602082015260400190565b60405180910390a350505050505050565b600061182d600283612b62565b905080156118c9576001546001600160a01b031663b4f56b2673c0c607cf29852476311b4c17328d18a2d02a845c61186a846402540be400612b2a565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156118b057600080fd5b505af11580156118c4573d6000803e3d6000fd5b505050505b6118d38183612b17565b905080836060018181516118e79190612b84565b905250505050565b8160200151811115611247576000611910828460800151856000015161243e565b905060008360400151620186a083856119299190612b84565b6119339190612b2a565b61193d9190612b62565b905061194e6001600160281b612b17565b811115611967576119646001600160281b612b17565b90505b8460400151811115611987576040850181905283516119879082906125ce565b5050505050565b815460009061199f90600190612b17565b9050808214611acc578281815481106119ba576119ba612aeb565b906000526020600020018383815481106119d6576119d6612aeb565b6000918252602090912082549101805464ffffffffff90921664ffffffffff1983168117825583546001600160701b031990931617600160281b928390046001600160481b0390811690930217808255835468ffffffffffffffffff60701b198216600160701b918290049094160292831782558354600160701b600160c81b031990911661ffff60b81b1990931692909217600160b81b9283900461ffff90811690930217808255835461ffff60c81b198216600160c81b9182900485169091029081178355935463ffffffff60c81b1990911661ffff60d81b1990941693909317600160d81b938490049092169092021790555b82805480611adc57611adc612bc6565b600082815260209020810160001990810180546001600160e81b0319169055019055505050565b80518251141580611b1c57508060200151826020015114155b80611b2f57508060400151826040015114155b80611b4257508060600151826060015114155b15611bc5578151600880546020850151604086015160608701516001600160481b03908116600160b81b026001600160b81b0364ffffffffff909316600160901b029290921671ffffffffffffffffffffffffffffffffffff938216600160481b026001600160901b031990951691909616179290921716929092179190911790555b80608001518260800151141580611be457508060a001518260a0015114155b80611c0557508060c0015164ffffffffff168260c0015164ffffffffff1614155b156115a05760808201516009805460a085015160c086015164ffffffffff16600160581b0264ffffffffff60581b196001600160481b0390921662010000026affffffffffffffffffffff1990931661ffff9095169490941791909117169190911790555050565b6115b3811115611cb45760405162461bcd60e51b81526020600482015260126024820152710dccaeea6e8c2d6cac888c2f2e640d0d2ced60731b604482015260640161066e565b60008360c0018051611cc590612bdc565b64ffffffffff169081905260025460405163903acf5160e01b8152336004820152602481018390529192506001600160a01b03169063903acf51906044016020604051808303816000875af1158015611d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d469190612c00565b506000611d5484848461243e565b905060008560400151620186a08387611d6d9190612b84565b611d779190612b2a565b611d819190612b62565b905080600003611ddd5760405162461bcd60e51b815260206004820152602160248201527f6e65775374616b65645873206d757374206265203e3d206d696e2063645261746044820152606560f81b606482015260840161066e565b60008660e001516001611df09190612b84565b336000908152600b60205260409020909150611f0090858885858a6040805160c08101825264ffffffffff96871681526001600160481b03958616602080830191825295871692820192835261ffff9485166060830190815293851660808301908152600060a084018181528b54600181018d559b82529790209251929099018054915193519451995196518616600160d81b0261ffff60d81b19978716600160c81b029790971663ffffffff60c81b199a909616600160b81b0261ffff60b81b19958916600160701b0295909516600160701b600160c81b031994909816600160281b026001600160701b03199092169290981691909117171693909317929092179390931617919091179055565b611f0c84878488612627565b8187602001818151611f1e9190612b84565b905250865186908890611f32908390612b84565b90525050505050505050565b60006201518060045442611f529190612b17565b610a589190612b62565b604080514264ffffffffff9081166dffffffffffffffffff0000000000602889901b161768ffffffffffffffffff60701b607088901b16176001600160b81b031960b887901b161782526001600160481b03841660208301523392908816916001600160a01b038a16917fd824970a2cf19cc2b630c87ce5b00f67301cac3ac60513d027c7a39129f93b46910160405180910390a4505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8183608001511061205957505050565b61207d60405180606001604052806000815260200160008152602001600081525090565b8351600154604080516318160ddd60e01b815290516402540be400926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa1580156120cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f19190612b49565b6120fb9190612b62565b6121059190612b84565b815260808401516121178583836126ab565b6020850151156121425784602001518560a0018181516121379190612b84565b905250600060208601525b8361214c82612bad565b9150811015612165576121608583836126ab565b612142565b612174856080015182856126fc565b608085018190526020820151156119875760015460208301516001600160a01b039091169063b4f56b269073c0c607cf29852476311b4c17328d18a2d02a845c906121c4906402540be400612b2a565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561220a57600080fd5b505af115801561221e573d6000803e3d6000fd5b505050505050505050565b815181526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c09182015164ffffffffff16910152565b6000808061227f8588612b84565b905060006002612290886001612b84565b61229a9190612b62565b9050605a8110156122a95750605a5b856000036122d45760006122be8a878b612775565b90506122ca8282612b2a565b9350505050612374565b8581101561231b5760006122e8828a612b84565b90506122f5868a8361237e565b9350600061230487838661237e565b90506123108186612b84565b955050505050612374565b61232685898461237e565b935085810361233757839250612371565b856123428286612b2a565b61234c9190612b62565b92506014600554111561237157612364848888610fc4565b61236e9084612b84565b92505b50505b9550959350505050565b6000825b828110156123df576000818152600a60205260409020546001600160481b03600160481b82048116916123b791889116612b2a565b6123c19190612b62565b6123cb9083612b84565b9150806123d781612bad565b915050612382565b509392505050565b600080600e6123f68688612b84565b6124009190612b84565b905080841161241357600091505061100a565b6102bc6124208286612b17565b61242a9085612b2a565b6124349190612b62565b9695505050505050565b600080600184111561246a57610e3884111561245c57610e38612467565b612467600185612b17565b90505b600061247e6305f5e1006308f0d180612b2a565b86111561249c576124976305f5e1006308f0d180612b2a565b61249e565b855b9050600654816124ae9190612b2a565b600a6124c26305f5e1006308f0d180612b2a565b6124cd906064612b2a565b6124d79190612b62565b6124e19084612b2a565b6124eb9190612b84565b9250600a6125016305f5e1006308f0d180612b2a565b61250c906064612b2a565b6125169190612b62565b6006546125239190612b2a565b61252d8488612b2a565b6125379190612b62565b60025460405163157a04bb60e21b815264ffffffffff87166004820152919450600a916001600160a01b03909116906355e812ec90602401602060405180830381865afa15801561258c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b09190612b49565b6125ba9085612b2a565b6125c49190612b62565b6124349084612b84565b8064ffffffffff167f7c289df238c8a368f40a4e87d0c1164b73f1cee6b3759a3f7b8d261fae2f14c960288464ffffffffff16901b4264ffffffffff161760405161261b91815260200190565b60405180910390a25050565b60405164ffffffffff8086169133917f14872dc760f33532684e68e1b6d5fd3f71ba7b07dee76bdb2b084f28b74233ef9161269d9142166dffffffffffffffffff000000000060288a901b161768ffffffffffffffffff60701b607089901b161761ffff60b81b60b888901b1617815260200190565b60405180910390a350505050565b6126b683838361286c565b6040918201516000918252600a602052919020805460a0909301516001600160481b03908116600160481b026001600160901b0319909416921691909117919091179055565b337fb8d6eb541ded1720cc657b719f57abcb1fe4711cb7ead82751b135f5d94bc9448261272a576000612730565b600160481b5b69ffffffffffffffffffff1660388561ffff16901b60288761ffff16901b4264ffffffffff1617171760405161276891815260200190565b60405180910390a2505050565b600061277f6128be565b6127898582612229565b6127ad60405180606001604052806000815260200160008152602001600081525090565b8551600154604080516318160ddd60e01b815290516402540be400926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa1580156127fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128219190612b49565b61282b9190612b62565b6128359190612b84565b815261284282828661286c565b848260a0018181516128549190612b84565b90525060a0820151604082015161242a908790612b2a565b815163043763b39061288090612710612b2a565b61288a9190612b62565b6040830152606083015115611247578260600151826040018181516128af9190612b84565b90525060006060840152505050565b604051806101000160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600064ffffffffff168152602001600081525090565b6040518061012001604052806009906020820280368337509192915050565b80356001600160a01b038116811461294057600080fd5b919050565b6000806040838503121561295857600080fd5b61296183612929565b946020939093013593505050565b60006020828403121561298157600080fd5b61298a82612929565b9392505050565b803564ffffffffff8116811461294057600080fd5b600080604083850312156129b957600080fd5b823591506129c960208401612991565b90509250929050565b600080604083850312156129e557600080fd5b50508035926020909101359150565b600080600060608486031215612a0957600080fd5b612a1284612929565b925060208401359150612a2760408501612991565b90509250925092565b6020808252825182820181905260009190848201906040850190845b81811015612a6857835183529284019291840191600101612a4c565b50909695505050505050565b600080600060608486031215612a8957600080fd5b505081359360208301359350604090920135919050565b600060208284031215612ab257600080fd5b5035919050565b6101208101818360005b6009811015612ae2578151835260209283019290910190600101612ac3565b50505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610fbe57610fbe612b01565b6000816000190483118215151615612b4457612b44612b01565b500290565b600060208284031215612b5b57600080fd5b5051919050565b600082612b7f57634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610fbe57610fbe612b01565b634e487b7160e01b600052604160045260246000fd5b600060018201612bbf57612bbf612b01565b5060010190565b634e487b7160e01b600052603160045260246000fd5b600064ffffffffff808316818103612bf657612bf6612b01565b6001019392505050565b600060208284031215612c1257600080fd5b8151801515811461298a57600080fdfea2646970667358221220c078c9a5fe317137d5ee5993a40f66525cb7c6f93bdca272ec42e0735d69332764736f6c63430008100033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063715018a6116101045780639f118536116100a2578063f04b5fa011610071578063f04b5fa0146104fe578063f1fcd72714610513578063f2fde38b1461051c578063f9b6baa11461052f57600080fd5b80639f1185361461041f578063c31245251461043c578063cc0911bf146104e3578063e1c7392a146104f657600080fd5b80638f1c65c0116100de5780638f1c65c01461037a57806390adafc71461038d57806390de6871146103a05780639d463cee1461041657600080fd5b8063715018a614610359578063789f07b1146103615780638da5cb5b1461036957600080fd5b80634a144516116101715780635c9302c91161014b5780635c9302c91461030b57806365cf71b2146103135780636a210a0e146103265780636de6e9321461034657600080fd5b80634a144516146102dc5780634e812b30146102ef57806352a438b8146102f857600080fd5b806333060d90116101ad57806333060d901461025f578063343009a2146102965780633a70a5ca146102a957806348f5d087146102b157600080fd5b80632607443b146101d4578063265622c4146102375780632fd9678d1461024c575b600080fd5b6101e76101e2366004612945565b610538565b6040805164ffffffffff90971687526001600160481b039586166020880152949093169385019390935261ffff908116606085015291821660808401521660a082015260c0015b60405180910390f35b61024a61024536600461296f565b6105a9565b005b61024a61025a36600461296f565b6105d3565b61028861026d36600461296f565b6001600160a01b03166000908152600b602052604090205490565b60405190815260200161022e565b61024a6102a43660046129a6565b6105fd565b610288610939565b6002546102c4906001600160a01b031681565b6040516001600160a01b03909116815260200161022e565b6001546102c4906001600160a01b031681565b61028860055481565b61024a6103063660046129d2565b610a5d565b610288610b67565b61024a6103213660046129f4565b610b71565b6103396103343660046129d2565b610e7e565b60405161022e9190612a30565b610288610354366004612a74565b610fc4565b61024a611012565b61024a611026565b6000546001600160a01b03166102c4565b61024a610388366004612aa0565b61119e565b6003546102c4906001600160a01b031681565b6103e76103ae366004612aa0565b600a602052600090815260409020546001600160481b0380821691600160481b810490911690600160901b900466ffffffffffffff1683565b604080516001600160481b03948516815293909216602084015266ffffffffffffff169082015260600161022e565b61028860075481565b600c5461042c9060ff1681565b604051901515815260200161022e565b600854600954610491916001600160481b0380821692600160481b830482169264ffffffffff600160901b8204811693600160b81b90920482169261ffff8116926201000082041691600160581b9091041687565b604080516001600160481b039889168152968816602088015264ffffffffff95861690870152928616606086015261ffff90911660808501529390931660a083015290911660c082015260e00161022e565b61024a6104f136600461296f565b61124c565b61024a611276565b61050661132a565b60405161022e9190612ab9565b610288610e3881565b61024a61052a36600461296f565b611439565b61028860065481565b600b602052816000526040600020818154811061055457600080fd5b60009182526020909120015464ffffffffff811692506001600160481b03600160281b820481169250600160701b8204169061ffff600160b81b8204811691600160c81b8104821691600160d81b9091041686565b6105b16114b2565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6105db6114b2565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6106056128be565b61060d6128be565b6106178282611520565b61061f611026565b336000908152600b6020526040812080549091036106775760405162461bcd60e51b815260206004820152601060248201526f195b5c1d1e481cdd185ad9481b1a5cdd60821b60448201526064015b60405180910390fd5b805485106106bc5760405162461bcd60e51b81526020600482015260126024820152711cdd185ad9525b99195e081a5b9d985b1a5960721b604482015260640161066e565b6106fc6040518060c00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b61072282878154811061071157610711612aeb565b9060005260206000200186836115a4565b61072b84611661565b6000808260a001516000141590506000806000905060008086606001518a60e00151106107b25784156107645786608001519550610798565b61076e8a88611671565b86606001518a60e001516107829190612b17565b9550866080015186111561079857866080015195505b6107a38a8888611698565b929650909450925090506107d3565b86604001518a6020018181516107c89190612b17565b905250602087015193505b6107ea8b8860200151896040015186868b8b61175b565b80158015906107f7575084155b15610806576108068a82611820565b8315610896576001546001600160a01b031663b4f56b263361082d876402540be400612b2a565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561087357600080fd5b505af1158015610887573d6000803e3d6000fd5b505050506108968a88866118ef565b60208701518a518b906108aa908390612b17565b90525060025460405163a9db026960e01b815233600482015264ffffffffff8d1660248201526001600160a01b039091169063a9db026990604401600060405180830381600087803b1580156108ff57600080fd5b505af1158015610913573d6000803e3d6000fd5b50505050610921888d61198e565b61092b8a8a611b03565b505050505050505050505050565b600854600354604080516361bf897b60e11b815290516000936001600160481b0316926402540be400926001600160a01b039091169163c37f12f6916004808201926020929091908290030181865afa15801561099a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109be9190612b49565b6109c89190612b62565b600154604080516318160ddd60e01b815290516402540be400926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa158015610a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3a9190612b49565b610a449190612b62565b610a4e9190612b84565b610a589190612b84565b905090565b610a656128be565b610a6d6128be565b610a778282611520565b610a7f611026565b6001831015610ac45760405162461bcd60e51b81526020600482015260116024820152706e65775374616b656444617973206c6f7760781b604482015260640161066e565b610acd82611661565b610ad8828585611c6d565b6001546001600160a01b031663a8a778ae33610af9876402540be400612b2a565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610b3f57600080fd5b505af1158015610b53573d6000803e3d6000fd5b50505050610b618282611b03565b50505050565b6000610a58611f3e565b610b796128be565b610b816128be565b610b8b8282611520565b6001600160a01b0385166000908152600b60205260408120549003610be55760405162461bcd60e51b815260206004820152601060248201526f195b5c1d1e481cdd185ad9481b1a5cdd60821b604482015260640161066e565b6001600160a01b0385166000908152600b60205260409020548410610c415760405162461bcd60e51b81526020600482015260126024820152711cdd185ad9525b99195e081a5b9d985b1a5960721b604482015260640161066e565b6001600160a01b0385166000908152600b60205260408120805486908110610c6b57610c6b612aeb565b906000526020600020019050610cb76040518060c00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b610cc28286836115a4565b80608001518160600151610cd69190612b84565b8460e001511015610d225760405162461bcd60e51b815260206004820152601660248201527514dd185ad9481b9bdd08199d5b1b1e481cd95c9d995960521b604482015260640161066e565b60a081015115610d6d5760405162461bcd60e51b815260206004820152601660248201527514dd185ad948185b1c9958591e481d5b9b1bd8dad95960521b604482015260640161066e565b610d7684611661565b610d808482611671565b6000806000610d9487858660800151611698565b93509350935050610db18a89866020015187604001518787611f5c565b8015610dc157610dc18782611820565b83518554602086015160408701516060880151608089015160a08a015164ffffffffff9096166001600160701b031990951694909417600160281b6001600160481b039485160217600160701b600160c81b031916600160701b939092169290920261ffff60b81b191617600160b81b61ffff928316021763ffffffff60c81b1916600160c81b9282169290920261ffff60d81b191691909117600160d81b9190921602178555610e728787611b03565b50505050505050505050565b60608183108015610e95575060095461ffff168211155b610ed15760405162461bcd60e51b815260206004820152600d60248201526c1c985b99d9481a5b9d985b1a59609a1b604482015260640161066e565b610edb8383612b17565b67ffffffffffffffff811115610ef357610ef3612b97565b604051908082528060200260200182016040528015610f1c578160200160208202803683370190505b509050826000805b610f3060486002612b2a565b6000848152600a6020526040902054600160901b810466ffffffffffffff1690911b600160481b820460481b71ffffffffffffffffff00000000000000000016176001600160481b03909116179050808483610f8b81612bad565b945081518110610f9d57610f9d612aeb565b602090810291909101015284610fb284612bad565b93508310610f24575050505b92915050565b6000600a610fd28385612b17565b6014600554610fe19190612b17565b610feb9190612b2a565b610ff59190612b62565b610fff9085612b2a565b61100a90600b612b2a565b949350505050565b61101a6114b2565b6110246000611ff9565b565b600062093a806007544261103a9190612b17565b101590506000600160009054906101000a90046001600160a01b03166001600160a01b03166351e238e36040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190612b49565b600160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561110c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111309190612b49565b11905080801561114257506028600554105b801561114b5750815b15611169576005805461115d91612b84565b60055542600755611188565b8015801561117957506014600554115b15611188576014600555426007555b60055461119790618e30612b62565b6006555050565b6111a66128be565b6111ae6128be565b6111b88282611520565b821561122d578160e0015183111561121c5760405162461bcd60e51b815260206004820152602160248201527f6265666f72654461792063616e6e6f7420626520696e207468652066757475726044820152606560f81b606482015260840161066e565b61122882846000612049565b61123d565b61123d828360e001516000612049565b6112478282611b03565b505050565b6112546114b2565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b600c5460ff16156112b55760405162461bcd60e51b81526020600482015260096024820152681a5b9a5d1a585d195960ba1b604482015260640161066e565b6112be33611ff9565b6112cc620186a06001612b2a565b6008805464ffffffffff92909216600160901b0264ffffffffff60901b199092169190911790556009805461ffff19166001179055426004556014600581905561131890618e30612b62565b600655600c805460ff19166001179055565b61133261290a565b60408051610120810182526008546001600160481b038082168352600160481b8204811660208085019190915264ffffffffff600160901b8404811685870152600160b81b9093048216606085015260095461ffff8116608086015262010000810490921660a0850152600160581b90910490911660c08301524260e083015260015483516318160ddd60e01b8152935192936101008501936402540be400936001600160a01b03909316926318160ddd92600480820193918290030181865afa158015611404573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114289190612b49565b6114329190612b62565b9052919050565b6114416114b2565b6001600160a01b0381166114a65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161066e565b6114af81611ff9565b50565b6000546001600160a01b03163314806114d457506000546001600160a01b0316155b6110245760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066e565b6008546001600160481b038082168452600160481b82048116602085015264ffffffffff600160901b830481166040860152600160b81b9092048116606085015260095461ffff8116608086015262010000810490911660a0850152600160581b90041660c0830152611591611f3e565b60e08301526115a08282612229565b5050565b825464ffffffffff8381169116146115fe5760405162461bcd60e51b815260206004820152601960248201527f7374616b654964506172616d206e6f7420696e207374616b6500000000000000604482015260640161066e565b915464ffffffffff811683526001600160481b03600160281b820481166020850152600160701b820416604084015261ffff600160b81b820481166060850152600160c81b820481166080850152600160d81b9091041660a09092019190915250565b6114af818260e001516001612049565b80604001518260a0018181516116879190612b17565b90525060e09091015160a090910152565b60008060008085608001518510156116df576116c38787606001518860800151888a60400151612271565b602088015191945092506116d8908490612b84565b935061172c565b604086015160608701516116fd91906116f88882612b84565b61237e565b925082866020015161170f9190612b84565b9350611729866060015187608001518860a00151876123e7565b91505b811561175257838211156117435750600092611752565b508061174f8185612b17565b93505b93509350935093565b8664ffffffffff16336001600160a01b03167f72d9c5a7ab13846e08d9c838f9e866a1bb4a66a2fd3ba3c9e7da3cf9e394dfd760b8876001600160481b0316901b6070896001600160481b0316901b60288b6001600160481b0316901b4264ffffffffff16171717846117cf5760006117d5565b600160581b5b6bffffffffffffffffffffffff1660488761ffff16901b886001600160481b0316171760405161180f929190918252602082015260400190565b60405180910390a350505050505050565b600061182d600283612b62565b905080156118c9576001546001600160a01b031663b4f56b2673c0c607cf29852476311b4c17328d18a2d02a845c61186a846402540be400612b2a565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156118b057600080fd5b505af11580156118c4573d6000803e3d6000fd5b505050505b6118d38183612b17565b905080836060018181516118e79190612b84565b905250505050565b8160200151811115611247576000611910828460800151856000015161243e565b905060008360400151620186a083856119299190612b84565b6119339190612b2a565b61193d9190612b62565b905061194e6001600160281b612b17565b811115611967576119646001600160281b612b17565b90505b8460400151811115611987576040850181905283516119879082906125ce565b5050505050565b815460009061199f90600190612b17565b9050808214611acc578281815481106119ba576119ba612aeb565b906000526020600020018383815481106119d6576119d6612aeb565b6000918252602090912082549101805464ffffffffff90921664ffffffffff1983168117825583546001600160701b031990931617600160281b928390046001600160481b0390811690930217808255835468ffffffffffffffffff60701b198216600160701b918290049094160292831782558354600160701b600160c81b031990911661ffff60b81b1990931692909217600160b81b9283900461ffff90811690930217808255835461ffff60c81b198216600160c81b9182900485169091029081178355935463ffffffff60c81b1990911661ffff60d81b1990941693909317600160d81b938490049092169092021790555b82805480611adc57611adc612bc6565b600082815260209020810160001990810180546001600160e81b0319169055019055505050565b80518251141580611b1c57508060200151826020015114155b80611b2f57508060400151826040015114155b80611b4257508060600151826060015114155b15611bc5578151600880546020850151604086015160608701516001600160481b03908116600160b81b026001600160b81b0364ffffffffff909316600160901b029290921671ffffffffffffffffffffffffffffffffffff938216600160481b026001600160901b031990951691909616179290921716929092179190911790555b80608001518260800151141580611be457508060a001518260a0015114155b80611c0557508060c0015164ffffffffff168260c0015164ffffffffff1614155b156115a05760808201516009805460a085015160c086015164ffffffffff16600160581b0264ffffffffff60581b196001600160481b0390921662010000026affffffffffffffffffffff1990931661ffff9095169490941791909117169190911790555050565b6115b3811115611cb45760405162461bcd60e51b81526020600482015260126024820152710dccaeea6e8c2d6cac888c2f2e640d0d2ced60731b604482015260640161066e565b60008360c0018051611cc590612bdc565b64ffffffffff169081905260025460405163903acf5160e01b8152336004820152602481018390529192506001600160a01b03169063903acf51906044016020604051808303816000875af1158015611d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d469190612c00565b506000611d5484848461243e565b905060008560400151620186a08387611d6d9190612b84565b611d779190612b2a565b611d819190612b62565b905080600003611ddd5760405162461bcd60e51b815260206004820152602160248201527f6e65775374616b65645873206d757374206265203e3d206d696e2063645261746044820152606560f81b606482015260840161066e565b60008660e001516001611df09190612b84565b336000908152600b60205260409020909150611f0090858885858a6040805160c08101825264ffffffffff96871681526001600160481b03958616602080830191825295871692820192835261ffff9485166060830190815293851660808301908152600060a084018181528b54600181018d559b82529790209251929099018054915193519451995196518616600160d81b0261ffff60d81b19978716600160c81b029790971663ffffffff60c81b199a909616600160b81b0261ffff60b81b19958916600160701b0295909516600160701b600160c81b031994909816600160281b026001600160701b03199092169290981691909117171693909317929092179390931617919091179055565b611f0c84878488612627565b8187602001818151611f1e9190612b84565b905250865186908890611f32908390612b84565b90525050505050505050565b60006201518060045442611f529190612b17565b610a589190612b62565b604080514264ffffffffff9081166dffffffffffffffffff0000000000602889901b161768ffffffffffffffffff60701b607088901b16176001600160b81b031960b887901b161782526001600160481b03841660208301523392908816916001600160a01b038a16917fd824970a2cf19cc2b630c87ce5b00f67301cac3ac60513d027c7a39129f93b46910160405180910390a4505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8183608001511061205957505050565b61207d60405180606001604052806000815260200160008152602001600081525090565b8351600154604080516318160ddd60e01b815290516402540be400926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa1580156120cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f19190612b49565b6120fb9190612b62565b6121059190612b84565b815260808401516121178583836126ab565b6020850151156121425784602001518560a0018181516121379190612b84565b905250600060208601525b8361214c82612bad565b9150811015612165576121608583836126ab565b612142565b612174856080015182856126fc565b608085018190526020820151156119875760015460208301516001600160a01b039091169063b4f56b269073c0c607cf29852476311b4c17328d18a2d02a845c906121c4906402540be400612b2a565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561220a57600080fd5b505af115801561221e573d6000803e3d6000fd5b505050505050505050565b815181526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c09182015164ffffffffff16910152565b6000808061227f8588612b84565b905060006002612290886001612b84565b61229a9190612b62565b9050605a8110156122a95750605a5b856000036122d45760006122be8a878b612775565b90506122ca8282612b2a565b9350505050612374565b8581101561231b5760006122e8828a612b84565b90506122f5868a8361237e565b9350600061230487838661237e565b90506123108186612b84565b955050505050612374565b61232685898461237e565b935085810361233757839250612371565b856123428286612b2a565b61234c9190612b62565b92506014600554111561237157612364848888610fc4565b61236e9084612b84565b92505b50505b9550959350505050565b6000825b828110156123df576000818152600a60205260409020546001600160481b03600160481b82048116916123b791889116612b2a565b6123c19190612b62565b6123cb9083612b84565b9150806123d781612bad565b915050612382565b509392505050565b600080600e6123f68688612b84565b6124009190612b84565b905080841161241357600091505061100a565b6102bc6124208286612b17565b61242a9085612b2a565b6124349190612b62565b9695505050505050565b600080600184111561246a57610e3884111561245c57610e38612467565b612467600185612b17565b90505b600061247e6305f5e1006308f0d180612b2a565b86111561249c576124976305f5e1006308f0d180612b2a565b61249e565b855b9050600654816124ae9190612b2a565b600a6124c26305f5e1006308f0d180612b2a565b6124cd906064612b2a565b6124d79190612b62565b6124e19084612b2a565b6124eb9190612b84565b9250600a6125016305f5e1006308f0d180612b2a565b61250c906064612b2a565b6125169190612b62565b6006546125239190612b2a565b61252d8488612b2a565b6125379190612b62565b60025460405163157a04bb60e21b815264ffffffffff87166004820152919450600a916001600160a01b03909116906355e812ec90602401602060405180830381865afa15801561258c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b09190612b49565b6125ba9085612b2a565b6125c49190612b62565b6124349084612b84565b8064ffffffffff167f7c289df238c8a368f40a4e87d0c1164b73f1cee6b3759a3f7b8d261fae2f14c960288464ffffffffff16901b4264ffffffffff161760405161261b91815260200190565b60405180910390a25050565b60405164ffffffffff8086169133917f14872dc760f33532684e68e1b6d5fd3f71ba7b07dee76bdb2b084f28b74233ef9161269d9142166dffffffffffffffffff000000000060288a901b161768ffffffffffffffffff60701b607089901b161761ffff60b81b60b888901b1617815260200190565b60405180910390a350505050565b6126b683838361286c565b6040918201516000918252600a602052919020805460a0909301516001600160481b03908116600160481b026001600160901b0319909416921691909117919091179055565b337fb8d6eb541ded1720cc657b719f57abcb1fe4711cb7ead82751b135f5d94bc9448261272a576000612730565b600160481b5b69ffffffffffffffffffff1660388561ffff16901b60288761ffff16901b4264ffffffffff1617171760405161276891815260200190565b60405180910390a2505050565b600061277f6128be565b6127898582612229565b6127ad60405180606001604052806000815260200160008152602001600081525090565b8551600154604080516318160ddd60e01b815290516402540be400926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa1580156127fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128219190612b49565b61282b9190612b62565b6128359190612b84565b815261284282828661286c565b848260a0018181516128549190612b84565b90525060a0820151604082015161242a908790612b2a565b815163043763b39061288090612710612b2a565b61288a9190612b62565b6040830152606083015115611247578260600151826040018181516128af9190612b84565b90525060006060840152505050565b604051806101000160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600064ffffffffff168152602001600081525090565b6040518061012001604052806009906020820280368337509192915050565b80356001600160a01b038116811461294057600080fd5b919050565b6000806040838503121561295857600080fd5b61296183612929565b946020939093013593505050565b60006020828403121561298157600080fd5b61298a82612929565b9392505050565b803564ffffffffff8116811461294057600080fd5b600080604083850312156129b957600080fd5b823591506129c960208401612991565b90509250929050565b600080604083850312156129e557600080fd5b50508035926020909101359150565b600080600060608486031215612a0957600080fd5b612a1284612929565b925060208401359150612a2760408501612991565b90509250925092565b6020808252825182820181905260009190848201906040850190845b81811015612a6857835183529284019291840191600101612a4c565b50909695505050505050565b600080600060608486031215612a8957600080fd5b505081359360208301359350604090920135919050565b600060208284031215612ab257600080fd5b5035919050565b6101208101818360005b6009811015612ae2578151835260209283019290910190600101612ac3565b50505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610fbe57610fbe612b01565b6000816000190483118215151615612b4457612b44612b01565b500290565b600060208284031215612b5b57600080fd5b5051919050565b600082612b7f57634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610fbe57610fbe612b01565b634e487b7160e01b600052604160045260246000fd5b600060018201612bbf57612bbf612b01565b5060010190565b634e487b7160e01b600052603160045260246000fd5b600064ffffffffff808316818103612bf657612bf6612b01565b6001019392505050565b600060208284031215612c1257600080fd5b8151801515811461298a57600080fdfea2646970667358221220c078c9a5fe317137d5ee5993a40f66525cb7c6f93bdca272ec42e0735d69332764736f6c63430008100033