Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
StakingThales
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;
import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/SafeERC20.sol";
import "openzeppelin-solidity-2.3.0/contracts/math/SafeMath.sol";
import "../utils/proxy/ProxyReentrancyGuard.sol";
import "../utils/proxy/ProxyOwned.sol";
import "../utils/proxy/ProxyPausable.sol";
import "@openzeppelin/upgrades-core/contracts/Initializable.sol";
import "../interfaces/IEscrowThales.sol";
import "../interfaces/IStakingThales.sol";
import "../interfaces/ISNXRewards.sol";
import "../interfaces/IThalesRoyale.sol";
import "../interfaces/IPriceFeed.sol";
import "../interfaces/IThalesStakingRewardsPool.sol";
import "../interfaces/IAddressResolver.sol";
import "../interfaces/ISportsAMMLiquidityPool.sol";
import "../interfaces/IThalesAMMLiquidityPool.sol";
import "../interfaces/IParlayAMMLiquidityPool.sol";
import "../interfaces/IThalesAMM.sol";
import "../interfaces/IPositionalMarketManager.sol";
import "../interfaces/IStakingThalesBonusRewardsManager.sol";
import "../interfaces/ICCIPCollector.sol";
import "../interfaces/IStakingThalesBettingProxy.sol";
/// @title A Staking contract that provides logic for staking and claiming rewards
contract StakingThales is IStakingThales, Initializable, ProxyOwned, ProxyReentrancyGuard, ProxyPausable {
/* ========== LIBRARIES ========== */
using SafeMath for uint;
using SafeERC20 for IERC20;
/* ========== STATE VARIABLES ========== */
IEscrowThales public iEscrowThales;
IERC20 public stakingToken;
IERC20 public feeToken;
ISNXRewards private SNXRewards;
IThalesRoyale private thalesRoyale;
IPriceFeed public priceFeed;
uint public periodsOfStaking;
uint public lastPeriodTimeStamp;
uint public durationPeriod;
uint public unstakeDurationPeriod;
uint public startTimeStamp;
uint public currentPeriodRewards;
uint public currentPeriodFees;
bool public distributeFeesEnabled;
uint public fixedPeriodReward;
uint public periodExtraReward;
uint private totalSNXRewardsInPeriod;
uint private totalSNXFeesInPeriod;
bool public claimEnabled;
mapping(address => uint) public stakerLifetimeRewardsClaimed;
mapping(address => uint) public stakerFeesClaimed;
uint private _totalStakedAmount;
uint private _totalEscrowedAmount;
uint private _totalPendingStakeAmount;
uint private _totalUnclaimedRewards;
uint private _totalRewardsClaimed;
uint private _totalRewardFeesClaimed;
mapping(address => uint) public lastUnstakeTime;
mapping(address => bool) public unstaking;
mapping(address => uint) public unstakingAmount;
mapping(address => uint) private _stakedBalances;
mapping(address => uint) private _lastRewardsClaimedPeriod;
address public thalesAMM;
uint constant HUNDRED = 1e18;
uint constant AMM_EXTRA_REWARD_PERIODS = 4;
struct AMMVolumeEntry {
uint amount;
uint period;
}
mapping(address => uint) private lastAMMUpdatePeriod;
mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private stakerAMMVolume;
bool public extraRewardsActive;
IThalesStakingRewardsPool public ThalesStakingRewardsPool;
uint private maxSNXRewardsPercentage;
uint private maxAMMVolumeRewardsPercentage;
uint private AMMVolumeRewardsMultiplier;
uint private maxThalesRoyaleRewardsPercentage;
uint constant ONE = 1e18;
uint constant ONE_PERCENT = 1e16;
uint private SNXVolumeRewardsMultiplier;
mapping(address => uint) private _lastStakingPeriod;
uint public totalStakedLastPeriodEnd;
uint public totalEscrowedLastPeriodEnd;
address private exoticBonds;
IAddressResolver private addressResolver;
address public thalesRangedAMM;
address public sportsAMM;
mapping(address => uint) private lastThalesAMMUpdatePeriod;
mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private thalesAMMVolume;
mapping(address => uint) private lastThalesRangedAMMUpdatePeriod;
mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private thalesRangedAMMVolume;
mapping(address => uint) private lastExoticMarketsUpdatePeriod;
mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private exoticMarketsVolume;
mapping(address => uint) private lastSportsAMMUpdatePeriod;
mapping(address => AMMVolumeEntry[AMM_EXTRA_REWARD_PERIODS]) private sportsAMMVolume;
mapping(address => mapping(address => bool)) public canClaimOnBehalf;
bool public mergeAccountEnabled;
mapping(address => address) public delegatedVolume;
mapping(address => bool) public supportedSportVault;
mapping(address => bool) public supportedAMMVault;
ISportsAMMLiquidityPool private sportsAMMLiquidityPool;
IThalesAMMLiquidityPool private thalesAMMLiquidityPool;
IStakingThalesBonusRewardsManager public stakingThalesBonusRewardsManager;
IParlayAMMLiquidityPool private parlayAMMLiquidityPool;
bool public readOnlyMode;
bool public closingPeriodInProgress;
uint public closingPeriodPauseTime;
bool public sendCCIPMessage;
address public stakingThalesBettingProxy;
/* ========== CONSTRUCTOR ========== */
function initialize(
address _owner,
address _iEscrowThales, //THALES
address _stakingToken, //THALES
address _feeToken, //sUSD
uint _durationPeriod,
uint _unstakeDurationPeriod,
address _ISNXRewards
) public initializer {
setOwner(_owner);
initNonReentrant();
iEscrowThales = IEscrowThales(_iEscrowThales);
stakingToken = IERC20(_stakingToken);
feeToken = IERC20(_feeToken);
stakingToken.approve(_iEscrowThales, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
durationPeriod = _durationPeriod;
unstakeDurationPeriod = _unstakeDurationPeriod;
fixedPeriodReward = 70000 * 1e18;
periodExtraReward = 21000 * 1e18;
SNXRewards = ISNXRewards(_ISNXRewards);
}
/* ========== VIEWS ========== */
/// @notice Get the total staked amount on the contract
/// @return total staked amount
function totalStakedAmount() external view returns (uint) {
return _totalStakedAmount;
}
/// @notice Get the staked balance for the account
/// @param account to get the staked balance for
/// @return the staked balance for the account
function stakedBalanceOf(address account) external view returns (uint) {
return _stakedBalances[account];
}
/// @notice Get the last period of claimed rewards for the account
/// @param account to get the last period of claimed rewards for
/// @return the last period of claimed rewards for the account
function getLastPeriodOfClaimedRewards(address account) external view returns (uint) {
return _lastRewardsClaimedPeriod[account];
}
/// @notice Get the rewards available for the claim for the account
/// @param account to get the rewards available for the claim for
/// @return the rewards available for the claim for the account
function getRewardsAvailable(address account) external view returns (uint) {
return _calculateAvailableRewardsToClaim(account);
}
/// @notice Get the reward fees available for the claim for the account
/// @param account to get the reward fees available for the claim for
/// @return the rewards fees available for the claim for the account
function getRewardFeesAvailable(address account) external view returns (uint) {
return _calculateAvailableFeesToClaim(account);
}
/// @notice Get the total rewards claimed for the account until now
/// @param account to get the total rewards claimed for
/// @return the total rewards claimed for the account until now
function getAlreadyClaimedRewards(address account) external view returns (uint) {
return stakerLifetimeRewardsClaimed[account];
}
/// @notice Get the rewards funds available on the rewards pool
/// @return the rewards funds available on the rewards pool
function getContractRewardFunds() external view returns (uint) {
return stakingToken.balanceOf(address(ThalesStakingRewardsPool));
}
/// @notice Get the fee funds available on the staking contract
/// @return the fee funds available on the staking contract
function getContractFeeFunds() external view returns (uint) {
return feeToken.balanceOf(address(this));
}
/// @notice Set staking parametars
/// @param _claimEnabled enable/disable claim rewards
/// @param _distributeFeesEnabled enable/disable fees distribution
/// @param _durationPeriod duration of the staking period
/// @param _unstakeDurationPeriod duration of the unstaking cooldown period
/// @param _mergeAccountEnabled enable/disable account merging
/// @param _readOnlyMode enable/disable readonlymode
/// @param _sendCCIPMessage enable/disable sending CCIP message
function setStakingParameters(
bool _claimEnabled,
bool _distributeFeesEnabled,
uint _durationPeriod,
uint _unstakeDurationPeriod,
bool _mergeAccountEnabled,
bool _readOnlyMode,
bool _sendCCIPMessage
) external onlyOwner {
claimEnabled = _claimEnabled;
distributeFeesEnabled = _distributeFeesEnabled;
durationPeriod = _durationPeriod;
unstakeDurationPeriod = _unstakeDurationPeriod;
mergeAccountEnabled = _mergeAccountEnabled;
readOnlyMode = _readOnlyMode;
sendCCIPMessage = _sendCCIPMessage;
emit StakingParametersChanged(
_claimEnabled,
_distributeFeesEnabled,
_durationPeriod,
_unstakeDurationPeriod,
_mergeAccountEnabled,
_readOnlyMode,
_sendCCIPMessage
);
}
/// @notice Set staking rewards parameters
/// @param _fixedReward amount for weekly base rewards pool
/// @param _extraReward amount for weekly bonus rewards pool
/// @param _extraRewardsActive enable/disable bonus rewards
function setStakingRewardsParameters(
uint _fixedReward,
uint _extraReward,
bool _extraRewardsActive
) external onlyOwner {
fixedPeriodReward = _fixedReward;
periodExtraReward = _extraReward;
extraRewardsActive = _extraRewardsActive;
emit StakingRewardsParametersChanged(_fixedReward, _extraReward, _extraRewardsActive);
}
/// @notice Set contract addresses
/// @param _thalesAMM address of Thales AMM contract
/// @param _thalesRangedAMM address of Thales ranged AMM contract
/// @param _sportsAMM address of sport markets AMM contract
/// @param _priceFeed address of price feed contract
/// @param _thalesStakingRewardsPool address of Thales staking rewards pool
/// @param _addressResolver address of address resolver contract
/// @param _stakingThalesBonusRewardsManager manager for TIP-135 gamification systme
function setAddresses(
address _thalesAMM,
address _thalesRangedAMM,
address _sportsAMM,
address _priceFeed,
address _thalesStakingRewardsPool,
address _addressResolver,
address _stakingThalesBonusRewardsManager
) external onlyOwner {
thalesAMM = _thalesAMM;
thalesRangedAMM = _thalesRangedAMM;
sportsAMM = _sportsAMM;
priceFeed = IPriceFeed(_priceFeed);
ThalesStakingRewardsPool = IThalesStakingRewardsPool(_thalesStakingRewardsPool);
addressResolver = IAddressResolver(_addressResolver);
stakingThalesBonusRewardsManager = IStakingThalesBonusRewardsManager(_stakingThalesBonusRewardsManager);
emit AddressesChanged(
_thalesAMM,
_thalesRangedAMM,
_sportsAMM,
_priceFeed,
_thalesStakingRewardsPool,
_addressResolver,
_stakingThalesBonusRewardsManager
);
}
/// @notice sets the stakingThalesBettingProxy address, required for handling ticket claiming via StakingThalesBettingProxy
function setStakingThalesBettingProxy(address _stakingThalesBettingProxy) external onlyOwner {
stakingThalesBettingProxy = _stakingThalesBettingProxy;
emit SetStakingThalesBettingProxy(_stakingThalesBettingProxy);
}
/// @notice Set address of Escrow Thales contract
/// @param _escrowThalesContract address of Escrow Thales contract
function setEscrow(address _escrowThalesContract) external onlyOwner {
if (address(iEscrowThales) != address(0)) {
stakingToken.approve(address(iEscrowThales), 0);
}
iEscrowThales = IEscrowThales(_escrowThalesContract);
emit EscrowChanged(_escrowThalesContract);
}
/// @notice add a sport vault address to count towards gamified staking volume
/// @param _sportVault address to set
/// @param value to set
function setSupportedSportVault(address _sportVault, bool value) external onlyOwner {
supportedSportVault[_sportVault] = value;
emit SupportedSportVaultSet(_sportVault, value);
}
/// @notice add a amm vault address to count towards gamified staking volume
/// @param _ammVault address to set
/// @param value to set
function setSupportedAMMVault(address _ammVault, bool value) external onlyOwner {
supportedAMMVault[_ammVault] = value;
emit SupportedAMMVaultSet(_ammVault, value);
}
/// @notice Set last period timestamp
/// @param _lastPeriodTimestamp last period timestamp to be set
function setLastPeriodTimestamp(uint _lastPeriodTimestamp) external onlyOwner {
require(_lastPeriodTimestamp > (lastPeriodTimeStamp - 5 hours), "Too far back");
lastPeriodTimeStamp = _lastPeriodTimestamp;
emit LastPeriodTimestampSet(_lastPeriodTimestamp);
}
/// @notice Get the base reward amount available for the claim for the account
/// @param account to get the base reward amount available for the claim for
/// @return the base reward amount available for the claim for the account
function getBaseReward(address account) public view returns (uint _baseRewards) {
if (
!((_lastStakingPeriod[account] == periodsOfStaking) ||
(_stakedBalances[account] == 0) ||
(_lastRewardsClaimedPeriod[account] == periodsOfStaking) ||
(totalStakedLastPeriodEnd == 0))
) {
_baseRewards = _stakedBalances[account]
.add(iEscrowThales.getStakedEscrowedBalanceForRewards(account))
.mul(currentPeriodRewards)
.div(totalStakedLastPeriodEnd.add(totalEscrowedLastPeriodEnd));
}
}
/// @notice [DEPRECATED maintained because of IStakingThales] Get the total protocol volume for the account
/// @param account to get the total protocol volume for
/// @return the total protocol volume for the account
function getAMMVolume(address account) external view returns (uint) {
return 0;
}
/// @notice Get the total bonus rewards for the account
/// @param account to get the total bonus rewards for
/// @return the total bonus rewards for the account
function getTotalBonus(address account) public view returns (uint returnValue) {
if (
(address(stakingThalesBonusRewardsManager) != address(0)) && stakingThalesBonusRewardsManager.useNewBonusModel()
) {
returnValue = periodExtraReward
.mul(stakingThalesBonusRewardsManager.getUserRoundBonusShare(account, periodsOfStaking - 1))
.div(ONE);
}
}
/// @notice Get the flag that indicates whether the current period can be closed
/// @return the flag that indicates whether the current period can be closed
function canClosePeriod() external view returns (bool) {
return (startTimeStamp > 0 && (block.timestamp >= lastPeriodTimeStamp.add(durationPeriod)));
}
/* ========== PUBLIC ========== */
/// @notice Start the first staking period
function startStakingPeriod() external onlyOwner {
require(startTimeStamp == 0, "Staking has already started");
startTimeStamp = block.timestamp;
periodsOfStaking = 0;
lastPeriodTimeStamp = startTimeStamp;
_totalRewardsClaimed = 0;
_totalRewardFeesClaimed = 0;
_totalStakedAmount = 0;
_totalEscrowedAmount = 0;
_totalPendingStakeAmount = 0;
emit StakingPeriodStarted();
}
/// @notice Close the current staking period
function closePeriod() external nonReentrant notPaused {
require(startTimeStamp > 0, "Staking period has not started");
require(
block.timestamp >= lastPeriodTimeStamp.add(durationPeriod),
"A full period has not passed since the last closed period"
);
require(!closingPeriodInProgress, "ClosingInProgress");
iEscrowThales.updateCurrentPeriod();
lastPeriodTimeStamp = block.timestamp;
periodsOfStaking = iEscrowThales.currentVestingPeriod();
totalEscrowedLastPeriodEnd = iEscrowThales.totalEscrowedRewards().sub(
iEscrowThales.totalEscrowBalanceNotIncludedInStaking()
);
currentPeriodRewards = fixedPeriodReward;
currentPeriodFees = feeToken.balanceOf(address(this));
totalStakedLastPeriodEnd = _totalStakedAmount;
if (sendCCIPMessage) {
_sendRoundClosingMessageCrosschain();
}
emit ClosedPeriod(periodsOfStaking, lastPeriodTimeStamp);
}
/// @notice if CCIP is configured, this method will send the staking data to relevant chains
function sendRoundClosingMessageCrosschain() external onlyOwner {
_sendRoundClosingMessageCrosschain();
}
function _sendRoundClosingMessageCrosschain() internal {
if (addressResolver.checkIfContractExists("CrossChainCollector")) {
if (!readOnlyMode) {
paused = true;
closingPeriodInProgress = true;
lastPauseTime = block.timestamp;
closingPeriodPauseTime = block.timestamp;
}
ICCIPCollector(addressResolver.getAddress("CrossChainCollector")).sendOnClosePeriod(
totalStakedLastPeriodEnd,
totalEscrowedLastPeriodEnd,
stakingThalesBonusRewardsManager.totalRoundBonusPoints(periodsOfStaking - 1),
_reverseTransformCollateral(feeToken.balanceOf(address(this)))
);
}
}
/// @notice Updating the staking rewards parameters after closed period with the calculated values via CCIP
/// @param _currentPeriodRewards the calculated base rewards to be distributed for the current period on the particular chain
/// @param _extraRewards the calculated extra rewards to be distributed for the current period on the particular chain
/// @param _revShare the calculated revenue share to be distributed for the current period on the particular chain
function updateStakingRewards(
uint _currentPeriodRewards,
uint _extraRewards,
uint _revShare
) external nonReentrant {
if (!readOnlyMode) {
// if it is readOnlyMode==true discard all following the updates
require(msg.sender == addressResolver.getAddress("CrossChainCollector") || msg.sender == owner, "InvCCIP");
require(closingPeriodInProgress, "NotInClosePeriod");
require(
_currentPeriodRewards <= fixedPeriodReward &&
_extraRewards <= fixedPeriodReward &&
_revShare <= 5 * fixedPeriodReward,
"Rejected due to suspicious values"
);
bool safeBoxBufferSet = addressResolver.checkIfContractExists("SafeBoxBuffer");
bool insufficientFundsInBuffer;
uint currentBalance = feeToken.balanceOf(address(this));
currentPeriodFees = _transformCollateral(_revShare);
if (safeBoxBufferSet) {
address safeBoxBuffer = addressResolver.getAddress("SafeBoxBuffer");
if (currentPeriodFees > currentBalance) {
if (feeToken.balanceOf(safeBoxBuffer) < (currentPeriodFees - currentBalance)) {
insufficientFundsInBuffer = true;
} else {
ICCIPCollector(safeBoxBuffer).pullExtraFunds(currentPeriodFees - currentBalance);
}
} else if (currentPeriodFees > 0 && currentPeriodFees < currentBalance) {
feeToken.transfer(safeBoxBuffer, currentBalance - currentPeriodFees);
}
}
currentPeriodRewards = _currentPeriodRewards;
periodExtraReward = _extraRewards;
closingPeriodInProgress = false;
if (closingPeriodPauseTime == lastPauseTime) {
paused = !safeBoxBufferSet || insufficientFundsInBuffer;
}
}
emit ReceivedStakingRewardsUpdate(_currentPeriodRewards, _extraRewards, _transformCollateral(_revShare));
}
/// @notice Stake the amount of staking token to get weekly rewards
/// @param amount to stake
function stake(uint amount) external nonReentrant notPaused {
_stake(amount);
emit Staked(msg.sender, amount);
}
/// @notice Start unstaking cooldown for the amount of staking token
/// @param amount to unstake
function startUnstake(uint amount) external notPaused {
require(amount > 0, "Cannot unstake 0");
require(_stakedBalances[msg.sender] >= amount, "Account doesnt have that much staked");
require(!unstaking[msg.sender], "Account has already triggered unstake cooldown");
if (_calculateAvailableRewardsToClaim(msg.sender) > 0) {
_claimReward(msg.sender);
}
lastUnstakeTime[msg.sender] = block.timestamp;
unstaking[msg.sender] = true;
_totalStakedAmount = _totalStakedAmount.sub(amount);
unstakingAmount[msg.sender] = amount;
_stakedBalances[msg.sender] = _stakedBalances[msg.sender].sub(amount);
// on full unstake add his escrowed balance to totalEscrowBalanceNotIncludedInStaking
if (_stakedBalances[msg.sender] == 0) {
if (iEscrowThales.totalAccountEscrowedAmount(msg.sender) > 0) {
iEscrowThales.addTotalEscrowBalanceNotIncludedInStaking(
iEscrowThales.totalAccountEscrowedAmount(msg.sender)
);
}
}
emit UnstakeCooldown(msg.sender, lastUnstakeTime[msg.sender].add(unstakeDurationPeriod), amount);
}
/// @notice Cancel unstaking cooldown
function cancelUnstake() external notPaused {
require(unstaking[msg.sender], "Account is not unstaking");
// on revert full unstake remove his escrowed balance from totalEscrowBalanceNotIncludedInStaking
_subtractTotalEscrowBalanceNotIncludedInStaking(msg.sender);
if (_calculateAvailableRewardsToClaim(msg.sender) > 0) {
_claimReward(msg.sender);
}
unstaking[msg.sender] = false;
_totalStakedAmount = _totalStakedAmount.add(unstakingAmount[msg.sender]);
_stakedBalances[msg.sender] = _stakedBalances[msg.sender].add(unstakingAmount[msg.sender]);
unstakingAmount[msg.sender] = 0;
emit CancelUnstake(msg.sender);
}
/// @notice Unstake after the cooldown period expired
function unstake() external notPaused {
require(unstaking[msg.sender], "Account has not triggered unstake cooldown");
require(
lastUnstakeTime[msg.sender] < block.timestamp.sub(unstakeDurationPeriod),
"Cannot unstake yet, cooldown not expired."
);
unstaking[msg.sender] = false;
uint unstakeAmount = unstakingAmount[msg.sender];
stakingToken.safeTransfer(msg.sender, unstakeAmount);
unstakingAmount[msg.sender] = 0;
emit Unstaked(msg.sender, unstakeAmount);
}
/// @notice Claim the weekly staking rewards
function claimReward() public nonReentrant notPaused {
_claimReward(msg.sender);
}
/// @notice Claim the weekly staking rewards on behalf of the account
/// @param account to claim on behalf of
function claimRewardOnBehalf(address account) public nonReentrant notPaused {
require(account != address(0) && account != msg.sender, "Invalid address");
require(canClaimOnBehalf[account][msg.sender], "Cannot claim on behalf");
_claimReward(account);
}
/// @notice Update the protocol volume for the account
/// @param account to update the protocol volume for
/// @param amount to add to the existing protocol volume
function updateVolume(address account, uint amount) external {
_updateVolume(account, amount);
}
/// @notice Update the protocol volume for the account
/// @param account to update the protocol volume for
/// @param amount to add to the existing protocol volume
/// @param decimals in which the amount is sent
function updateVolumeAtAmountDecimals(
address account,
uint amount,
uint decimals
) external {
uint actualAmount = amount;
uint stakingCollateralDecimals = ICCIPCollector(address(feeToken)).decimals();
if (decimals < stakingCollateralDecimals) {
actualAmount = amount * 10**(18 - decimals);
} else if (decimals > stakingCollateralDecimals) {
actualAmount = amount / 10**(18 - stakingCollateralDecimals);
}
_updateVolume(account, actualAmount);
}
function _updateVolume(address account, uint amount) internal {
require(account != address(0) && amount > 0, "Invalid params");
if (delegatedVolume[account] != address(0)) {
account = delegatedVolume[account];
}
require(
msg.sender == thalesAMM ||
msg.sender == thalesRangedAMM ||
msg.sender == sportsAMM ||
supportedSportVault[msg.sender] ||
supportedAMMVault[msg.sender],
"Invalid address"
);
amount = _reverseTransformCollateral(amount);
if (address(stakingThalesBonusRewardsManager) != address(0)) {
stakingThalesBonusRewardsManager.storePoints(account, msg.sender, amount, periodsOfStaking);
}
emit AMMVolumeUpdated(account, amount, msg.sender);
}
/// @notice Used by stakingThalesBettingProxy to make a bet with StakedTHALES
/// @param account the staker
/// @param amount to be used for betting
function decreaseAndTransferStakedThales(address account, uint amount) external notPaused onlyStakingProxy {
_modifyStakingBalance(account, amount, true, stakingThalesBettingProxy);
emit StakedThalesDecreased(account, amount);
}
/// @notice Used by stakingThalesBettingProxy to claim a winning bet made with StakedTHALES
/// @param account the staker
/// @param amount that was won
function increaseAndTransferStakedThales(address account, uint amount) external notPaused onlyStakingProxy {
_modifyStakingBalance(account, amount, false, stakingThalesBettingProxy);
emit StakedThalesIncreased(account, amount);
}
function _modifyStakingBalance(
address _account,
uint _amount,
bool isTrade,
address _proxyAccount
) internal {
if (_stakedBalances[_account] > 0 && _lastRewardsClaimedPeriod[_account] != periodsOfStaking) {
_claimReward(_account);
}
if (!isTrade && _stakedBalances[_account] == 0 && _amount > 0) {
//effectively becoming a new staker
_lastStakingPeriod[_account] = periodsOfStaking;
_subtractTotalEscrowBalanceNotIncludedInStaking(_account);
}
if (isTrade) {
require(_stakedBalances[_account] >= _amount.add(ONE), "Insufficient staked amount");
_totalStakedAmount = _totalStakedAmount.sub(_amount);
_stakedBalances[_account] = _stakedBalances[_account].sub(_amount);
stakingToken.safeTransfer(_proxyAccount, _amount);
} else {
_totalStakedAmount = _totalStakedAmount.add(_amount);
_stakedBalances[_account] = _stakedBalances[_account].add(_amount);
stakingToken.safeTransferFrom(_proxyAccount, address(this), _amount);
}
}
modifier onlyStakingProxy() {
require(msg.sender == stakingThalesBettingProxy, "Unsupported staking proxy");
_;
}
/// @notice Merge account to transfer all staking amounts to another account
/// @param destAccount to merge into
function mergeAccount(address destAccount) external notPaused {
require(mergeAccountEnabled, "Merge account is disabled");
require(destAccount != address(0) && destAccount != msg.sender, "Invalid address");
require(
_calculateAvailableRewardsToClaim(msg.sender) == 0 && _calculateAvailableRewardsToClaim(destAccount) == 0,
"Cannot merge, claim rewards on both accounts before merging"
);
require(
!unstaking[msg.sender] && !unstaking[destAccount],
"Cannot merge, cancel unstaking on both accounts before merging"
);
iEscrowThales.mergeAccount(msg.sender, destAccount);
_stakedBalances[destAccount] = _stakedBalances[destAccount].add(_stakedBalances[msg.sender]);
stakerLifetimeRewardsClaimed[destAccount] = stakerLifetimeRewardsClaimed[destAccount].add(
stakerLifetimeRewardsClaimed[msg.sender]
);
stakerFeesClaimed[destAccount] = stakerFeesClaimed[destAccount].add(stakerFeesClaimed[msg.sender]);
_lastRewardsClaimedPeriod[destAccount] = periodsOfStaking;
_lastStakingPeriod[destAccount] = periodsOfStaking;
delete lastUnstakeTime[msg.sender];
delete unstaking[msg.sender];
delete unstakingAmount[msg.sender];
delete _stakedBalances[msg.sender];
delete stakerLifetimeRewardsClaimed[msg.sender];
delete stakerFeesClaimed[msg.sender];
delete _lastRewardsClaimedPeriod[msg.sender];
delete _lastStakingPeriod[msg.sender];
emit AccountMerged(msg.sender, destAccount);
}
/// @notice Set flag to enable/disable claim on behalf of the msg.sender for the account
/// @param account to enable/disable claim on behalf of msg.sender
/// @param _canClaimOnBehalf enable/disable claim on behalf of the msg.sender for the account
function setCanClaimOnBehalf(address account, bool _canClaimOnBehalf) external notPaused {
require(account != address(0) && account != msg.sender, "Invalid address");
canClaimOnBehalf[msg.sender][account] = _canClaimOnBehalf;
emit CanClaimOnBehalfChanged(msg.sender, account, _canClaimOnBehalf);
}
/// @notice delegate your volume to another address
/// @param account address to delegate to
function delegateVolume(address account) external notPaused {
delegatedVolume[msg.sender] = account;
emit DelegatedVolume(account);
}
/// @notice withdraw collateral amount from the contract
/// @param _collateral collateral to withdraw
/// @param _recipient address to send the withdrawing funds to
/// @param _amount to withdraw
function withdrawCollateral(
address _collateral,
address _recipient,
uint _amount
) external onlyOwner {
require(_collateral != address(stakingToken), "Can not withdraw staking token");
IERC20(_collateral).safeTransfer(_recipient, _amount);
}
/* ========== INTERNAL FUNCTIONS ========== */
function _claimReward(address account) internal notPaused {
require(claimEnabled, "Claiming is not enabled.");
require(startTimeStamp > 0, "Staking period has not started");
require(_lastRewardsClaimedPeriod[account] < periodsOfStaking, "Already claimed");
//Calculate rewards
if (distributeFeesEnabled) {
uint availableFeesToClaim = _calculateAvailableFeesToClaim(account);
if (availableFeesToClaim > 0) {
feeToken.safeTransfer(account, availableFeesToClaim);
stakerFeesClaimed[account] = stakerFeesClaimed[account].add(availableFeesToClaim);
_totalRewardFeesClaimed = _totalRewardFeesClaimed.add(availableFeesToClaim);
emit FeeRewardsClaimed(account, availableFeesToClaim);
}
}
uint availableRewardsToClaim = _calculateAvailableRewardsToClaim(account);
if (availableRewardsToClaim > 0) {
// Transfer THALES to Escrow contract
ThalesStakingRewardsPool.addToEscrow(account, availableRewardsToClaim);
// Record the total claimed rewards
stakerLifetimeRewardsClaimed[account] = stakerLifetimeRewardsClaimed[account].add(availableRewardsToClaim);
_totalRewardsClaimed = _totalRewardsClaimed.add(availableRewardsToClaim);
emit RewardsClaimed(account, availableRewardsToClaim, getBaseReward(account));
}
// Update last claiming period
_lastRewardsClaimedPeriod[account] = periodsOfStaking;
}
function _stake(uint amount) internal {
require(startTimeStamp > 0, "Staking period has not started");
require(amount > 0, "Cannot stake 0");
require(!unstaking[msg.sender], "The staker is paused from staking due to unstaking");
_modifyStakingBalance(msg.sender, amount, false, msg.sender);
}
function _subtractTotalEscrowBalanceNotIncludedInStaking(address account) internal {
if (_stakedBalances[account] == 0) {
if (iEscrowThales.totalAccountEscrowedAmount(account) > 0) {
iEscrowThales.subtractTotalEscrowBalanceNotIncludedInStaking(
iEscrowThales.totalAccountEscrowedAmount(account)
);
}
}
}
function _calculateAvailableRewardsToClaim(address account) internal view returns (uint) {
uint baseReward = getBaseReward(account);
if (baseReward == 0) {
return 0;
}
if (!extraRewardsActive) {
return baseReward;
} else {
return baseReward.add(getTotalBonus(account));
}
}
function _calculateAvailableFeesToClaim(address account) internal view returns (uint) {
uint baseReward = getBaseReward(account);
if (baseReward == 0) {
return 0;
}
return
_stakedBalances[account]
.add(iEscrowThales.getStakedEscrowedBalanceForRewards(account))
.mul(currentPeriodFees)
.div(totalStakedLastPeriodEnd.add(totalEscrowedLastPeriodEnd));
}
function _transformCollateral(uint _amount) internal view returns (uint) {
return (ICCIPCollector(address(feeToken)).decimals() == 6) ? _amount / 1e12 : _amount;
}
function _reverseTransformCollateral(uint _amount) internal view returns (uint) {
return (ICCIPCollector(address(feeToken)).decimals() == 6) ? _amount * 1e12 : _amount;
}
/* ========== EVENTS ========== */
event RewardAdded(uint reward);
event Staked(address user, uint amount);
event StakedOnBehalf(address user, address staker, uint amount);
event ClosedPeriod(uint PeriodOfStaking, uint lastPeriodTimeStamp);
event RewardsClaimed(address account, uint unclaimedReward, uint baseRewards);
event FeeRewardsClaimed(address account, uint unclaimedFees);
event UnstakeCooldown(address account, uint cooldownTime, uint amount);
event CancelUnstake(address account);
event Unstaked(address account, uint unstakeAmount);
event StakingParametersChanged(
bool claimEnabled,
bool distributeFeesEnabled,
uint durationPeriod,
uint unstakeDurationPeriod,
bool mergeAccountEnabled,
bool readOnlyMode,
bool sendCCIPMessage
);
event StakingRewardsParametersChanged(uint fixedPeriodReward, uint periodExtraReward, bool extraRewardsActive);
event AddressesChanged(
address thalesAMM,
address thalesRangedAMM,
address sportsAMM,
address priceFeed,
address ThalesStakingRewardsPool,
address addressResolver,
address stakingThalesBonusRewardsManager
);
event ReceivedStakingRewardsUpdate(uint _currentPeriodRewards, uint _extraRewards, uint _revShare);
event EscrowChanged(address newEscrow);
event SetStakingThalesBettingProxy(address stakingThalesBettingProxy);
event StakingPeriodStarted();
event AMMVolumeUpdated(address account, uint amount, address source);
event AccountMerged(address srcAccount, address destAccount);
event DelegatedVolume(address destAccount);
event CanClaimOnBehalfChanged(address sender, address account, bool canClaimOnBehalf);
event SupportedAMMVaultSet(address vault, bool value);
event SupportedSportVaultSet(address vault, bool value);
event LastPeriodTimestampSet(uint lastPeriodTimestamp);
event StakedThalesIncreased(address account, uint amount);
event StakedThalesDecreased(address account, uint amount);
}pragma solidity ^0.5.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}pragma solidity ^0.5.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, "SafeMath: division by zero");
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.5.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier
* available, which can be aplied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*/
contract ProxyReentrancyGuard {
/// @dev counter to allow mutex lock with only one SSTORE operation
uint256 private _guardCounter;
bool private _initialized;
function initNonReentrant() public {
require(!_initialized, "Already initialized");
_initialized = true;
_guardCounter = 1;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_guardCounter += 1;
uint256 localCounter = _guardCounter;
_;
require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;
// Clone of syntetix contract without constructor
contract ProxyOwned {
address public owner;
address public nominatedOwner;
bool private _initialized;
bool private _transferredAtInit;
function setOwner(address _owner) public {
require(_owner != address(0), "Owner address cannot be 0");
require(!_initialized, "Already initialized, use nominateNewOwner");
_initialized = true;
owner = _owner;
emit OwnerChanged(address(0), _owner);
}
function nominateNewOwner(address _owner) external onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external {
require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
function transferOwnershipAtInit(address proxyAddress) external onlyOwner {
require(proxyAddress != address(0), "Invalid address");
require(!_transferredAtInit, "Already transferred");
owner = proxyAddress;
_transferredAtInit = true;
emit OwnerChanged(owner, proxyAddress);
}
modifier onlyOwner {
_onlyOwner();
_;
}
function _onlyOwner() private view {
require(msg.sender == owner, "Only the contract owner may perform this action");
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;
// Inheritance
import "./ProxyOwned.sol";
// Clone of syntetix contract without constructor
contract ProxyPausable is ProxyOwned {
uint public lastPauseTime;
bool public paused;
/**
* @notice Change the paused state of the contract
* @dev Only the contract owner may call this.
*/
function setPaused(bool _paused) external onlyOwner {
// Ensure we're actually changing the state before we do anything
if (_paused == paused) {
return;
}
// Set our paused state.
paused = _paused;
// If applicable, set the last pause time.
if (paused) {
lastPauseTime = block.timestamp;
}
// Let everyone know that our pause state has changed.
emit PauseChanged(paused);
}
event PauseChanged(bool isPaused);
modifier notPaused {
require(!paused, "This action cannot be performed while the contract is paused");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.4.24 <0.7.0;
/**
* @title Initializable
*
* @dev Helper contract to support initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* WARNING: Unlike constructors, initializer functions must be manually
* invoked. This applies both to deploying an Initializable contract, as well
* as extending an Initializable contract via inheritance.
* WARNING: When used with inheritance, manual care must be taken to not invoke
* a parent initializer twice, or ensure that all initializers are idempotent,
* because this is not dealt with automatically as with constructors.
*/
contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private initializing;
/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
// Reserved storage space to allow for layout changes in the future.
uint256[50] private ______gap;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface IEscrowThales {
/* ========== VIEWS / VARIABLES ========== */
function getStakerPeriod(address account, uint index) external view returns (uint);
function getStakerAmounts(address account, uint index) external view returns (uint);
function totalAccountEscrowedAmount(address account) external view returns (uint);
function getStakedEscrowedBalanceForRewards(address account) external view returns (uint);
function totalEscrowedRewards() external view returns (uint);
function totalEscrowBalanceNotIncludedInStaking() external view returns (uint);
function currentVestingPeriod() external view returns (uint);
function updateCurrentPeriod() external returns (bool);
function claimable(address account) external view returns (uint);
function addToEscrow(address account, uint amount) external;
function vest(uint amount) external returns (bool);
function addTotalEscrowBalanceNotIncludedInStaking(uint amount) external;
function subtractTotalEscrowBalanceNotIncludedInStaking(uint amount) external;
function mergeAccount(address srcAccount, address destAccount) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface IStakingThales {
function updateVolume(address account, uint amount) external;
function updateStakingRewards(
uint _currentPeriodRewards,
uint _extraRewards,
uint _revShare
) external;
/* ========== VIEWS / VARIABLES ========== */
function totalStakedAmount() external view returns (uint);
function stakedBalanceOf(address account) external view returns (uint);
function currentPeriodRewards() external view returns (uint);
function currentPeriodFees() external view returns (uint);
function getLastPeriodOfClaimedRewards(address account) external view returns (uint);
function getRewardsAvailable(address account) external view returns (uint);
function getRewardFeesAvailable(address account) external view returns (uint);
function getAlreadyClaimedRewards(address account) external view returns (uint);
function getContractRewardFunds() external view returns (uint);
function getContractFeeFunds() external view returns (uint);
function getAMMVolume(address account) external view returns (uint);
function decreaseAndTransferStakedThales(address account, uint amount) external;
function increaseAndTransferStakedThales(address account, uint amount) external;
function updateVolumeAtAmountDecimals(
address account,
uint amount,
uint decimals
) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface ISNXRewards {
/* ========== VIEWS / VARIABLES ========== */
function collateralisationRatioAndAnyRatesInvalid(address account) external view returns (uint, bool);
function debtBalanceOf(address _issuer, bytes32 currencyKey) external view returns (uint);
function issuanceRatio() external view returns (uint);
function setCRatio(address account, uint _c_ratio) external;
function setIssuanceRatio(uint _issuanceRation) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
pragma experimental ABIEncoderV2;
import "../interfaces/IPassportPosition.sol";
interface IThalesRoyale {
/* ========== VIEWS / VARIABLES ========== */
function getBuyInAmount() external view returns (uint);
function season() external view returns (uint);
function tokenSeason(uint tokenId) external view returns (uint);
function seasonFinished(uint _season) external view returns (bool);
function roundInASeason(uint _round) external view returns (uint);
function roundResultPerSeason(uint _season, uint round) external view returns (uint);
function isTokenAliveInASpecificSeason(uint tokenId, uint _season) external view returns (bool);
function hasParticipatedInCurrentOrLastRoyale(address _player) external view returns (bool);
function getTokenPositions(uint tokenId) external view returns (IPassportPosition.Position[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface IPriceFeed {
// Structs
struct RateAndUpdatedTime {
uint216 rate;
uint40 time;
}
// Mutative functions
function addAggregator(bytes32 currencyKey, address aggregatorAddress) external;
function removeAggregator(bytes32 currencyKey) external;
// Views
function rateForCurrency(bytes32 currencyKey) external view returns (uint);
function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time);
function getRates() external view returns (uint[] memory);
function getCurrencies() external view returns (bytes32[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;
interface IThalesStakingRewardsPool {
function addToEscrow(address account, uint amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;
// pragma experimental ABIEncoderV2;
interface IAddressResolver {
/* ========== VIEWS / VARIABLES ========== */
// function getAddress(bytes32 _contractName) external view returns (address contract_);
// function getAddresses(string[] calldata _contractNames) external view returns (address[] memory contracts);
function getAddress(string calldata _contractName) external view returns (address contract_);
function checkIfContractExists(string calldata _contractName) external view returns (bool contractExists);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface ISportsAMMLiquidityPool {
/* ========== VIEWS / VARIABLES ========== */
function isUserLPing(address user) external view returns (bool isUserInLP);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface IThalesAMMLiquidityPool {
/* ========== VIEWS / VARIABLES ========== */
function isUserLPing(address user) external view returns (bool isUserInLP);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface IParlayAMMLiquidityPool {
function commitTrade(address market, uint amountToMint) external;
function getMarketRound(address market) external view returns (uint _round);
function getMarketPool(address market) external view returns (address roundPool);
function transferToPool(address market, uint amount) external;
function isUserLPing(address user) external view returns (bool isUserInLP);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
import "./IPriceFeed.sol";
interface IThalesAMM {
enum Position {
Up,
Down
}
function manager() external view returns (address);
function availableToBuyFromAMM(address market, Position position) external view returns (uint);
function impliedVolatilityPerAsset(bytes32 oracleKey) external view returns (uint);
function buyFromAmmQuote(
address market,
Position position,
uint amount
) external view returns (uint);
function buyFromAMM(
address market,
Position position,
uint amount,
uint expectedPayout,
uint additionalSlippage
) external returns (uint);
function availableToSellToAMM(address market, Position position) external view returns (uint);
function sellToAmmQuote(
address market,
Position position,
uint amount
) external view returns (uint);
function sellToAMM(
address market,
Position position,
uint amount,
uint expectedPayout,
uint additionalSlippage
) external returns (uint);
function isMarketInAMMTrading(address market) external view returns (bool);
function price(address market, Position position) external view returns (uint);
function buyPriceImpact(
address market,
Position position,
uint amount
) external view returns (int);
function sellPriceImpact(
address market,
Position position,
uint amount
) external view returns (int);
function priceFeed() external view returns (IPriceFeed);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
import "../interfaces/IPositionalMarket.sol";
interface IPositionalMarketManager {
/* ========== VIEWS / VARIABLES ========== */
function durations() external view returns (uint expiryDuration, uint maxTimeToMaturity);
function capitalRequirement() external view returns (uint);
function marketCreationEnabled() external view returns (bool);
function onlyAMMMintingAndBurning() external view returns (bool);
function transformCollateral(uint value) external view returns (uint);
function reverseTransformCollateral(uint value) external view returns (uint);
function totalDeposited() external view returns (uint);
function numActiveMarkets() external view returns (uint);
function activeMarkets(uint index, uint pageSize) external view returns (address[] memory);
function numMaturedMarkets() external view returns (uint);
function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory);
function isActiveMarket(address candidate) external view returns (bool);
function isKnownMarket(address candidate) external view returns (bool);
function getThalesAMM() external view returns (address);
/* ========== MUTATIVE FUNCTIONS ========== */
function createMarket(
bytes32 oracleKey,
uint strikePrice,
uint maturity,
uint initialMint // initial sUSD to mint options for,
) external returns (IPositionalMarket);
function resolveMarket(address market) external;
function expireMarkets(address[] calldata market) external;
function transferSusdTo(
address sender,
address receiver,
uint amount
) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface IStakingThalesBonusRewardsManager {
function storePoints(
address user,
address origin,
uint basePoins,
uint round
) external;
function getUserRoundBonusShare(address user, uint round) external view returns (uint);
function useNewBonusModel() external view returns (bool);
function totalRoundBonusPoints(uint round) external view returns (uint);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface ICCIPCollector {
function sendOnClosePeriod(
uint _totalStakedLastPeriodEnd,
uint _totalEscrowedLastPeriodEnd,
uint _totalBonusPointsInRound,
uint _revShare
) external;
function pullExtraFunds(uint _amount) external;
function decimals() external view returns (uint);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface IStakingThalesBettingProxy {
function numOfActiveTicketsPerUser(address _user) external view returns (uint);
}pragma solidity ^0.5.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see `ERC20Detailed`.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `Transfer` event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through `transferFrom`. This is
* zero by default.
*
* This value changes when `approve` or `transferFrom` are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* > Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an `Approval` event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `Transfer` event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to `approve`. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}pragma solidity ^0.5.0;
/**
* @dev Collection of functions related to the address type,
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* This test is non-exhaustive, and there may be false-negatives: during the
* execution of a contract's constructor, its address will be reported as
* not containing a contract.
*
* > It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*/
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
interface IPassportPosition {
struct Position {
uint round;
uint position;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
import "../interfaces/IPositionalMarketManager.sol";
import "../interfaces/IPosition.sol";
import "../interfaces/IPriceFeed.sol";
interface IPositionalMarket {
/* ========== TYPES ========== */
enum Phase {
Trading,
Maturity,
Expiry
}
enum Side {
Up,
Down
}
/* ========== VIEWS / VARIABLES ========== */
function getOptions() external view returns (IPosition up, IPosition down);
function times() external view returns (uint maturity, uint destructino);
function getOracleDetails()
external
view
returns (
bytes32 key,
uint strikePrice,
uint finalPrice
);
function fees() external view returns (uint poolFee, uint creatorFee);
function deposited() external view returns (uint);
function creator() external view returns (address);
function resolved() external view returns (bool);
function phase() external view returns (Phase);
function oraclePrice() external view returns (uint);
function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt);
function canResolve() external view returns (bool);
function result() external view returns (Side);
function balancesOf(address account) external view returns (uint up, uint down);
function totalSupplies() external view returns (uint up, uint down);
function getMaximumBurnable(address account) external view returns (uint amount);
/* ========== MUTATIVE FUNCTIONS ========== */
function mint(uint value) external;
function exerciseOptions() external returns (uint);
function burnOptions(uint amount) external;
function burnOptionsMaximum() external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;
import "./IPositionalMarket.sol";
interface IPosition {
/* ========== VIEWS / VARIABLES ========== */
function getBalanceOf(address account) external view returns (uint);
function getTotalSupply() external view returns (uint);
function exerciseWithAmount(address claimant, uint amount) external;
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"source","type":"address"}],"name":"AMMVolumeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"srcAccount","type":"address"},{"indexed":false,"internalType":"address","name":"destAccount","type":"address"}],"name":"AccountMerged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"thalesAMM","type":"address"},{"indexed":false,"internalType":"address","name":"thalesRangedAMM","type":"address"},{"indexed":false,"internalType":"address","name":"sportsAMM","type":"address"},{"indexed":false,"internalType":"address","name":"priceFeed","type":"address"},{"indexed":false,"internalType":"address","name":"ThalesStakingRewardsPool","type":"address"},{"indexed":false,"internalType":"address","name":"addressResolver","type":"address"},{"indexed":false,"internalType":"address","name":"stakingThalesBonusRewardsManager","type":"address"}],"name":"AddressesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"canClaimOnBehalf","type":"bool"}],"name":"CanClaimOnBehalfChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"CancelUnstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"PeriodOfStaking","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastPeriodTimeStamp","type":"uint256"}],"name":"ClosedPeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"destAccount","type":"address"}],"name":"DelegatedVolume","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newEscrow","type":"address"}],"name":"EscrowChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"unclaimedFees","type":"uint256"}],"name":"FeeRewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lastPeriodTimestamp","type":"uint256"}],"name":"LastPeriodTimestampSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PauseChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_currentPeriodRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_extraRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_revShare","type":"uint256"}],"name":"ReceivedStakingRewardsUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"unclaimedReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseRewards","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"stakingThalesBettingProxy","type":"address"}],"name":"SetStakingThalesBettingProxy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakedOnBehalf","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakedThalesDecreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakedThalesIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"claimEnabled","type":"bool"},{"indexed":false,"internalType":"bool","name":"distributeFeesEnabled","type":"bool"},{"indexed":false,"internalType":"uint256","name":"durationPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakeDurationPeriod","type":"uint256"},{"indexed":false,"internalType":"bool","name":"mergeAccountEnabled","type":"bool"},{"indexed":false,"internalType":"bool","name":"readOnlyMode","type":"bool"},{"indexed":false,"internalType":"bool","name":"sendCCIPMessage","type":"bool"}],"name":"StakingParametersChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingPeriodStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fixedPeriodReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"periodExtraReward","type":"uint256"},{"indexed":false,"internalType":"bool","name":"extraRewardsActive","type":"bool"}],"name":"StakingRewardsParametersChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"SupportedAMMVaultSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"SupportedSportVaultSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"cooldownTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnstakeCooldown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"unstakeAmount","type":"uint256"}],"name":"Unstaked","type":"event"},{"constant":true,"inputs":[],"name":"ThalesStakingRewardsPool","outputs":[{"internalType":"contract IThalesStakingRewardsPool","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"canClaimOnBehalf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canClosePeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"cancelUnstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"claimEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"claimReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"claimRewardOnBehalf","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"closePeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"closingPeriodInProgress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"closingPeriodPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentPeriodFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentPeriodRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decreaseAndTransferStakedThales","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegateVolume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegatedVolume","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"distributeFeesEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"durationPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"extraRewardsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"fixedPeriodReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAMMVolume","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAlreadyClaimedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getBaseReward","outputs":[{"internalType":"uint256","name":"_baseRewards","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractFeeFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractRewardFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getLastPeriodOfClaimedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getRewardFeesAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getRewardsAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getTotalBonus","outputs":[{"internalType":"uint256","name":"returnValue","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"iEscrowThales","outputs":[{"internalType":"contract IEscrowThales","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increaseAndTransferStakedThales","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"initNonReentrant","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_iEscrowThales","type":"address"},{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_feeToken","type":"address"},{"internalType":"uint256","name":"_durationPeriod","type":"uint256"},{"internalType":"uint256","name":"_unstakeDurationPeriod","type":"uint256"},{"internalType":"address","name":"_ISNXRewards","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"lastPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastPeriodTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastUnstakeTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"destAccount","type":"address"}],"name":"mergeAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"mergeAccountEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"periodExtraReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"periodsOfStaking","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"priceFeed","outputs":[{"internalType":"contract IPriceFeed","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"readOnlyMode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sendCCIPMessage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"sendRoundClosingMessageCrosschain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_thalesAMM","type":"address"},{"internalType":"address","name":"_thalesRangedAMM","type":"address"},{"internalType":"address","name":"_sportsAMM","type":"address"},{"internalType":"address","name":"_priceFeed","type":"address"},{"internalType":"address","name":"_thalesStakingRewardsPool","type":"address"},{"internalType":"address","name":"_addressResolver","type":"address"},{"internalType":"address","name":"_stakingThalesBonusRewardsManager","type":"address"}],"name":"setAddresses","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"_canClaimOnBehalf","type":"bool"}],"name":"setCanClaimOnBehalf","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_escrowThalesContract","type":"address"}],"name":"setEscrow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_lastPeriodTimestamp","type":"uint256"}],"name":"setLastPeriodTimestamp","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_claimEnabled","type":"bool"},{"internalType":"bool","name":"_distributeFeesEnabled","type":"bool"},{"internalType":"uint256","name":"_durationPeriod","type":"uint256"},{"internalType":"uint256","name":"_unstakeDurationPeriod","type":"uint256"},{"internalType":"bool","name":"_mergeAccountEnabled","type":"bool"},{"internalType":"bool","name":"_readOnlyMode","type":"bool"},{"internalType":"bool","name":"_sendCCIPMessage","type":"bool"}],"name":"setStakingParameters","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_fixedReward","type":"uint256"},{"internalType":"uint256","name":"_extraReward","type":"uint256"},{"internalType":"bool","name":"_extraRewardsActive","type":"bool"}],"name":"setStakingRewardsParameters","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_stakingThalesBettingProxy","type":"address"}],"name":"setStakingThalesBettingProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_ammVault","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setSupportedAMMVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_sportVault","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setSupportedSportVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sportsAMM","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"stakedBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakerFeesClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakerLifetimeRewardsClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stakingThalesBettingProxy","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stakingThalesBonusRewardsManager","outputs":[{"internalType":"contract IStakingThalesBonusRewardsManager","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"startStakingPeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"startTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"startUnstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedAMMVault","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedSportVault","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"thalesAMM","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"thalesRangedAMM","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalEscrowedLastPeriodEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStakedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStakedLastPeriodEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"proxyAddress","type":"address"}],"name":"transferOwnershipAtInit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"unstakeDurationPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unstaking","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unstakingAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_currentPeriodRewards","type":"uint256"},{"internalType":"uint256","name":"_extraRewards","type":"uint256"},{"internalType":"uint256","name":"_revShare","type":"uint256"}],"name":"updateStakingRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"updateVolume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"decimals","type":"uint256"}],"name":"updateVolumeAtAmountDecimals","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawCollateral","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506152ce806100206000396000f3fe608060405234801561001057600080fd5b50600436106104cd5760003560e01c806364c8359111610283578063a4bce4ac1161015c578063c9925288116100ce578063e81a252611610092578063e81a252614610c93578063eaa8ba7f14610cb9578063ebc7977214610d11578063eff4a90014610d19578063f38d00f014610d45578063fd143c0b14610d4d576104cd565b8063c992528814610c4d578063cb8d751a14610c55578063d66e067714610c7b578063df52461a14610c83578063e11cd05514610c8b576104cd565b8063ba47a5d911610120578063ba47a5d914610ba5578063bd45006214610bad578063c10c354614610bd3578063c3b83f5f14610bf9578063c5335ac614610c1f578063c731a3d114610c45576104cd565b8063a4bce4ac14610b68578063a5b935a414610b70578063a694fc3a14610b78578063afac7fb114610b95578063b88a802f14610b9d576104cd565b80638759263f116101f557806393eb2e66116101b957806393eb2e6614610aac57806395910db214610ab45780639a09edab14610abc5780639a109bc214610ae2578063a00159a814610b08578063a2dd835f14610b36576104cd565b80638759263f14610a025780638a0ac0ff14610a2b5780638a239de814610a765780638da5cb5b14610a9c57806391b4ded914610aa4576104cd565b806372f702f31161024757806372f702f3146109b4578063741bef1a146109bc57806379ba5097146109c45780637a685677146109cc5780637c17f6fc146109f2578063847ae197146109fa576104cd565b806364c83591146108e157806366c4c8c7146109075780636801d9fb1461090f5780636dca3b02146109355780636e3c0d8714610989576104cd565b806335e5d29a116103b557806353cf411511610327578063605f5aa9116102eb578063605f5aa91461086f578063608daf891461089b57806361c01db7146108a357806362139e0e146108c95780636282719e146108d1578063647846a5146108d9576104cd565b806353cf41151461082157806356091ad114610829578063567e98f914610857578063572e36e61461085f5780635c975abb14610867576104cd565b80634ab17969116103795780634ab17969146107ad5780634c4e75df146107b55780634ed25b43146107db578063505b1497146107e3578063507a73281461081157806353a47bb714610819576104cd565b806335e5d29a1461073457806336468b5a146107515780633faae53414610777578063406a77661461077f57806347dda6ec14610787576104cd565b80631cb70a951161044e5780632ae8bdfe116104125780632ae8bdfe146106855780632d287886146106bb5780632def6620146106e15780632f324158146106e9578063331e03a8146106f157806334dfb26814610717576104cd565b80631cb70a95146106495780632007435414610651578063203d3718146106595780632145e92e146106615780632866ed2114610669576104cd565b806315da50641161049557806315da5064146105a85780631627540c146105b057806316765391146105d657806316c38b3c146105fc57806317433c911461061b576104cd565b806302c7739b146104d2578063080e2b47146105005780630fe62190146105385780631314f7591461055c57806313af403514610582575b600080fd5b6104fe600480360360408110156104e857600080fd5b506001600160a01b038135169060200135610d73565b005b6105266004803603602081101561051657600080fd5b50356001600160a01b0316610d81565b60408051918252519081900360200190f35b610540610d93565b604080516001600160a01b039092168252519081900360200190f35b6105266004803603602081101561057257600080fd5b50356001600160a01b0316610da7565b6104fe6004803603602081101561059857600080fd5b50356001600160a01b0316610dba565b610526610ecf565b6104fe600480360360208110156105c657600080fd5b50356001600160a01b0316610ed5565b610526600480360360208110156105ec57600080fd5b50356001600160a01b0316610f31565b6104fe6004803603602081101561061257600080fd5b50351515610f4c565b6104fe6004803603604081101561063157600080fd5b506001600160a01b0381351690602001351515610fc6565b610540611032565b610526611046565b61054061104c565b6104fe61105b565b61067161106d565b604080519115158252519081900360200190f35b6104fe6004803603606081101561069b57600080fd5b506001600160a01b03813581169160208101359091169060400135611076565b610526600480360360208110156106d157600080fd5b50356001600160a01b0316611100565b6104fe611112565b610540611292565b6105266004803603602081101561070757600080fd5b50356001600160a01b03166112a6565b6104fe6004803603602081101561072d57600080fd5b50356112b8565b6104fe6004803603602081101561074a57600080fd5b5035611646565b6105266004803603602081101561076757600080fd5b50356001600160a01b03166116d2565b61052661181d565b6105266118a7565b6106716004803603602081101561079d57600080fd5b50356001600160a01b03166118ad565b6104fe6118c2565b610526600480360360208110156107cb57600080fd5b50356001600160a01b0316611a42565b610526611a5d565b6104fe600480360360408110156107f957600080fd5b506001600160a01b0381351690602001351515611a63565b6104fe611b7e565b610540611fdb565b610671611fea565b6104fe6004803603604081101561083f57600080fd5b506001600160a01b0381351690602001351515611ff3565b61052661205f565b610540612065565b610671612074565b6104fe6004803603604081101561088557600080fd5b506001600160a01b03813516906020013561207d565b610526612189565b6104fe600480360360208110156108b957600080fd5b50356001600160a01b031661218f565b6105266122fe565b6104fe612304565b6105406123b6565b610526600480360360208110156108f757600080fd5b50356001600160a01b03166123c5565b6105406123d7565b6104fe6004803603602081101561092557600080fd5b50356001600160a01b03166123e6565b6104fe600480360360e081101561094b57600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013582169160808201359160a08101359160c0909101351661244a565b6104fe6004803603606081101561099f57600080fd5b50803590602081013590604001351515612606565b61054061266f565b61054061267e565b6104fe61268d565b610526600480360360208110156109e257600080fd5b50356001600160a01b0316612749565b610526612754565b61067161275a565b6104fe60048036036060811015610a1857600080fd5b5080359060208101359060400135612763565b6104fe600480360360e0811015610a4157600080fd5b5080351515906020810135151590604081013590606081013590608081013515159060a081013515159060c001351515612d57565b61052660048036036020811015610a8c57600080fd5b50356001600160a01b0316612e27565b610540612e42565b610526612e51565b610526612e57565b610526612e5d565b61052660048036036020811015610ad257600080fd5b50356001600160a01b0316612e63565b61052660048036036020811015610af857600080fd5b50356001600160a01b0316612e69565b61067160048036036040811015610b1e57600080fd5b506001600160a01b0381358116916020013516612faf565b6104fe60048036036060811015610b4c57600080fd5b506001600160a01b038135169060208101359060400135612fcf565b61067161308b565b610671613094565b6104fe60048036036020811015610b8e57600080fd5b50356130a4565b610671613179565b6104fe6131a5565b61052661323f565b61054060048036036020811015610bc357600080fd5b50356001600160a01b0316613245565b6104fe60048036036020811015610be957600080fd5b50356001600160a01b0316613260565b6104fe60048036036020811015610c0f57600080fd5b50356001600160a01b0316613367565b6104fe60048036036020811015610c3557600080fd5b50356001600160a01b0316613486565b61067161383c565b610540613845565b61067160048036036020811015610c6b57600080fd5b50356001600160a01b0316613854565b610526613869565b6106716138b4565b6105266138c4565b6104fe60048036036020811015610ca957600080fd5b50356001600160a01b03166138ca565b6104fe600480360360e0811015610ccf57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c0909101351661396f565b6104fe613a64565b6104fe60048036036040811015610d2f57600080fd5b506001600160a01b038135169060200135613ac7565b610526613bd3565b61067160048036036020811015610d6357600080fd5b50356001600160a01b0316613bd9565b610d7d8282613bee565b5050565b604c6020526000908152604090205481565b607a5461010090046001600160a01b031681565b6000610db282613e1e565b90505b919050565b6001600160a01b038116610e15576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b603454600160a01b900460ff1615610e5e5760405162461bcd60e51b8152600401808060200182810382526029815260200180614fe36029913960400191505060405180910390fd5b6034805460ff60a01b1916600160a01b179055603380546001600160a01b0383166001600160a01b031990911681179091556040805160008152602081019290925280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60465481565b610edd613f09565b603480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b6001600160a01b031660009081526056602052604090205490565b610f54613f09565b60385460ff1615158115151415610f6a57610fc3565b6038805460ff1916821515179081905560ff1615610f8757426037555b6038546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b610fce613f09565b6001600160a01b038216600081815260736020908152604091829020805460ff191685151590811790915582519384529083015280517fd2a8401466e7483577592b4b5160af1ba59060100f12387853477637096cfb919281900390910190a15050565b605b5461010090046001600160a01b031681565b603f5481565b6066546001600160a01b031681565b611063613f09565b61106b613f52565b565b604a5460ff1681565b61107e613f09565b6039546001600160a01b03848116911614156110e1576040805162461bcd60e51b815260206004820152601e60248201527f43616e206e6f74207769746864726177207374616b696e6720746f6b656e0000604482015290519081900360640190fd5b6110fb6001600160a01b038416838363ffffffff61422f16565b505050565b60556020526000908152604090205481565b60385460ff16156111545760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b3360009081526054602052604090205460ff166111a25760405162461bcd60e51b815260040180806020018281038252602a815260200180615035602a913960400191505060405180910390fd5b6041546111b690429063ffffffff61428116565b33600090815260536020526040902054106112025760405162461bcd60e51b815260040180806020018281038252602981526020018061500c6029913960400191505060405180910390fd5b336000818152605460209081526040808320805460ff1916905560559091529020546039549091611243916001600160a01b0316908363ffffffff61422f16565b336000818152605560209081526040808320929092558151928352820183905280517f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759281900390910190a150565b60385461010090046001600160a01b031681565b60536020526000908152604090205481565b60385460ff16156112fa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b60008111611342576040805162461bcd60e51b815260206004820152601060248201526f043616e6e6f7420756e7374616b6520360841b604482015290519081900360640190fd5b336000908152605660205260409020548111156113905760405162461bcd60e51b81526004018080602001828103825260248152602001806151f06024913960400191505060405180910390fd5b3360009081526054602052604090205460ff16156113df5760405162461bcd60e51b815260040180806020018281038252602e815260200180615148602e913960400191505060405180910390fd5b60006113ea336142e3565b11156113f9576113f933614332565b33600090815260536020908152604080832042905560549091529020805460ff19166001179055604d54611433908263ffffffff61428116565b604d553360009081526055602090815260408083208490556056909152902054611463908263ffffffff61428116565b3360009081526056602052604090208190556115d557603854604080516334c78ae560e11b8152336004820152905160009261010090046001600160a01b03169163698f15ca916024808301926020929190829003018186803b1580156114c957600080fd5b505afa1580156114dd573d6000803e3d6000fd5b505050506040513d60208110156114f357600080fd5b505111156115d557603854604080516334c78ae560e11b815233600482015290516101009092046001600160a01b031691635817d04291839163698f15ca91602480820192602092909190829003018186803b15801561155257600080fd5b505afa158015611566573d6000803e3d6000fd5b505050506040513d602081101561157c57600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b1580156115bc57600080fd5b505af11580156115d0573d6000803e3d6000fd5b505050505b604154336000818152605360205260409020547f30797de805f090008d8b19fa0c6f92d0f164789f64d6f7a1b097fbf0b1abac6b9261161a919063ffffffff6146ae16565b604080516001600160a01b0390931683526020830191909152818101849052519081900360600190a150565b61164e613f09565b614650603f54038111611697576040805162461bcd60e51b815260206004820152600c60248201526b546f6f20666172206261636b60a01b604482015290519081900360640190fd5b603f8190556040805182815290517fd1956985dae3dbe5da7d4db0d0abc90d01284cf79627ffef5538d2cd006901049181900360200190a150565b6077546000906001600160a01b0316158015906117655750607760009054906101000a90046001600160a01b03166001600160a01b0316635bd90b486040518163ffffffff1660e01b815260040160206040518083038186803b15801561173857600080fd5b505afa15801561174c573d6000803e3d6000fd5b505050506040513d602081101561176257600080fd5b50515b15610db557607754603e5460408051638d61c38b60e01b81526001600160a01b03868116600483015260001990930160248201529051610db293670de0b6b3a76400009361181193911691638d61c38b91604480820192602092909190829003018186803b1580156117d657600080fd5b505afa1580156117ea573d6000803e3d6000fd5b505050506040513d602081101561180057600080fd5b50516047549063ffffffff61470816565b9063ffffffff61476116565b603954605b54604080516370a0823160e01b81526101009092046001600160a01b039081166004840152905160009391909116916370a08231916024808301926020929190829003018186803b15801561187657600080fd5b505afa15801561188a573d6000803e3d6000fd5b505050506040513d60208110156118a057600080fd5b5051905090565b60795481565b60736020526000908152604090205460ff1681565b60385460ff16156119045760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b3360009081526054602052604090205460ff16611968576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e74206973206e6f7420756e7374616b696e670000000000000000604482015290519081900360640190fd5b611971336147cb565b600061197c336142e3565b111561198b5761198b33614332565b336000908152605460209081526040808320805460ff191690556055909152902054604d546119bf9163ffffffff6146ae16565b604d55336000908152605560209081526040808320546056909252909120546119ed9163ffffffff6146ae16565b336000818152605660209081526040808320949094556055815283822091909155825191825291517f725ee3b9a70aadcb1e002c94935880d7f515620783a5144c90e39201dc6f92da929181900390910190a1565b6001600160a01b031660009081526057602052604090205490565b60475481565b60385460ff1615611aa55760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b6001600160a01b03821615801590611ac657506001600160a01b0382163314155b611b09576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b3360008181526070602090815260408083206001600160a01b03871680855290835292819020805486151560ff19909116811790915581519485529184019290925282820152517fc939ba7d9b3e1a4e6505db209888366a551f46a85918944eb89becb92289935b9181900360600190a15050565b603580546001019081905560385460ff1615611bcb5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b600060425411611c22576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b604054603f54611c379163ffffffff6146ae16565b421015611c755760405162461bcd60e51b81526004018080602001828103825260398152602001806150dd6039913960400191505060405180910390fd5b607854600160a81b900460ff1615611cc8576040805162461bcd60e51b8152602060048201526011602482015270436c6f73696e67496e50726f677265737360781b604482015290519081900360640190fd5b603860019054906101000a90046001600160a01b03166001600160a01b031663acfabbe46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611d1857600080fd5b505af1158015611d2c573d6000803e3d6000fd5b505050506040513d6020811015611d4257600080fd5b505042603f5560385460408051635d13850560e01b815290516101009092046001600160a01b031691635d13850591600480820192602092909190829003018186803b158015611d9157600080fd5b505afa158015611da5573d6000803e3d6000fd5b505050506040513d6020811015611dbb57600080fd5b5051603e55603854604080516347d3681760e11b81529051611eb89261010090046001600160a01b031691638fa6d02e916004808301926020929190829003018186803b158015611e0b57600080fd5b505afa158015611e1f573d6000803e3d6000fd5b505050506040513d6020811015611e3557600080fd5b50516038546040805163b9d1c70b60e01b815290516101009092046001600160a01b03169163b9d1c70b91600480820192602092909190829003018186803b158015611e8057600080fd5b505afa158015611e94573d6000803e3d6000fd5b505050506040513d6020811015611eaa57600080fd5b50519063ffffffff61428116565b606355604654604355603a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611f0c57600080fd5b505afa158015611f20573d6000803e3d6000fd5b505050506040513d6020811015611f3657600080fd5b5051604455604d54606255607a5460ff1615611f5457611f54613f52565b7f80827f48a8070d07af7887688320aadf44499e3a2751fc41cc965870cf0627d7603e54603f54604051808381526020018281526020019250505060405180910390a16035548114610fc3576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b6034546001600160a01b031681565b60455460ff1681565b611ffb613f09565b6001600160a01b038216600081815260746020908152604091829020805460ff191685151590811790915582519384529083015280517fcf84063977a2a7766d440ee9919a260c5e0add05c19db1f47b31250b89c73e399281900390910190a15050565b604d5490565b6058546001600160a01b031681565b60385460ff1681565b60385460ff16156120bf5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b607a5461010090046001600160a01b0316331461211f576040805162461bcd60e51b8152602060048201526019602482015278556e737570706f72746564207374616b696e672070726f787960381b604482015290519081900360640190fd5b61214182826001607a60019054906101000a90046001600160a01b0316614948565b604080516001600160a01b03841681526020810183905281517f4914c7018facdafd839d7c7a6b61fe4d9efb99adcfa37f98693187e081c893b9929181900390910190a15050565b60625481565b603580546001019081905560385460ff16156121dc5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b6001600160a01b038216158015906121fd57506001600160a01b0382163314155b612240576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b6001600160a01b038216600090815260706020908152604080832033845290915290205460ff166122b1576040805162461bcd60e51b815260206004820152601660248201527521b0b73737ba1031b630b4b69037b7103132b430b63360511b604482015290519081900360640190fd5b6122ba82614332565b6035548114610d7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b60405481565b61230c613f09565b60425415612361576040805162461bcd60e51b815260206004820152601b60248201527f5374616b696e672068617320616c726561647920737461727465640000000000604482015290519081900360640190fd5b4260428190556000603e819055603f9190915560518190556052819055604d819055604e819055604f8190556040517f7c01398e484f9a82feaa276906d5d1f84867a0ff5a5bd9a485d4357f58d401839190a1565b603a546001600160a01b031681565b604b6020526000908152604090205481565b6077546001600160a01b031681565b6123ee613f09565b607a80546001600160a01b0383166101008102610100600160a81b03199092169190911790915560408051918252517f52dc607ac868d5b1fa7bba518a16fe90c6fc54562dcb05e35304ac1d26d32a249181900360200190a150565b600054610100900460ff16806124635750612463614b63565b80612471575060005460ff16155b6124ac5760405162461bcd60e51b815260040180806020018281038252602e8152602001806150af602e913960400191505060405180910390fd5b600054610100900460ff161580156124d7576000805460ff1961ff0019909116610100171660011790555b6124e088610dba565b6124e8613a64565b60388054610100600160a81b0319166101006001600160a01b038a811691820292909217909255603980546001600160a01b03199081168a84161791829055603a80549091168984161790556040805163095ea7b360e01b8152600481019490945260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b15801561257d57600080fd5b505af1158015612591573d6000803e3d6000fd5b505050506040513d60208110156125a757600080fd5b505060408490556041839055690ed2b525841adfc00000604655690472698b413b43200000604755603b80546001600160a01b0319166001600160a01b03841617905580156125fc576000805461ff00191690555b5050505050505050565b61260e613f09565b60468390556047829055605b805482151560ff199091168117909155604080518581526020810185905280820192909252517ff2192442b5560227e5c603bd8ec631a14b2fe42f35cf4e8e2083502de9571bb49181900360600190a1505050565b6039546001600160a01b031681565b603d546001600160a01b031681565b6034546001600160a01b031633146126d65760405162461bcd60e51b8152600401808060200182810382526035815260200180614fae6035913960400191505060405180910390fd5b603354603454604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160348054603380546001600160a01b03199081166001600160a01b03841617909155169055565b6000610db2826142e3565b603e5481565b607a5460ff1681565b6035805460010190819055607854600160a01b900460ff16612cc4576065546040805163bf40fac160e01b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263bf40fac192606480840193919291829003018186803b1580156127ed57600080fd5b505afa158015612801573d6000803e3d6000fd5b505050506040513d602081101561281757600080fd5b50516001600160a01b031633148061283957506033546001600160a01b031633145b612874576040805162461bcd60e51b81526020600482015260076024820152660496e76434349560cc1b604482015290519081900360640190fd5b607854600160a81b900460ff166128c5576040805162461bcd60e51b815260206004820152601060248201526f139bdd125b90db1bdcd954195c9a5bd960821b604482015290519081900360640190fd5b60465484111580156128d957506046548311155b80156128ea57506046546005028211155b6129255760405162461bcd60e51b81526004018080602001828103825260218152602001806152796021913960400191505060405180910390fd5b6065546040805163045f670760e21b8152602060048201819052600d60248301526c29b0b332a137bc213ab33332b960991b604483015291516000936001600160a01b03169263117d9c1c9260648082019391829003018186803b15801561298c57600080fd5b505afa1580156129a0573d6000803e3d6000fd5b505050506040513d60208110156129b657600080fd5b5051603a54604080516370a0823160e01b8152306004820152905192935060009283926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015612a0857600080fd5b505afa158015612a1c573d6000803e3d6000fd5b505050506040513d6020811015612a3257600080fd5b50519050612a3f85614b69565b6044558215612c81576065546040805163bf40fac160e01b8152602060048201819052600d60248301526c29b0b332a137bc213ab33332b960991b604483015291516000936001600160a01b03169263bf40fac19260648082019391829003018186803b158015612aaf57600080fd5b505afa158015612ac3573d6000803e3d6000fd5b505050506040513d6020811015612ad957600080fd5b5051604454909150821015612be057604454603a54604080516370a0823160e01b81526001600160a01b0385811660048301529151938690039391909216916370a08231916024808301926020929190829003018186803b158015612b3d57600080fd5b505afa158015612b51573d6000803e3d6000fd5b505050506040513d6020811015612b6757600080fd5b50511015612b785760019250612bdb565b806001600160a01b0316639ffcb31683604454036040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015612bc257600080fd5b505af1158015612bd6573d6000803e3d6000fd5b505050505b612c7f565b6000604454118015612bf3575081604454105b15612c7f57603a54604480546040805163a9059cbb60e01b81526001600160a01b03868116600483015292870360248201529051919093169263a9059cbb92818101926020929091908290030181600087803b158015612c5257600080fd5b505af1158015612c66573d6000803e3d6000fd5b505050506040513d6020811015612c7c57600080fd5b50505b505b604387905560478690556078805460ff60a81b191690556037546079541415612cc057821580612cae5750815b6038805460ff19169115159190911790555b5050505b7fb4873f5e95851bc84e2c197ca35129e61b53e3525c5d563b4dfd9307833f4dcc8484612cf085614b69565b60408051938452602084019290925282820152519081900360600190a16035548114612d51576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b50505050565b612d5f613f09565b604a805488151560ff1991821681179092556045805489151590831681179091556040888155604188905560718054881515908516811790915560788054881515600160a01b810260ff60a01b1990921691909117909155607a8054881515961686179055825195865260208601939093528482018a905260608501899052608085015260a084019190915260c0830191909152517fd0b7c05d30d50a3a23a9835892652aebc30da318b53c90521825ea7698e590a09181900360e00190a150505050505050565b6001600160a01b03166000908152604b602052604090205490565b6033546001600160a01b031681565b60375481565b60415481565b60635481565b50600090565b603e546001600160a01b03821660009081526061602052604081205490911480612ea957506001600160a01b038216600090815260566020526040902054155b80612ecd5750603e546001600160a01b038316600090815260576020526040902054145b80612ed85750606254155b610db557610db2612ef66063546062546146ae90919063ffffffff16565b604354603854604080516317640e0760e01b81526001600160a01b03888116600483015291516118119493612fa39361010090910416916317640e07916024808301926020929190829003018186803b158015612f5257600080fd5b505afa158015612f66573d6000803e3d6000fd5b505050506040513d6020811015612f7c57600080fd5b50516001600160a01b0388166000908152605660205260409020549063ffffffff6146ae16565b9063ffffffff61470816565b607060209081526000928352604080842090915290825290205460ff1681565b603a546040805163313ce56760e01b8152905184926000926001600160a01b039091169163313ce56791600480820192602092909190829003018186803b15801561301957600080fd5b505afa15801561302d573d6000803e3d6000fd5b505050506040513d602081101561304357600080fd5b505190508083101561305f5782601203600a0a8402915061307a565b8083111561307a5780601203600a0a848161307657fe5b0491505b6130848583613bee565b5050505050565b605b5460ff1681565b607854600160a01b900460ff1681565b603580546001019081905560385460ff16156130f15760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b6130fa82614bf3565b604080513381526020810184905281517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d929181900390910190a16035548114610d7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b6000806042541180156131a05750604054603f5461319c9163ffffffff6146ae16565b4210155b905090565b603580546001019081905560385460ff16156131f25760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b6131fb33614332565b6035548114610fc3576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b60445481565b6072602052600090815260409020546001600160a01b031681565b613268613f09565b60385461010090046001600160a01b03161561330b576039546038546040805163095ea7b360e01b81526101009092046001600160a01b039081166004840152600060248401819052915193169263095ea7b3926044808201936020939283900390910190829087803b1580156132de57600080fd5b505af11580156132f2573d6000803e3d6000fd5b505050506040513d602081101561330857600080fd5b50505b603880546001600160a01b0383166101008102610100600160a81b03199092169190911790915560408051918252517feb1a4b1e230d212e1644ea31e3890084e2fa17ddee990e46a46e198e1728c4a09181900360200190a150565b61336f613f09565b6001600160a01b0381166133bc576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b603454600160a81b900460ff1615613411576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b603380546001600160a01b038084166001600160a01b03199092168217928390556034805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60385460ff16156134c85760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b60715460ff1661351f576040805162461bcd60e51b815260206004820152601960248201527f4d65726765206163636f756e742069732064697361626c656400000000000000604482015290519081900360640190fd5b6001600160a01b0381161580159061354057506001600160a01b0381163314155b613583576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b61358c336142e3565b15801561359f575061359d816142e3565b155b6135da5760405162461bcd60e51b815260040180806020018281038252603b815260200180615214603b913960400191505060405180910390fd5b3360009081526054602052604090205460ff1615801561361357506001600160a01b03811660009081526054602052604090205460ff16155b61364e5760405162461bcd60e51b815260040180806020018281038252603e815260200180615176603e913960400191505060405180910390fd5b60385460408051630282a2ed60e21b81523360048201526001600160a01b038481166024830152915161010090930490911691630a0a8bb49160448082019260009290919082900301818387803b1580156136a857600080fd5b505af11580156136bc573d6000803e3d6000fd5b505033600090815260566020526040808220546001600160a01b03861683529120546136f09350915063ffffffff6146ae16565b6001600160a01b038216600081815260566020908152604080832094909455338252604b90528281205491815291909120546137319163ffffffff6146ae16565b6001600160a01b0382166000818152604b6020908152604080832094909455338252604c90528281205491815291909120546137729163ffffffff6146ae16565b6001600160a01b0382166000818152604c6020818152604080842095909555603e546057808352868520829055606180845287862092909255338086526053845287862086905560548452878620805460ff191690556055845287862086905560568452878620869055604b8452878620869055938352868520859055825285842084905581528483209290925583519081529081019190915281517fa0fc26d627101bedf9c6cedb33e9eeac3fa2a7d508f89b597134bcee1a12d32c929181900390910190a150565b60715460ff1681565b6067546001600160a01b031681565b60546020526000908152604090205460ff1681565b603a54604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561187657600080fd5b607854600160a81b900460ff1681565b60435481565b60385460ff161561390c5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b3360009081526072602090815260409182902080546001600160a01b0319166001600160a01b038516908117909155825190815291517f0c417702befaa0d74611c15e4278a897f344514ffbfbd4ea9a6e9168be46b8da9281900390910190a150565b613977613f09565b605880546001600160a01b03808a166001600160a01b03199283168117909355606680548a83169084168117909155606780548a84169085168117909155603d80548a85169086168117909155605b80548a86166101008102610100600160a81b031990921691909117909155606580548a8716908816811790915560778054968a16969097168617909655604080519788526020880194909452868401929092526060860152608085015260a084019290925260c0830152517fbe8209a2817cacf2137f586f29208a496d2d159efa011f3937e8172892826a9a9181900360e00190a150505050505050565b60365460ff1615613ab2576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6036805460ff19166001908117909155603555565b60385460ff1615613b095760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b607a5461010090046001600160a01b03163314613b69576040805162461bcd60e51b8152602060048201526019602482015278556e737570706f72746564207374616b696e672070726f787960381b604482015290519081900360640190fd5b613b8b82826000607a60019054906101000a90046001600160a01b0316614948565b604080516001600160a01b03841681526020810183905281517f95979d8a89d7d2a9728d0e86dc6a0e3374af9b407d8d978a8f4b583d8a1bfecf929181900390910190a15050565b60425481565b60746020526000908152604090205460ff1681565b6001600160a01b03821615801590613c065750600081115b613c48576040805162461bcd60e51b815260206004820152600e60248201526d496e76616c696420706172616d7360901b604482015290519081900360640190fd5b6001600160a01b038281166000908152607260205260409020541615613c87576001600160a01b03918216600090815260726020526040902054909116905b6058546001600160a01b0316331480613caa57506066546001600160a01b031633145b80613cbf57506067546001600160a01b031633145b80613cd957503360009081526073602052604090205460ff165b80613cf357503360009081526074602052604090205460ff165b613d36576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b613d3f81614cec565b6077549091506001600160a01b031615613dd257607754603e54604080516352a31c0760e01b81526001600160a01b038681166004830152336024830152604482018690526064820193909352905191909216916352a31c0791608480830192600092919082900301818387803b158015613db957600080fd5b505af1158015613dcd573d6000803e3d6000fd5b505050505b604080516001600160a01b038416815260208101839052338183015290517fb43a20c9abfed93eb48264a3acf807336352ba8cb6ee42c1754b1b1b280a20b99181900360600190a15050565b600080613e2a83612e69565b905080613e3b576000915050610db5565b613f02613e556063546062546146ae90919063ffffffff16565b604454603854604080516317640e0760e01b81526001600160a01b03898116600483015291516118119493612fa39361010090910416916317640e07916024808301926020929190829003018186803b158015613eb157600080fd5b505afa158015613ec5573d6000803e3d6000fd5b505050506040513d6020811015613edb57600080fd5b50516001600160a01b0389166000908152605660205260409020549063ffffffff6146ae16565b9392505050565b6033546001600160a01b0316331461106b5760405162461bcd60e51b815260040180806020018281038252602f81526020018061505f602f913960400191505060405180910390fd5b6065546040805163045f670760e21b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263117d9c1c92606480840193919291829003018186803b158015613fc057600080fd5b505afa158015613fd4573d6000803e3d6000fd5b505050506040513d6020811015613fea57600080fd5b50511561106b57607854600160a01b900460ff1661402c576038805460ff191660011790556078805460ff60a81b1916600160a81b1790554260378190556079555b6065546040805163bf40fac160e01b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263bf40fac192606480840193919291829003018186803b15801561409a57600080fd5b505afa1580156140ae573d6000803e3d6000fd5b505050506040513d60208110156140c457600080fd5b5051606254606354607754603e546040805163df022bf560e01b81526000199092016004830152516001600160a01b03958616956334bd229c959493169163df022bf5916024808301926020929190829003018186803b15801561412757600080fd5b505afa15801561413b573d6000803e3d6000fd5b505050506040513d602081101561415157600080fd5b5051603a54604080516370a0823160e01b815230600482015290516141d0926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561419f57600080fd5b505afa1580156141b3573d6000803e3d6000fd5b505050506040513d60208110156141c957600080fd5b5051614cec565b6040518563ffffffff1660e01b815260040180858152602001848152602001838152602001828152602001945050505050600060405180830381600087803b15801561421b57600080fd5b505af1158015612d51573d6000803e3d6000fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526110fb908490614d75565b6000828211156142d8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000806142ef83612e69565b905080614300576000915050610db5565b605b5460ff16614311579050610db5565b61432a61431d846116d2565b829063ffffffff6146ae16565b915050610db5565b60385460ff16156143745760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b604a5460ff166143cb576040805162461bcd60e51b815260206004820152601860248201527f436c61696d696e67206973206e6f7420656e61626c65642e0000000000000000604482015290519081900360640190fd5b600060425411614422576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b603e546001600160a01b03821660009081526057602052604090205410614482576040805162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b604482015290519081900360640190fd5b60455460ff161561455c57600061449882613e1e565b9050801561455a57603a546144bd906001600160a01b0316838363ffffffff61422f16565b6001600160a01b0382166000908152604c60205260409020546144e6908263ffffffff6146ae16565b6001600160a01b0383166000908152604c6020526040902055605254614512908263ffffffff6146ae16565b605255604080516001600160a01b03841681526020810183905281517f5b16e1043a283423361eb77682c99aff55948b34296846800a1a7dc9547a89fc929181900390910190a15b505b6000614567826142e3565b9050801561468e57605b546040805163b01ca88f60e01b81526001600160a01b0385811660048301526024820185905291516101009093049091169163b01ca88f9160448082019260009290919082900301818387803b1580156145ca57600080fd5b505af11580156145de573d6000803e3d6000fd5b5050506001600160a01b0383166000908152604b602052604090205461460b91508263ffffffff6146ae16565b6001600160a01b0383166000908152604b6020526040902055605154614637908263ffffffff6146ae16565b6051557fdacbdde355ba930696a362ea6738feb9f8bd52dfb3d81947558fd3217e23e325828261466682612e69565b604080516001600160a01b039094168452602084019290925282820152519081900360600190a15b50603e546001600160a01b03909116600090815260576020526040902055565b600082820183811015613f02576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082614717575060006142dd565b8282028284828161472457fe5b0414613f025760405162461bcd60e51b815260040180806020018281038252602181526020018061508e6021913960400191505060405180910390fd5b60008082116147b7576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816147c257fe5b04949350505050565b6001600160a01b038116600090815260566020526040902054610fc357603854604080516334c78ae560e11b81526001600160a01b038481166004830152915160009361010090049092169163698f15ca91602480820192602092909190829003018186803b15801561483d57600080fd5b505afa158015614851573d6000803e3d6000fd5b505050506040513d602081101561486757600080fd5b50511115610fc357603854604080516334c78ae560e11b81526001600160a01b03848116600483015291516101009093049091169163ad6d15de91839163698f15ca91602480820192602092909190829003018186803b1580156148ca57600080fd5b505afa1580156148de573d6000803e3d6000fd5b505050506040513d60208110156148f457600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b15801561493457600080fd5b505af1158015613084573d6000803e3d6000fd5b6001600160a01b038416600090815260566020526040902054158015906149895750603e546001600160a01b03851660009081526057602052604090205414155b156149975761499784614332565b811580156149bb57506001600160a01b038416600090815260566020526040902054155b80156149c75750600083115b156149f157603e546001600160a01b0385166000908152606160205260409020556149f1846147cb565b8115614af157614a0f83670de0b6b3a764000063ffffffff6146ae16565b6001600160a01b0385166000908152605660205260409020541015614a7b576040805162461bcd60e51b815260206004820152601a60248201527f496e73756666696369656e74207374616b656420616d6f756e74000000000000604482015290519081900360640190fd5b604d54614a8e908463ffffffff61428116565b604d556001600160a01b038416600090815260566020526040902054614aba908463ffffffff61428116565b6001600160a01b03808616600090815260566020526040902091909155603954614aec9116828563ffffffff61422f16565b612d51565b604d54614b04908463ffffffff6146ae16565b604d556001600160a01b038416600090815260566020526040902054614b30908463ffffffff6146ae16565b6001600160a01b03808616600090815260566020526040902091909155603954612d51911682308663ffffffff614f2d16565b303b1590565b603a546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b158015614bae57600080fd5b505afa158015614bc2573d6000803e3d6000fd5b505050506040513d6020811015614bd857600080fd5b5051600614614be75781610db2565b5064e8d4a51000900490565b600060425411614c4a576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b60008111614c90576040805162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b604482015290519081900360640190fd5b3360009081526054602052604090205460ff1615614cdf5760405162461bcd60e51b81526004018080602001828103825260328152602001806151166032913960400191505060405180910390fd5b610fc33382600033614948565b603a546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b158015614d3157600080fd5b505afa158015614d45573d6000803e3d6000fd5b505050506040513d6020811015614d5b57600080fd5b5051600614614d6a5781610db2565b5064e8d4a510000290565b614d87826001600160a01b0316614f87565b614dd8576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310614e165780518252601f199092019160209182019101614df7565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614e78576040519150601f19603f3d011682016040523d82523d6000602084013e614e7d565b606091505b509150915081614ed4576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612d5157808060200190516020811015614ef057600080fd5b5051612d515760405162461bcd60e51b815260040180806020018281038252602a81526020018061524f602a913960400191505060405180910390fd5b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612d51908590614d75565b3b15159056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e657243616e6e6f7420756e7374616b65207965742c20636f6f6c646f776e206e6f7420657870697265642e4163636f756e7420686173206e6f742074726967676572656420756e7374616b6520636f6f6c646f776e4f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564412066756c6c20706572696f6420686173206e6f74207061737365642073696e636520746865206c61737420636c6f73656420706572696f64546865207374616b6572206973207061757365642066726f6d207374616b696e672064756520746f20756e7374616b696e674163636f756e742068617320616c72656164792074726967676572656420756e7374616b6520636f6f6c646f776e43616e6e6f74206d657267652c2063616e63656c20756e7374616b696e67206f6e20626f7468206163636f756e7473206265666f7265206d657267696e675468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e7472616374206973207061757365644163636f756e7420646f65736e7420686176652074686174206d756368207374616b656443616e6e6f74206d657267652c20636c61696d2072657761726473206f6e20626f7468206163636f756e7473206265666f7265206d657267696e675361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656452656a65637465642064756520746f20737573706963696f75732076616c756573a265627a7a72315820870aa13266d88af16f0e886715e7d423afa6e8c486ea8c1cb596d4906efd930764736f6c63430005100032
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104cd5760003560e01c806364c8359111610283578063a4bce4ac1161015c578063c9925288116100ce578063e81a252611610092578063e81a252614610c93578063eaa8ba7f14610cb9578063ebc7977214610d11578063eff4a90014610d19578063f38d00f014610d45578063fd143c0b14610d4d576104cd565b8063c992528814610c4d578063cb8d751a14610c55578063d66e067714610c7b578063df52461a14610c83578063e11cd05514610c8b576104cd565b8063ba47a5d911610120578063ba47a5d914610ba5578063bd45006214610bad578063c10c354614610bd3578063c3b83f5f14610bf9578063c5335ac614610c1f578063c731a3d114610c45576104cd565b8063a4bce4ac14610b68578063a5b935a414610b70578063a694fc3a14610b78578063afac7fb114610b95578063b88a802f14610b9d576104cd565b80638759263f116101f557806393eb2e66116101b957806393eb2e6614610aac57806395910db214610ab45780639a09edab14610abc5780639a109bc214610ae2578063a00159a814610b08578063a2dd835f14610b36576104cd565b80638759263f14610a025780638a0ac0ff14610a2b5780638a239de814610a765780638da5cb5b14610a9c57806391b4ded914610aa4576104cd565b806372f702f31161024757806372f702f3146109b4578063741bef1a146109bc57806379ba5097146109c45780637a685677146109cc5780637c17f6fc146109f2578063847ae197146109fa576104cd565b806364c83591146108e157806366c4c8c7146109075780636801d9fb1461090f5780636dca3b02146109355780636e3c0d8714610989576104cd565b806335e5d29a116103b557806353cf411511610327578063605f5aa9116102eb578063605f5aa91461086f578063608daf891461089b57806361c01db7146108a357806362139e0e146108c95780636282719e146108d1578063647846a5146108d9576104cd565b806353cf41151461082157806356091ad114610829578063567e98f914610857578063572e36e61461085f5780635c975abb14610867576104cd565b80634ab17969116103795780634ab17969146107ad5780634c4e75df146107b55780634ed25b43146107db578063505b1497146107e3578063507a73281461081157806353a47bb714610819576104cd565b806335e5d29a1461073457806336468b5a146107515780633faae53414610777578063406a77661461077f57806347dda6ec14610787576104cd565b80631cb70a951161044e5780632ae8bdfe116104125780632ae8bdfe146106855780632d287886146106bb5780632def6620146106e15780632f324158146106e9578063331e03a8146106f157806334dfb26814610717576104cd565b80631cb70a95146106495780632007435414610651578063203d3718146106595780632145e92e146106615780632866ed2114610669576104cd565b806315da50641161049557806315da5064146105a85780631627540c146105b057806316765391146105d657806316c38b3c146105fc57806317433c911461061b576104cd565b806302c7739b146104d2578063080e2b47146105005780630fe62190146105385780631314f7591461055c57806313af403514610582575b600080fd5b6104fe600480360360408110156104e857600080fd5b506001600160a01b038135169060200135610d73565b005b6105266004803603602081101561051657600080fd5b50356001600160a01b0316610d81565b60408051918252519081900360200190f35b610540610d93565b604080516001600160a01b039092168252519081900360200190f35b6105266004803603602081101561057257600080fd5b50356001600160a01b0316610da7565b6104fe6004803603602081101561059857600080fd5b50356001600160a01b0316610dba565b610526610ecf565b6104fe600480360360208110156105c657600080fd5b50356001600160a01b0316610ed5565b610526600480360360208110156105ec57600080fd5b50356001600160a01b0316610f31565b6104fe6004803603602081101561061257600080fd5b50351515610f4c565b6104fe6004803603604081101561063157600080fd5b506001600160a01b0381351690602001351515610fc6565b610540611032565b610526611046565b61054061104c565b6104fe61105b565b61067161106d565b604080519115158252519081900360200190f35b6104fe6004803603606081101561069b57600080fd5b506001600160a01b03813581169160208101359091169060400135611076565b610526600480360360208110156106d157600080fd5b50356001600160a01b0316611100565b6104fe611112565b610540611292565b6105266004803603602081101561070757600080fd5b50356001600160a01b03166112a6565b6104fe6004803603602081101561072d57600080fd5b50356112b8565b6104fe6004803603602081101561074a57600080fd5b5035611646565b6105266004803603602081101561076757600080fd5b50356001600160a01b03166116d2565b61052661181d565b6105266118a7565b6106716004803603602081101561079d57600080fd5b50356001600160a01b03166118ad565b6104fe6118c2565b610526600480360360208110156107cb57600080fd5b50356001600160a01b0316611a42565b610526611a5d565b6104fe600480360360408110156107f957600080fd5b506001600160a01b0381351690602001351515611a63565b6104fe611b7e565b610540611fdb565b610671611fea565b6104fe6004803603604081101561083f57600080fd5b506001600160a01b0381351690602001351515611ff3565b61052661205f565b610540612065565b610671612074565b6104fe6004803603604081101561088557600080fd5b506001600160a01b03813516906020013561207d565b610526612189565b6104fe600480360360208110156108b957600080fd5b50356001600160a01b031661218f565b6105266122fe565b6104fe612304565b6105406123b6565b610526600480360360208110156108f757600080fd5b50356001600160a01b03166123c5565b6105406123d7565b6104fe6004803603602081101561092557600080fd5b50356001600160a01b03166123e6565b6104fe600480360360e081101561094b57600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013582169160808201359160a08101359160c0909101351661244a565b6104fe6004803603606081101561099f57600080fd5b50803590602081013590604001351515612606565b61054061266f565b61054061267e565b6104fe61268d565b610526600480360360208110156109e257600080fd5b50356001600160a01b0316612749565b610526612754565b61067161275a565b6104fe60048036036060811015610a1857600080fd5b5080359060208101359060400135612763565b6104fe600480360360e0811015610a4157600080fd5b5080351515906020810135151590604081013590606081013590608081013515159060a081013515159060c001351515612d57565b61052660048036036020811015610a8c57600080fd5b50356001600160a01b0316612e27565b610540612e42565b610526612e51565b610526612e57565b610526612e5d565b61052660048036036020811015610ad257600080fd5b50356001600160a01b0316612e63565b61052660048036036020811015610af857600080fd5b50356001600160a01b0316612e69565b61067160048036036040811015610b1e57600080fd5b506001600160a01b0381358116916020013516612faf565b6104fe60048036036060811015610b4c57600080fd5b506001600160a01b038135169060208101359060400135612fcf565b61067161308b565b610671613094565b6104fe60048036036020811015610b8e57600080fd5b50356130a4565b610671613179565b6104fe6131a5565b61052661323f565b61054060048036036020811015610bc357600080fd5b50356001600160a01b0316613245565b6104fe60048036036020811015610be957600080fd5b50356001600160a01b0316613260565b6104fe60048036036020811015610c0f57600080fd5b50356001600160a01b0316613367565b6104fe60048036036020811015610c3557600080fd5b50356001600160a01b0316613486565b61067161383c565b610540613845565b61067160048036036020811015610c6b57600080fd5b50356001600160a01b0316613854565b610526613869565b6106716138b4565b6105266138c4565b6104fe60048036036020811015610ca957600080fd5b50356001600160a01b03166138ca565b6104fe600480360360e0811015610ccf57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c0909101351661396f565b6104fe613a64565b6104fe60048036036040811015610d2f57600080fd5b506001600160a01b038135169060200135613ac7565b610526613bd3565b61067160048036036020811015610d6357600080fd5b50356001600160a01b0316613bd9565b610d7d8282613bee565b5050565b604c6020526000908152604090205481565b607a5461010090046001600160a01b031681565b6000610db282613e1e565b90505b919050565b6001600160a01b038116610e15576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b603454600160a01b900460ff1615610e5e5760405162461bcd60e51b8152600401808060200182810382526029815260200180614fe36029913960400191505060405180910390fd5b6034805460ff60a01b1916600160a01b179055603380546001600160a01b0383166001600160a01b031990911681179091556040805160008152602081019290925280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60465481565b610edd613f09565b603480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b6001600160a01b031660009081526056602052604090205490565b610f54613f09565b60385460ff1615158115151415610f6a57610fc3565b6038805460ff1916821515179081905560ff1615610f8757426037555b6038546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b610fce613f09565b6001600160a01b038216600081815260736020908152604091829020805460ff191685151590811790915582519384529083015280517fd2a8401466e7483577592b4b5160af1ba59060100f12387853477637096cfb919281900390910190a15050565b605b5461010090046001600160a01b031681565b603f5481565b6066546001600160a01b031681565b611063613f09565b61106b613f52565b565b604a5460ff1681565b61107e613f09565b6039546001600160a01b03848116911614156110e1576040805162461bcd60e51b815260206004820152601e60248201527f43616e206e6f74207769746864726177207374616b696e6720746f6b656e0000604482015290519081900360640190fd5b6110fb6001600160a01b038416838363ffffffff61422f16565b505050565b60556020526000908152604090205481565b60385460ff16156111545760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b3360009081526054602052604090205460ff166111a25760405162461bcd60e51b815260040180806020018281038252602a815260200180615035602a913960400191505060405180910390fd5b6041546111b690429063ffffffff61428116565b33600090815260536020526040902054106112025760405162461bcd60e51b815260040180806020018281038252602981526020018061500c6029913960400191505060405180910390fd5b336000818152605460209081526040808320805460ff1916905560559091529020546039549091611243916001600160a01b0316908363ffffffff61422f16565b336000818152605560209081526040808320929092558151928352820183905280517f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759281900390910190a150565b60385461010090046001600160a01b031681565b60536020526000908152604090205481565b60385460ff16156112fa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b60008111611342576040805162461bcd60e51b815260206004820152601060248201526f043616e6e6f7420756e7374616b6520360841b604482015290519081900360640190fd5b336000908152605660205260409020548111156113905760405162461bcd60e51b81526004018080602001828103825260248152602001806151f06024913960400191505060405180910390fd5b3360009081526054602052604090205460ff16156113df5760405162461bcd60e51b815260040180806020018281038252602e815260200180615148602e913960400191505060405180910390fd5b60006113ea336142e3565b11156113f9576113f933614332565b33600090815260536020908152604080832042905560549091529020805460ff19166001179055604d54611433908263ffffffff61428116565b604d553360009081526055602090815260408083208490556056909152902054611463908263ffffffff61428116565b3360009081526056602052604090208190556115d557603854604080516334c78ae560e11b8152336004820152905160009261010090046001600160a01b03169163698f15ca916024808301926020929190829003018186803b1580156114c957600080fd5b505afa1580156114dd573d6000803e3d6000fd5b505050506040513d60208110156114f357600080fd5b505111156115d557603854604080516334c78ae560e11b815233600482015290516101009092046001600160a01b031691635817d04291839163698f15ca91602480820192602092909190829003018186803b15801561155257600080fd5b505afa158015611566573d6000803e3d6000fd5b505050506040513d602081101561157c57600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b1580156115bc57600080fd5b505af11580156115d0573d6000803e3d6000fd5b505050505b604154336000818152605360205260409020547f30797de805f090008d8b19fa0c6f92d0f164789f64d6f7a1b097fbf0b1abac6b9261161a919063ffffffff6146ae16565b604080516001600160a01b0390931683526020830191909152818101849052519081900360600190a150565b61164e613f09565b614650603f54038111611697576040805162461bcd60e51b815260206004820152600c60248201526b546f6f20666172206261636b60a01b604482015290519081900360640190fd5b603f8190556040805182815290517fd1956985dae3dbe5da7d4db0d0abc90d01284cf79627ffef5538d2cd006901049181900360200190a150565b6077546000906001600160a01b0316158015906117655750607760009054906101000a90046001600160a01b03166001600160a01b0316635bd90b486040518163ffffffff1660e01b815260040160206040518083038186803b15801561173857600080fd5b505afa15801561174c573d6000803e3d6000fd5b505050506040513d602081101561176257600080fd5b50515b15610db557607754603e5460408051638d61c38b60e01b81526001600160a01b03868116600483015260001990930160248201529051610db293670de0b6b3a76400009361181193911691638d61c38b91604480820192602092909190829003018186803b1580156117d657600080fd5b505afa1580156117ea573d6000803e3d6000fd5b505050506040513d602081101561180057600080fd5b50516047549063ffffffff61470816565b9063ffffffff61476116565b603954605b54604080516370a0823160e01b81526101009092046001600160a01b039081166004840152905160009391909116916370a08231916024808301926020929190829003018186803b15801561187657600080fd5b505afa15801561188a573d6000803e3d6000fd5b505050506040513d60208110156118a057600080fd5b5051905090565b60795481565b60736020526000908152604090205460ff1681565b60385460ff16156119045760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b3360009081526054602052604090205460ff16611968576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e74206973206e6f7420756e7374616b696e670000000000000000604482015290519081900360640190fd5b611971336147cb565b600061197c336142e3565b111561198b5761198b33614332565b336000908152605460209081526040808320805460ff191690556055909152902054604d546119bf9163ffffffff6146ae16565b604d55336000908152605560209081526040808320546056909252909120546119ed9163ffffffff6146ae16565b336000818152605660209081526040808320949094556055815283822091909155825191825291517f725ee3b9a70aadcb1e002c94935880d7f515620783a5144c90e39201dc6f92da929181900390910190a1565b6001600160a01b031660009081526057602052604090205490565b60475481565b60385460ff1615611aa55760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b6001600160a01b03821615801590611ac657506001600160a01b0382163314155b611b09576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b3360008181526070602090815260408083206001600160a01b03871680855290835292819020805486151560ff19909116811790915581519485529184019290925282820152517fc939ba7d9b3e1a4e6505db209888366a551f46a85918944eb89becb92289935b9181900360600190a15050565b603580546001019081905560385460ff1615611bcb5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b600060425411611c22576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b604054603f54611c379163ffffffff6146ae16565b421015611c755760405162461bcd60e51b81526004018080602001828103825260398152602001806150dd6039913960400191505060405180910390fd5b607854600160a81b900460ff1615611cc8576040805162461bcd60e51b8152602060048201526011602482015270436c6f73696e67496e50726f677265737360781b604482015290519081900360640190fd5b603860019054906101000a90046001600160a01b03166001600160a01b031663acfabbe46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611d1857600080fd5b505af1158015611d2c573d6000803e3d6000fd5b505050506040513d6020811015611d4257600080fd5b505042603f5560385460408051635d13850560e01b815290516101009092046001600160a01b031691635d13850591600480820192602092909190829003018186803b158015611d9157600080fd5b505afa158015611da5573d6000803e3d6000fd5b505050506040513d6020811015611dbb57600080fd5b5051603e55603854604080516347d3681760e11b81529051611eb89261010090046001600160a01b031691638fa6d02e916004808301926020929190829003018186803b158015611e0b57600080fd5b505afa158015611e1f573d6000803e3d6000fd5b505050506040513d6020811015611e3557600080fd5b50516038546040805163b9d1c70b60e01b815290516101009092046001600160a01b03169163b9d1c70b91600480820192602092909190829003018186803b158015611e8057600080fd5b505afa158015611e94573d6000803e3d6000fd5b505050506040513d6020811015611eaa57600080fd5b50519063ffffffff61428116565b606355604654604355603a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611f0c57600080fd5b505afa158015611f20573d6000803e3d6000fd5b505050506040513d6020811015611f3657600080fd5b5051604455604d54606255607a5460ff1615611f5457611f54613f52565b7f80827f48a8070d07af7887688320aadf44499e3a2751fc41cc965870cf0627d7603e54603f54604051808381526020018281526020019250505060405180910390a16035548114610fc3576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b6034546001600160a01b031681565b60455460ff1681565b611ffb613f09565b6001600160a01b038216600081815260746020908152604091829020805460ff191685151590811790915582519384529083015280517fcf84063977a2a7766d440ee9919a260c5e0add05c19db1f47b31250b89c73e399281900390910190a15050565b604d5490565b6058546001600160a01b031681565b60385460ff1681565b60385460ff16156120bf5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b607a5461010090046001600160a01b0316331461211f576040805162461bcd60e51b8152602060048201526019602482015278556e737570706f72746564207374616b696e672070726f787960381b604482015290519081900360640190fd5b61214182826001607a60019054906101000a90046001600160a01b0316614948565b604080516001600160a01b03841681526020810183905281517f4914c7018facdafd839d7c7a6b61fe4d9efb99adcfa37f98693187e081c893b9929181900390910190a15050565b60625481565b603580546001019081905560385460ff16156121dc5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b6001600160a01b038216158015906121fd57506001600160a01b0382163314155b612240576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b6001600160a01b038216600090815260706020908152604080832033845290915290205460ff166122b1576040805162461bcd60e51b815260206004820152601660248201527521b0b73737ba1031b630b4b69037b7103132b430b63360511b604482015290519081900360640190fd5b6122ba82614332565b6035548114610d7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b60405481565b61230c613f09565b60425415612361576040805162461bcd60e51b815260206004820152601b60248201527f5374616b696e672068617320616c726561647920737461727465640000000000604482015290519081900360640190fd5b4260428190556000603e819055603f9190915560518190556052819055604d819055604e819055604f8190556040517f7c01398e484f9a82feaa276906d5d1f84867a0ff5a5bd9a485d4357f58d401839190a1565b603a546001600160a01b031681565b604b6020526000908152604090205481565b6077546001600160a01b031681565b6123ee613f09565b607a80546001600160a01b0383166101008102610100600160a81b03199092169190911790915560408051918252517f52dc607ac868d5b1fa7bba518a16fe90c6fc54562dcb05e35304ac1d26d32a249181900360200190a150565b600054610100900460ff16806124635750612463614b63565b80612471575060005460ff16155b6124ac5760405162461bcd60e51b815260040180806020018281038252602e8152602001806150af602e913960400191505060405180910390fd5b600054610100900460ff161580156124d7576000805460ff1961ff0019909116610100171660011790555b6124e088610dba565b6124e8613a64565b60388054610100600160a81b0319166101006001600160a01b038a811691820292909217909255603980546001600160a01b03199081168a84161791829055603a80549091168984161790556040805163095ea7b360e01b8152600481019490945260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b15801561257d57600080fd5b505af1158015612591573d6000803e3d6000fd5b505050506040513d60208110156125a757600080fd5b505060408490556041839055690ed2b525841adfc00000604655690472698b413b43200000604755603b80546001600160a01b0319166001600160a01b03841617905580156125fc576000805461ff00191690555b5050505050505050565b61260e613f09565b60468390556047829055605b805482151560ff199091168117909155604080518581526020810185905280820192909252517ff2192442b5560227e5c603bd8ec631a14b2fe42f35cf4e8e2083502de9571bb49181900360600190a1505050565b6039546001600160a01b031681565b603d546001600160a01b031681565b6034546001600160a01b031633146126d65760405162461bcd60e51b8152600401808060200182810382526035815260200180614fae6035913960400191505060405180910390fd5b603354603454604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160348054603380546001600160a01b03199081166001600160a01b03841617909155169055565b6000610db2826142e3565b603e5481565b607a5460ff1681565b6035805460010190819055607854600160a01b900460ff16612cc4576065546040805163bf40fac160e01b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263bf40fac192606480840193919291829003018186803b1580156127ed57600080fd5b505afa158015612801573d6000803e3d6000fd5b505050506040513d602081101561281757600080fd5b50516001600160a01b031633148061283957506033546001600160a01b031633145b612874576040805162461bcd60e51b81526020600482015260076024820152660496e76434349560cc1b604482015290519081900360640190fd5b607854600160a81b900460ff166128c5576040805162461bcd60e51b815260206004820152601060248201526f139bdd125b90db1bdcd954195c9a5bd960821b604482015290519081900360640190fd5b60465484111580156128d957506046548311155b80156128ea57506046546005028211155b6129255760405162461bcd60e51b81526004018080602001828103825260218152602001806152796021913960400191505060405180910390fd5b6065546040805163045f670760e21b8152602060048201819052600d60248301526c29b0b332a137bc213ab33332b960991b604483015291516000936001600160a01b03169263117d9c1c9260648082019391829003018186803b15801561298c57600080fd5b505afa1580156129a0573d6000803e3d6000fd5b505050506040513d60208110156129b657600080fd5b5051603a54604080516370a0823160e01b8152306004820152905192935060009283926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015612a0857600080fd5b505afa158015612a1c573d6000803e3d6000fd5b505050506040513d6020811015612a3257600080fd5b50519050612a3f85614b69565b6044558215612c81576065546040805163bf40fac160e01b8152602060048201819052600d60248301526c29b0b332a137bc213ab33332b960991b604483015291516000936001600160a01b03169263bf40fac19260648082019391829003018186803b158015612aaf57600080fd5b505afa158015612ac3573d6000803e3d6000fd5b505050506040513d6020811015612ad957600080fd5b5051604454909150821015612be057604454603a54604080516370a0823160e01b81526001600160a01b0385811660048301529151938690039391909216916370a08231916024808301926020929190829003018186803b158015612b3d57600080fd5b505afa158015612b51573d6000803e3d6000fd5b505050506040513d6020811015612b6757600080fd5b50511015612b785760019250612bdb565b806001600160a01b0316639ffcb31683604454036040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015612bc257600080fd5b505af1158015612bd6573d6000803e3d6000fd5b505050505b612c7f565b6000604454118015612bf3575081604454105b15612c7f57603a54604480546040805163a9059cbb60e01b81526001600160a01b03868116600483015292870360248201529051919093169263a9059cbb92818101926020929091908290030181600087803b158015612c5257600080fd5b505af1158015612c66573d6000803e3d6000fd5b505050506040513d6020811015612c7c57600080fd5b50505b505b604387905560478690556078805460ff60a81b191690556037546079541415612cc057821580612cae5750815b6038805460ff19169115159190911790555b5050505b7fb4873f5e95851bc84e2c197ca35129e61b53e3525c5d563b4dfd9307833f4dcc8484612cf085614b69565b60408051938452602084019290925282820152519081900360600190a16035548114612d51576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b50505050565b612d5f613f09565b604a805488151560ff1991821681179092556045805489151590831681179091556040888155604188905560718054881515908516811790915560788054881515600160a01b810260ff60a01b1990921691909117909155607a8054881515961686179055825195865260208601939093528482018a905260608501899052608085015260a084019190915260c0830191909152517fd0b7c05d30d50a3a23a9835892652aebc30da318b53c90521825ea7698e590a09181900360e00190a150505050505050565b6001600160a01b03166000908152604b602052604090205490565b6033546001600160a01b031681565b60375481565b60415481565b60635481565b50600090565b603e546001600160a01b03821660009081526061602052604081205490911480612ea957506001600160a01b038216600090815260566020526040902054155b80612ecd5750603e546001600160a01b038316600090815260576020526040902054145b80612ed85750606254155b610db557610db2612ef66063546062546146ae90919063ffffffff16565b604354603854604080516317640e0760e01b81526001600160a01b03888116600483015291516118119493612fa39361010090910416916317640e07916024808301926020929190829003018186803b158015612f5257600080fd5b505afa158015612f66573d6000803e3d6000fd5b505050506040513d6020811015612f7c57600080fd5b50516001600160a01b0388166000908152605660205260409020549063ffffffff6146ae16565b9063ffffffff61470816565b607060209081526000928352604080842090915290825290205460ff1681565b603a546040805163313ce56760e01b8152905184926000926001600160a01b039091169163313ce56791600480820192602092909190829003018186803b15801561301957600080fd5b505afa15801561302d573d6000803e3d6000fd5b505050506040513d602081101561304357600080fd5b505190508083101561305f5782601203600a0a8402915061307a565b8083111561307a5780601203600a0a848161307657fe5b0491505b6130848583613bee565b5050505050565b605b5460ff1681565b607854600160a01b900460ff1681565b603580546001019081905560385460ff16156130f15760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b6130fa82614bf3565b604080513381526020810184905281517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d929181900390910190a16035548114610d7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b6000806042541180156131a05750604054603f5461319c9163ffffffff6146ae16565b4210155b905090565b603580546001019081905560385460ff16156131f25760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b6131fb33614332565b6035548114610fc3576040805162461bcd60e51b815260206004820152601f6024820152600080516020614f8e833981519152604482015290519081900360640190fd5b60445481565b6072602052600090815260409020546001600160a01b031681565b613268613f09565b60385461010090046001600160a01b03161561330b576039546038546040805163095ea7b360e01b81526101009092046001600160a01b039081166004840152600060248401819052915193169263095ea7b3926044808201936020939283900390910190829087803b1580156132de57600080fd5b505af11580156132f2573d6000803e3d6000fd5b505050506040513d602081101561330857600080fd5b50505b603880546001600160a01b0383166101008102610100600160a81b03199092169190911790915560408051918252517feb1a4b1e230d212e1644ea31e3890084e2fa17ddee990e46a46e198e1728c4a09181900360200190a150565b61336f613f09565b6001600160a01b0381166133bc576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b603454600160a81b900460ff1615613411576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b603380546001600160a01b038084166001600160a01b03199092168217928390556034805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60385460ff16156134c85760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b60715460ff1661351f576040805162461bcd60e51b815260206004820152601960248201527f4d65726765206163636f756e742069732064697361626c656400000000000000604482015290519081900360640190fd5b6001600160a01b0381161580159061354057506001600160a01b0381163314155b613583576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b61358c336142e3565b15801561359f575061359d816142e3565b155b6135da5760405162461bcd60e51b815260040180806020018281038252603b815260200180615214603b913960400191505060405180910390fd5b3360009081526054602052604090205460ff1615801561361357506001600160a01b03811660009081526054602052604090205460ff16155b61364e5760405162461bcd60e51b815260040180806020018281038252603e815260200180615176603e913960400191505060405180910390fd5b60385460408051630282a2ed60e21b81523360048201526001600160a01b038481166024830152915161010090930490911691630a0a8bb49160448082019260009290919082900301818387803b1580156136a857600080fd5b505af11580156136bc573d6000803e3d6000fd5b505033600090815260566020526040808220546001600160a01b03861683529120546136f09350915063ffffffff6146ae16565b6001600160a01b038216600081815260566020908152604080832094909455338252604b90528281205491815291909120546137319163ffffffff6146ae16565b6001600160a01b0382166000818152604b6020908152604080832094909455338252604c90528281205491815291909120546137729163ffffffff6146ae16565b6001600160a01b0382166000818152604c6020818152604080842095909555603e546057808352868520829055606180845287862092909255338086526053845287862086905560548452878620805460ff191690556055845287862086905560568452878620869055604b8452878620869055938352868520859055825285842084905581528483209290925583519081529081019190915281517fa0fc26d627101bedf9c6cedb33e9eeac3fa2a7d508f89b597134bcee1a12d32c929181900390910190a150565b60715460ff1681565b6067546001600160a01b031681565b60546020526000908152604090205460ff1681565b603a54604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561187657600080fd5b607854600160a81b900460ff1681565b60435481565b60385460ff161561390c5760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b3360009081526072602090815260409182902080546001600160a01b0319166001600160a01b038516908117909155825190815291517f0c417702befaa0d74611c15e4278a897f344514ffbfbd4ea9a6e9168be46b8da9281900390910190a150565b613977613f09565b605880546001600160a01b03808a166001600160a01b03199283168117909355606680548a83169084168117909155606780548a84169085168117909155603d80548a85169086168117909155605b80548a86166101008102610100600160a81b031990921691909117909155606580548a8716908816811790915560778054968a16969097168617909655604080519788526020880194909452868401929092526060860152608085015260a084019290925260c0830152517fbe8209a2817cacf2137f586f29208a496d2d159efa011f3937e8172892826a9a9181900360e00190a150505050505050565b60365460ff1615613ab2576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6036805460ff19166001908117909155603555565b60385460ff1615613b095760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b607a5461010090046001600160a01b03163314613b69576040805162461bcd60e51b8152602060048201526019602482015278556e737570706f72746564207374616b696e672070726f787960381b604482015290519081900360640190fd5b613b8b82826000607a60019054906101000a90046001600160a01b0316614948565b604080516001600160a01b03841681526020810183905281517f95979d8a89d7d2a9728d0e86dc6a0e3374af9b407d8d978a8f4b583d8a1bfecf929181900390910190a15050565b60425481565b60746020526000908152604090205460ff1681565b6001600160a01b03821615801590613c065750600081115b613c48576040805162461bcd60e51b815260206004820152600e60248201526d496e76616c696420706172616d7360901b604482015290519081900360640190fd5b6001600160a01b038281166000908152607260205260409020541615613c87576001600160a01b03918216600090815260726020526040902054909116905b6058546001600160a01b0316331480613caa57506066546001600160a01b031633145b80613cbf57506067546001600160a01b031633145b80613cd957503360009081526073602052604090205460ff165b80613cf357503360009081526074602052604090205460ff165b613d36576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b613d3f81614cec565b6077549091506001600160a01b031615613dd257607754603e54604080516352a31c0760e01b81526001600160a01b038681166004830152336024830152604482018690526064820193909352905191909216916352a31c0791608480830192600092919082900301818387803b158015613db957600080fd5b505af1158015613dcd573d6000803e3d6000fd5b505050505b604080516001600160a01b038416815260208101839052338183015290517fb43a20c9abfed93eb48264a3acf807336352ba8cb6ee42c1754b1b1b280a20b99181900360600190a15050565b600080613e2a83612e69565b905080613e3b576000915050610db5565b613f02613e556063546062546146ae90919063ffffffff16565b604454603854604080516317640e0760e01b81526001600160a01b03898116600483015291516118119493612fa39361010090910416916317640e07916024808301926020929190829003018186803b158015613eb157600080fd5b505afa158015613ec5573d6000803e3d6000fd5b505050506040513d6020811015613edb57600080fd5b50516001600160a01b0389166000908152605660205260409020549063ffffffff6146ae16565b9392505050565b6033546001600160a01b0316331461106b5760405162461bcd60e51b815260040180806020018281038252602f81526020018061505f602f913960400191505060405180910390fd5b6065546040805163045f670760e21b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263117d9c1c92606480840193919291829003018186803b158015613fc057600080fd5b505afa158015613fd4573d6000803e3d6000fd5b505050506040513d6020811015613fea57600080fd5b50511561106b57607854600160a01b900460ff1661402c576038805460ff191660011790556078805460ff60a81b1916600160a81b1790554260378190556079555b6065546040805163bf40fac160e01b8152602060048201819052601360248301527221b937b9b9a1b430b4b721b7b63632b1ba37b960691b604483015291516001600160a01b039093169263bf40fac192606480840193919291829003018186803b15801561409a57600080fd5b505afa1580156140ae573d6000803e3d6000fd5b505050506040513d60208110156140c457600080fd5b5051606254606354607754603e546040805163df022bf560e01b81526000199092016004830152516001600160a01b03958616956334bd229c959493169163df022bf5916024808301926020929190829003018186803b15801561412757600080fd5b505afa15801561413b573d6000803e3d6000fd5b505050506040513d602081101561415157600080fd5b5051603a54604080516370a0823160e01b815230600482015290516141d0926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561419f57600080fd5b505afa1580156141b3573d6000803e3d6000fd5b505050506040513d60208110156141c957600080fd5b5051614cec565b6040518563ffffffff1660e01b815260040180858152602001848152602001838152602001828152602001945050505050600060405180830381600087803b15801561421b57600080fd5b505af1158015612d51573d6000803e3d6000fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526110fb908490614d75565b6000828211156142d8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000806142ef83612e69565b905080614300576000915050610db5565b605b5460ff16614311579050610db5565b61432a61431d846116d2565b829063ffffffff6146ae16565b915050610db5565b60385460ff16156143745760405162461bcd60e51b815260040180806020018281038252603c8152602001806151b4603c913960400191505060405180910390fd5b604a5460ff166143cb576040805162461bcd60e51b815260206004820152601860248201527f436c61696d696e67206973206e6f7420656e61626c65642e0000000000000000604482015290519081900360640190fd5b600060425411614422576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b603e546001600160a01b03821660009081526057602052604090205410614482576040805162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b604482015290519081900360640190fd5b60455460ff161561455c57600061449882613e1e565b9050801561455a57603a546144bd906001600160a01b0316838363ffffffff61422f16565b6001600160a01b0382166000908152604c60205260409020546144e6908263ffffffff6146ae16565b6001600160a01b0383166000908152604c6020526040902055605254614512908263ffffffff6146ae16565b605255604080516001600160a01b03841681526020810183905281517f5b16e1043a283423361eb77682c99aff55948b34296846800a1a7dc9547a89fc929181900390910190a15b505b6000614567826142e3565b9050801561468e57605b546040805163b01ca88f60e01b81526001600160a01b0385811660048301526024820185905291516101009093049091169163b01ca88f9160448082019260009290919082900301818387803b1580156145ca57600080fd5b505af11580156145de573d6000803e3d6000fd5b5050506001600160a01b0383166000908152604b602052604090205461460b91508263ffffffff6146ae16565b6001600160a01b0383166000908152604b6020526040902055605154614637908263ffffffff6146ae16565b6051557fdacbdde355ba930696a362ea6738feb9f8bd52dfb3d81947558fd3217e23e325828261466682612e69565b604080516001600160a01b039094168452602084019290925282820152519081900360600190a15b50603e546001600160a01b03909116600090815260576020526040902055565b600082820183811015613f02576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082614717575060006142dd565b8282028284828161472457fe5b0414613f025760405162461bcd60e51b815260040180806020018281038252602181526020018061508e6021913960400191505060405180910390fd5b60008082116147b7576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816147c257fe5b04949350505050565b6001600160a01b038116600090815260566020526040902054610fc357603854604080516334c78ae560e11b81526001600160a01b038481166004830152915160009361010090049092169163698f15ca91602480820192602092909190829003018186803b15801561483d57600080fd5b505afa158015614851573d6000803e3d6000fd5b505050506040513d602081101561486757600080fd5b50511115610fc357603854604080516334c78ae560e11b81526001600160a01b03848116600483015291516101009093049091169163ad6d15de91839163698f15ca91602480820192602092909190829003018186803b1580156148ca57600080fd5b505afa1580156148de573d6000803e3d6000fd5b505050506040513d60208110156148f457600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b15801561493457600080fd5b505af1158015613084573d6000803e3d6000fd5b6001600160a01b038416600090815260566020526040902054158015906149895750603e546001600160a01b03851660009081526057602052604090205414155b156149975761499784614332565b811580156149bb57506001600160a01b038416600090815260566020526040902054155b80156149c75750600083115b156149f157603e546001600160a01b0385166000908152606160205260409020556149f1846147cb565b8115614af157614a0f83670de0b6b3a764000063ffffffff6146ae16565b6001600160a01b0385166000908152605660205260409020541015614a7b576040805162461bcd60e51b815260206004820152601a60248201527f496e73756666696369656e74207374616b656420616d6f756e74000000000000604482015290519081900360640190fd5b604d54614a8e908463ffffffff61428116565b604d556001600160a01b038416600090815260566020526040902054614aba908463ffffffff61428116565b6001600160a01b03808616600090815260566020526040902091909155603954614aec9116828563ffffffff61422f16565b612d51565b604d54614b04908463ffffffff6146ae16565b604d556001600160a01b038416600090815260566020526040902054614b30908463ffffffff6146ae16565b6001600160a01b03808616600090815260566020526040902091909155603954612d51911682308663ffffffff614f2d16565b303b1590565b603a546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b158015614bae57600080fd5b505afa158015614bc2573d6000803e3d6000fd5b505050506040513d6020811015614bd857600080fd5b5051600614614be75781610db2565b5064e8d4a51000900490565b600060425411614c4a576040805162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720706572696f6420686173206e6f7420737461727465640000604482015290519081900360640190fd5b60008111614c90576040805162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b604482015290519081900360640190fd5b3360009081526054602052604090205460ff1615614cdf5760405162461bcd60e51b81526004018080602001828103825260328152602001806151166032913960400191505060405180910390fd5b610fc33382600033614948565b603a546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b158015614d3157600080fd5b505afa158015614d45573d6000803e3d6000fd5b505050506040513d6020811015614d5b57600080fd5b5051600614614d6a5781610db2565b5064e8d4a510000290565b614d87826001600160a01b0316614f87565b614dd8576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310614e165780518252601f199092019160209182019101614df7565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614e78576040519150601f19603f3d011682016040523d82523d6000602084013e614e7d565b606091505b509150915081614ed4576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612d5157808060200190516020811015614ef057600080fd5b5051612d515760405162461bcd60e51b815260040180806020018281038252602a81526020018061524f602a913960400191505060405180910390fd5b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612d51908590614d75565b3b15159056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e657243616e6e6f7420756e7374616b65207965742c20636f6f6c646f776e206e6f7420657870697265642e4163636f756e7420686173206e6f742074726967676572656420756e7374616b6520636f6f6c646f776e4f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564412066756c6c20706572696f6420686173206e6f74207061737365642073696e636520746865206c61737420636c6f73656420706572696f64546865207374616b6572206973207061757365642066726f6d207374616b696e672064756520746f20756e7374616b696e674163636f756e742068617320616c72656164792074726967676572656420756e7374616b6520636f6f6c646f776e43616e6e6f74206d657267652c2063616e63656c20756e7374616b696e67206f6e20626f7468206163636f756e7473206265666f7265206d657267696e675468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e7472616374206973207061757365644163636f756e7420646f65736e7420686176652074686174206d756368207374616b656443616e6e6f74206d657267652c20636c61696d2072657761726473206f6e20626f7468206163636f756e7473206265666f7265206d657267696e675361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656452656a65637465642064756520746f20737573706963696f75732076616c756573a265627a7a72315820870aa13266d88af16f0e886715e7d423afa6e8c486ea8c1cb596d4906efd930764736f6c63430005100032
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.