Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
BoostedDualVault
Compiler Version
v0.8.2+commit.661d1103
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-09-08
*/
pragma solidity 0.8.2;
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.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `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);
}
interface IRewardsRecipientWithPlatformToken {
function notifyRewardAmount(uint256 reward) external;
function getRewardToken() external view returns (IERC20);
function getPlatformToken() external view returns (IERC20);
}
interface IBoostedDualVaultWithLockup {
/**
* @dev Stakes a given amount of the StakingToken for the sender
* @param _amount Units of StakingToken
*/
function stake(uint256 _amount) external;
/**
* @dev Stakes a given amount of the StakingToken for a given beneficiary
* @param _beneficiary Staked tokens are credited to this address
* @param _amount Units of StakingToken
*/
function stake(address _beneficiary, uint256 _amount) external;
/**
* @dev Withdraws stake from pool and claims any unlocked rewards.
* Note, this function is costly - the args for _claimRewards
* should be determined off chain and then passed to other fn
*/
function exit() external;
/**
* @dev Withdraws stake from pool and claims any unlocked rewards.
* @param _first Index of the first array element to claim
* @param _last Index of the last array element to claim
*/
function exit(uint256 _first, uint256 _last) external;
/**
* @dev Withdraws given stake amount from the pool
* @param _amount Units of the staked token to withdraw
*/
function withdraw(uint256 _amount) external;
/**
* @dev Claims only the tokens that have been immediately unlocked, not including
* those that are in the lockers.
*/
function claimReward() external;
/**
* @dev Claims all unlocked rewards for sender.
* Note, this function is costly - the args for _claimRewards
* should be determined off chain and then passed to other fn
*/
function claimRewards() external;
/**
* @dev Claims all unlocked rewards for sender. Both immediately unlocked
* rewards and also locked rewards past their time lock.
* @param _first Index of the first array element to claim
* @param _last Index of the last array element to claim
*/
function claimRewards(uint256 _first, uint256 _last) external;
/**
* @dev Pokes a given account to reset the boost
*/
function pokeBoost(address _account) external;
/**
* @dev Gets the last applicable timestamp for this reward period
*/
function lastTimeRewardApplicable() external view returns (uint256);
/**
* @dev Calculates the amount of unclaimed rewards per token since last update,
* and sums with stored to give the new cumulative reward per token
* @return 'Reward' per staked token
*/
function rewardPerToken() external view returns (uint256, uint256);
/**
* @dev Returned the units of IMMEDIATELY claimable rewards a user has to receive. Note - this
* does NOT include the majority of rewards which will be locked up.
* @param _account User address
* @return Total reward amount earned
*/
function earned(address _account) external view returns (uint256, uint256);
/**
* @dev Calculates all unclaimed reward data, finding both immediately unlocked rewards
* and those that have passed their time lock.
* @param _account User address
* @return amount Total units of unclaimed rewards
* @return first Index of the first userReward that has unlocked
* @return last Index of the last userReward that has unlocked
*/
function unclaimedRewards(address _account)
external
view
returns (
uint256 amount,
uint256 first,
uint256 last,
uint256 platformAmount
);
}
contract ModuleKeys {
// Governance
// ===========
// keccak256("Governance");
bytes32 internal constant KEY_GOVERNANCE =
0x9409903de1e6fd852dfc61c9dacb48196c48535b60e25abf92acc92dd689078d;
//keccak256("Staking");
bytes32 internal constant KEY_STAKING =
0x1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034;
//keccak256("ProxyAdmin");
bytes32 internal constant KEY_PROXY_ADMIN =
0x96ed0203eb7e975a4cbcaa23951943fa35c5d8288117d50c12b3d48b0fab48d1;
// mStable
// =======
// keccak256("OracleHub");
bytes32 internal constant KEY_ORACLE_HUB =
0x8ae3a082c61a7379e2280f3356a5131507d9829d222d853bfa7c9fe1200dd040;
// keccak256("Manager");
bytes32 internal constant KEY_MANAGER =
0x6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f;
//keccak256("Recollateraliser");
bytes32 internal constant KEY_RECOLLATERALISER =
0x39e3ed1fc335ce346a8cbe3e64dd525cf22b37f1e2104a755e761c3c1eb4734f;
//keccak256("MetaToken");
bytes32 internal constant KEY_META_TOKEN =
0xea7469b14936af748ee93c53b2fe510b9928edbdccac3963321efca7eb1a57a2;
// keccak256("SavingsManager");
bytes32 internal constant KEY_SAVINGS_MANAGER =
0x12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf1;
// keccak256("Liquidator");
bytes32 internal constant KEY_LIQUIDATOR =
0x1e9cb14d7560734a61fa5ff9273953e971ff3cd9283c03d8346e3264617933d4;
// keccak256("InterestValidator");
bytes32 internal constant KEY_INTEREST_VALIDATOR =
0xc10a28f028c7f7282a03c90608e38a4a646e136e614e4b07d119280c5f7f839f;
}
interface INexus {
function governor() external view returns (address);
function getModule(bytes32 key) external view returns (address);
function proposeModule(bytes32 _key, address _addr) external;
function cancelProposedModule(bytes32 _key) external;
function acceptProposedModule(bytes32 _key) external;
function acceptProposedModules(bytes32[] calldata _keys) external;
function requestLockModule(bytes32 _key) external;
function cancelLockModule(bytes32 _key) external;
function lockModule(bytes32 _key) external;
}
abstract contract ImmutableModule is ModuleKeys {
INexus public immutable nexus;
/**
* @dev Initialization function for upgradable proxy contracts
* @param _nexus Nexus contract address
*/
constructor(address _nexus) {
require(_nexus != address(0), "Nexus address is zero");
nexus = INexus(_nexus);
}
/**
* @dev Modifier to allow function calls only from the Governor.
*/
modifier onlyGovernor() {
_onlyGovernor();
_;
}
function _onlyGovernor() internal view {
require(msg.sender == _governor(), "Only governor can execute");
}
/**
* @dev Modifier to allow function calls only from the Governance.
* Governance is either Governor address or Governance address.
*/
modifier onlyGovernance() {
require(
msg.sender == _governor() || msg.sender == _governance(),
"Only governance can execute"
);
_;
}
/**
* @dev Returns Governor address from the Nexus
* @return Address of Governor Contract
*/
function _governor() internal view returns (address) {
return nexus.governor();
}
/**
* @dev Returns Governance Module address from the Nexus
* @return Address of the Governance (Phase 2)
*/
function _governance() internal view returns (address) {
return nexus.getModule(KEY_GOVERNANCE);
}
/**
* @dev Return SavingsManager Module address from the Nexus
* @return Address of the SavingsManager Module contract
*/
function _savingsManager() internal view returns (address) {
return nexus.getModule(KEY_SAVINGS_MANAGER);
}
/**
* @dev Return Recollateraliser Module address from the Nexus
* @return Address of the Recollateraliser Module contract (Phase 2)
*/
function _recollateraliser() internal view returns (address) {
return nexus.getModule(KEY_RECOLLATERALISER);
}
/**
* @dev Return Recollateraliser Module address from the Nexus
* @return Address of the Recollateraliser Module contract (Phase 2)
*/
function _liquidator() internal view returns (address) {
return nexus.getModule(KEY_LIQUIDATOR);
}
/**
* @dev Return ProxyAdmin Module address from the Nexus
* @return Address of the ProxyAdmin Module contract
*/
function _proxyAdmin() internal view returns (address) {
return nexus.getModule(KEY_PROXY_ADMIN);
}
}
interface IRewardsDistributionRecipient {
function notifyRewardAmount(uint256 reward) external;
function getRewardToken() external view returns (IERC20);
}
abstract contract InitializableRewardsDistributionRecipient is
IRewardsDistributionRecipient,
ImmutableModule
{
// This address has the ability to distribute the rewards
address public rewardsDistributor;
constructor(address _nexus) ImmutableModule(_nexus) {}
/** @dev Recipient is a module, governed by mStable governance */
function _initialize(address _rewardsDistributor) internal {
rewardsDistributor = _rewardsDistributor;
}
/**
* @dev Only the rewards distributor can notify about rewards
*/
modifier onlyRewardsDistributor() {
require(msg.sender == rewardsDistributor, "Caller is not reward distributor");
_;
}
/**
* @dev Change the rewardsDistributor - only called by mStable governor
* @param _rewardsDistributor Address of the new distributor
*/
function setRewardsDistribution(address _rewardsDistributor) external onlyGovernor {
rewardsDistributor = _rewardsDistributor;
}
}
interface IBoostDirector {
function getBalance(address _user) external returns (uint256);
function setDirection(
address _old,
address _new,
bool _pokeNew
) external;
function whitelistVaults(address[] calldata _vaults) external;
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on 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;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return
functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data)
internal
view
returns (bytes memory)
{
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data)
internal
returns (bytes memory)
{
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
library SafeERC20 {
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)
);
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
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) + value;
_callOptionalReturn(
token,
abi.encodeWithSelector(token.approve.selector, spender, newAllowance)
);
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - 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. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(
data,
"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");
}
}
}
contract InitializableReentrancyGuard {
bool private _notEntered;
function _initializeReentrancyGuard() internal {
// Storing an initial non-zero value makes deployment a bit more
// expensive, but in exchange the refund on every call to nonReentrant
// will be lower in amount. Since refunds are capped to a percetange of
// the total transaction's gas, it is best to keep them low in cases
// like this one, to increase the likelihood of the full refund coming
// into effect.
_notEntered = true;
}
/**
* @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() {
// On the first call to nonReentrant, _notEntered will be true
require(_notEntered, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_notEntered = false;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_notEntered = true;
}
}
library StableMath {
/**
* @dev Scaling unit for use in specific calculations,
* where 1 * 10**18, or 1e18 represents a unit '1'
*/
uint256 private constant FULL_SCALE = 1e18;
/**
* @dev Token Ratios are used when converting between units of bAsset, mAsset and MTA
* Reasoning: Takes into account token decimals, and difference in base unit (i.e. grams to Troy oz for gold)
* bAsset ratio unit for use in exact calculations,
* where (1 bAsset unit * bAsset.ratio) / ratioScale == x mAsset unit
*/
uint256 private constant RATIO_SCALE = 1e8;
/**
* @dev Provides an interface to the scaling unit
* @return Scaling unit (1e18 or 1 * 10**18)
*/
function getFullScale() internal pure returns (uint256) {
return FULL_SCALE;
}
/**
* @dev Provides an interface to the ratio unit
* @return Ratio scale unit (1e8 or 1 * 10**8)
*/
function getRatioScale() internal pure returns (uint256) {
return RATIO_SCALE;
}
/**
* @dev Scales a given integer to the power of the full scale.
* @param x Simple uint256 to scale
* @return Scaled value a to an exact number
*/
function scaleInteger(uint256 x) internal pure returns (uint256) {
return x * FULL_SCALE;
}
/***************************************
PRECISE ARITHMETIC
****************************************/
/**
* @dev Multiplies two precise units, and then truncates by the full scale
* @param x Left hand input to multiplication
* @param y Right hand input to multiplication
* @return Result after multiplying the two inputs and then dividing by the shared
* scale unit
*/
function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {
return mulTruncateScale(x, y, FULL_SCALE);
}
/**
* @dev Multiplies two precise units, and then truncates by the given scale. For example,
* when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18
* @param x Left hand input to multiplication
* @param y Right hand input to multiplication
* @param scale Scale unit
* @return Result after multiplying the two inputs and then dividing by the shared
* scale unit
*/
function mulTruncateScale(
uint256 x,
uint256 y,
uint256 scale
) internal pure returns (uint256) {
// e.g. assume scale = fullScale
// z = 10e18 * 9e17 = 9e36
// return 9e36 / 1e18 = 9e18
return (x * y) / scale;
}
/**
* @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result
* @param x Left hand input to multiplication
* @param y Right hand input to multiplication
* @return Result after multiplying the two inputs and then dividing by the shared
* scale unit, rounded up to the closest base unit.
*/
function mulTruncateCeil(uint256 x, uint256 y) internal pure returns (uint256) {
// e.g. 8e17 * 17268172638 = 138145381104e17
uint256 scaled = x * y;
// e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17
uint256 ceil = scaled + FULL_SCALE - 1;
// e.g. 13814538111.399...e18 / 1e18 = 13814538111
return ceil / FULL_SCALE;
}
/**
* @dev Precisely divides two units, by first scaling the left hand operand. Useful
* for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)
* @param x Left hand input to division
* @param y Right hand input to division
* @return Result after multiplying the left operand by the scale, and
* executing the division on the right hand input.
*/
function divPrecisely(uint256 x, uint256 y) internal pure returns (uint256) {
// e.g. 8e18 * 1e18 = 8e36
// e.g. 8e36 / 10e18 = 8e17
return (x * FULL_SCALE) / y;
}
/***************************************
RATIO FUNCS
****************************************/
/**
* @dev Multiplies and truncates a token ratio, essentially flooring the result
* i.e. How much mAsset is this bAsset worth?
* @param x Left hand operand to multiplication (i.e Exact quantity)
* @param ratio bAsset ratio
* @return c Result after multiplying the two inputs and then dividing by the ratio scale
*/
function mulRatioTruncate(uint256 x, uint256 ratio) internal pure returns (uint256 c) {
return mulTruncateScale(x, ratio, RATIO_SCALE);
}
/**
* @dev Multiplies and truncates a token ratio, rounding up the result
* i.e. How much mAsset is this bAsset worth?
* @param x Left hand input to multiplication (i.e Exact quantity)
* @param ratio bAsset ratio
* @return Result after multiplying the two inputs and then dividing by the shared
* ratio scale, rounded up to the closest base unit.
*/
function mulRatioTruncateCeil(uint256 x, uint256 ratio) internal pure returns (uint256) {
// e.g. How much mAsset should I burn for this bAsset (x)?
// 1e18 * 1e8 = 1e26
uint256 scaled = x * ratio;
// 1e26 + 9.99e7 = 100..00.999e8
uint256 ceil = scaled + RATIO_SCALE - 1;
// return 100..00.999e8 / 1e8 = 1e18
return ceil / RATIO_SCALE;
}
/**
* @dev Precisely divides two ratioed units, by first scaling the left hand operand
* i.e. How much bAsset is this mAsset worth?
* @param x Left hand operand in division
* @param ratio bAsset ratio
* @return c Result after multiplying the left operand by the scale, and
* executing the division on the right hand input.
*/
function divRatioPrecisely(uint256 x, uint256 ratio) internal pure returns (uint256 c) {
// e.g. 1e14 * 1e8 = 1e22
// return 1e22 / 1e12 = 1e10
return (x * RATIO_SCALE) / ratio;
}
/***************************************
HELPERS
****************************************/
/**
* @dev Calculates minimum of two numbers
* @param x Left hand input
* @param y Right hand input
* @return Minimum of the two inputs
*/
function min(uint256 x, uint256 y) internal pure returns (uint256) {
return x > y ? y : x;
}
/**
* @dev Calculated maximum of two numbers
* @param x Left hand input
* @param y Right hand input
* @return Maximum of the two inputs
*/
function max(uint256 x, uint256 y) internal pure returns (uint256) {
return x > y ? x : y;
}
/**
* @dev Clamps a value to an upper bound
* @param x Left hand input
* @param upperBound Maximum possible value to return
* @return Input x clamped to a maximum value, upperBound
*/
function clamp(uint256 x, uint256 upperBound) internal pure returns (uint256) {
return x > upperBound ? upperBound : x;
}
}
library Root {
/**
* @dev Returns the square root of a given number
* @param x Input
* @return y Square root of Input
*/
function sqrt(uint256 x) internal pure returns (uint256 y) {
if (x == 0) return 0;
else {
uint256 xx = x;
uint256 r = 1;
if (xx >= 0x100000000000000000000000000000000) {
xx >>= 128;
r <<= 64;
}
if (xx >= 0x10000000000000000) {
xx >>= 64;
r <<= 32;
}
if (xx >= 0x100000000) {
xx >>= 32;
r <<= 16;
}
if (xx >= 0x10000) {
xx >>= 16;
r <<= 8;
}
if (xx >= 0x100) {
xx >>= 8;
r <<= 4;
}
if (xx >= 0x10) {
xx >>= 4;
r <<= 2;
}
if (xx >= 0x8) {
r <<= 1;
}
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1; // Seven iterations should be enough
uint256 r1 = x / r;
return uint256(r < r1 ? r : r1);
}
}
}
contract BoostedTokenWrapper is InitializableReentrancyGuard {
using StableMath for uint256;
using SafeERC20 for IERC20;
event Transfer(address indexed from, address indexed to, uint256 value);
string private _name;
string private _symbol;
IERC20 public immutable stakingToken;
IBoostDirector public immutable boostDirector;
uint256 private _totalBoostedSupply;
mapping(address => uint256) private _boostedBalances;
mapping(address => uint256) private _rawBalances;
// Vars for use in the boost calculations
uint256 private constant MIN_DEPOSIT = 1e18;
uint256 private constant MAX_VMTA = 600000e18;
uint256 private constant MAX_BOOST = 3e18;
uint256 private constant MIN_BOOST = 1e18;
uint256 private constant FLOOR = 98e16;
uint256 public immutable boostCoeff; // scaled by 10
uint256 public immutable priceCoeff;
/**
* @dev TokenWrapper constructor
* @param _stakingToken Wrapped token to be staked
* @param _boostDirector vMTA boost director
* @param _priceCoeff Rough price of a given LP token, to be used in boost calculations, where $1 = 1e18
* @param _boostCoeff Boost coefficent using the the boost formula
*/
constructor(
address _stakingToken,
address _boostDirector,
uint256 _priceCoeff,
uint256 _boostCoeff
) {
stakingToken = IERC20(_stakingToken);
boostDirector = IBoostDirector(_boostDirector);
priceCoeff = _priceCoeff;
boostCoeff = _boostCoeff;
}
/**
* @param _nameArg token name. eg imUSD Vault or GUSD Feeder Pool Vault
* @param _symbolArg token symbol. eg v-imUSD or v-fPmUSD/GUSD
*/
function _initialize(string memory _nameArg, string memory _symbolArg) internal {
_initializeReentrancyGuard();
_name = _nameArg;
_symbol = _symbolArg;
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev Get the total boosted amount
* @return uint256 total supply
*/
function totalSupply() public view returns (uint256) {
return _totalBoostedSupply;
}
/**
* @dev Get the boosted balance of a given account
* @param _account User for which to retrieve balance
*/
function balanceOf(address _account) public view returns (uint256) {
return _boostedBalances[_account];
}
/**
* @dev Get the RAW balance of a given account
* @param _account User for which to retrieve balance
*/
function rawBalanceOf(address _account) public view returns (uint256) {
return _rawBalances[_account];
}
/**
* @dev Read the boost for the given address
* @param _account User for which to return the boost
* @return boost where 1x == 1e18
*/
function getBoost(address _account) public view returns (uint256) {
return balanceOf(_account).divPrecisely(rawBalanceOf(_account));
}
/**
* @dev Deposits a given amount of StakingToken from sender
* @param _amount Units of StakingToken
*/
function _stakeRaw(address _beneficiary, uint256 _amount) internal nonReentrant {
_rawBalances[_beneficiary] += _amount;
stakingToken.safeTransferFrom(msg.sender, address(this), _amount);
}
/**
* @dev Withdraws a given stake from sender
* @param _amount Units of StakingToken
*/
function _withdrawRaw(uint256 _amount) internal nonReentrant {
_rawBalances[msg.sender] -= _amount;
stakingToken.safeTransfer(msg.sender, _amount);
}
/**
* @dev Updates the boost for the given address according to the formula
* boost = min(0.5 + c * vMTA_balance / imUSD_locked^(7/8), 1.5)
* If rawBalance <= MIN_DEPOSIT, boost is 0
* @param _account User for which to update the boost
*/
function _setBoost(address _account) internal {
uint256 rawBalance = _rawBalances[_account];
uint256 boostedBalance = _boostedBalances[_account];
uint256 boost = MIN_BOOST;
// Check whether balance is sufficient
// is_boosted is used to minimize gas usage
uint256 scaledBalance = (rawBalance * priceCoeff) / 1e18;
if (scaledBalance >= MIN_DEPOSIT) {
uint256 votingWeight = boostDirector.getBalance(_account);
boost = _computeBoost(scaledBalance, votingWeight);
}
uint256 newBoostedBalance = rawBalance.mulTruncate(boost);
if (newBoostedBalance != boostedBalance) {
_totalBoostedSupply = _totalBoostedSupply - boostedBalance + newBoostedBalance;
_boostedBalances[_account] = newBoostedBalance;
if (newBoostedBalance > boostedBalance) {
emit Transfer(address(0), _account, newBoostedBalance - boostedBalance);
} else {
emit Transfer(_account, address(0), boostedBalance - newBoostedBalance);
}
}
}
/**
* @dev Computes the boost for
* boost = min(m, max(1, 0.95 + c * min(voting_weight, f) / deposit^(3/4)))
* @param _scaledDeposit deposit amount in terms of USD
*/
function _computeBoost(uint256 _scaledDeposit, uint256 _votingWeight)
private
view
returns (uint256 boost)
{
if (_votingWeight == 0) return MIN_BOOST;
// Compute balance to the power 3/4
uint256 sqrt1 = Root.sqrt(_scaledDeposit * 1e6);
uint256 sqrt2 = Root.sqrt(sqrt1);
uint256 denominator = sqrt1 * sqrt2;
boost =
(((StableMath.min(_votingWeight, MAX_VMTA) * boostCoeff) / 10) * 1e18) /
denominator;
boost = StableMath.min(MAX_BOOST, StableMath.max(MIN_BOOST, FLOOR + boost));
}
}
library MassetHelpers {
using SafeERC20 for IERC20;
function transferReturnBalance(
address _sender,
address _recipient,
address _bAsset,
uint256 _qty
) internal returns (uint256 receivedQty, uint256 recipientBalance) {
uint256 balBefore = IERC20(_bAsset).balanceOf(_recipient);
IERC20(_bAsset).safeTransferFrom(_sender, _recipient, _qty);
recipientBalance = IERC20(_bAsset).balanceOf(_recipient);
receivedQty = recipientBalance - balBefore;
}
function safeInfiniteApprove(address _asset, address _spender) internal {
IERC20(_asset).safeApprove(_spender, 0);
IERC20(_asset).safeApprove(_spender, 2**256 - 1);
}
}
contract PlatformTokenVendor {
IERC20 public immutable platformToken;
address public immutable parentStakingContract;
/** @dev Simple constructor that stores the parent address */
constructor(IERC20 _platformToken) public {
parentStakingContract = msg.sender;
platformToken = _platformToken;
MassetHelpers.safeInfiniteApprove(address(_platformToken), msg.sender);
}
/**
* @dev Re-approves the StakingReward contract to spend the platform token.
* Just incase for some reason approval has been reset.
*/
function reApproveOwner() external {
MassetHelpers.safeInfiniteApprove(address(platformToken), parentStakingContract);
}
}
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;
}
library SafeCast {
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value < 2**128, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value < 2**64, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value < 2**32, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value < 2**16, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value < 2**8, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= -2**127 && value < 2**127, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= -2**63 && value < 2**63, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= -2**31 && value < 2**31, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= -2**15 && value < 2**15, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= -2**7 && value < 2**7, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
require(value < 2**255, "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
// SPDX-License-Identifier: AGPL-3.0-or-later
// Internal
// Libs
/**
* @title BoostedDualVault
* @author mStable
* @notice Accrues rewards second by second, based on a users boosted balance
* @dev Forked from rewards/staking/StakingRewards.sol
* Changes:
* - Lockup implemented in `updateReward` hook (20% unlock immediately, 80% locked for 6 months)
* - `updateBoost` hook called after every external action to reset a users boost
* - Struct packing of common data
* - Searching for and claiming of unlocked rewards
* - Add a second rewards token in the platform rewards
*/
contract BoostedDualVault is
IBoostedDualVaultWithLockup,
IRewardsRecipientWithPlatformToken,
Initializable,
InitializableRewardsDistributionRecipient,
BoostedTokenWrapper
{
using SafeERC20 for IERC20;
using StableMath for uint256;
using SafeCast for uint256;
event RewardAdded(uint256 reward, uint256 platformReward);
event Staked(address indexed user, uint256 amount, address payer);
event Withdrawn(address indexed user, uint256 amount);
event Poked(address indexed user);
event RewardPaid(address indexed user, uint256 reward, uint256 platformReward);
/// @notice token the rewards are distributed in. eg MTA
IERC20 public immutable rewardsToken;
/// @notice token the platform rewards are distributed in. eg WMATIC
IERC20 public immutable platformToken;
/// @notice contract that holds the platform tokens
PlatformTokenVendor public platformTokenVendor;
/// @notice total raw balance
uint256 public totalRaw;
/// @notice length of each staking period in seconds. 7 days = 604,800; 3 months = 7,862,400
uint64 public constant DURATION = 7 days;
/// @notice Length of token lockup, after rewards are earned
uint256 public constant LOCKUP = 26 weeks;
/// @notice Percentage of earned tokens unlocked immediately
uint64 public constant UNLOCK = 33e16;
/// @notice Timestamp for current period finish
uint256 public periodFinish;
/// @notice Reward rate for the rest of the period
uint256 public rewardRate;
/// @notice Platform reward rate for the rest of the period
uint256 public platformRewardRate;
/// @notice Last time any user took action
uint256 public lastUpdateTime;
/// @notice Ever increasing rewardPerToken rate, based on % of total supply
uint256 public rewardPerTokenStored;
/// @notice Ever increasing platformRewardPerToken rate, based on % of total supply
uint256 public platformRewardPerTokenStored;
mapping(address => UserData) public userData;
/// @notice Locked reward tracking
mapping(address => Reward[]) public userRewards;
mapping(address => uint64) public userClaim;
struct UserData {
uint128 rewardPerTokenPaid;
uint128 rewards;
uint128 platformRewardPerTokenPaid;
uint128 platformRewards;
uint64 lastAction;
uint64 rewardCount;
}
struct Reward {
uint64 start;
uint64 finish;
uint128 rate;
}
/**
* @param _nexus mStable system Nexus address
* @param _stakingToken token that is being rewarded for being staked. eg MTA, imUSD or fPmUSD/GUSD
* @param _boostDirector vMTA boost director
* @param _priceCoeff Rough price of a given LP token, to be used in boost calculations, where $1 = 1e18
* @param _boostCoeff Boost coefficent using the the boost formula
* @param _rewardsToken first token that is being distributed as a reward. eg MTA
* @param _platformToken second token that is being distributed as a reward. eg FXS for FRAX
*/
constructor(
address _nexus,
address _stakingToken,
address _boostDirector,
uint256 _priceCoeff,
uint256 _boostCoeff,
address _rewardsToken,
address _platformToken
)
InitializableRewardsDistributionRecipient(_nexus)
BoostedTokenWrapper(_stakingToken, _boostDirector, _priceCoeff, _boostCoeff)
{
rewardsToken = IERC20(_rewardsToken);
platformToken = IERC20(_platformToken);
}
/**
* @dev Initialization function for upgradable proxy contract.
* This function should be called via Proxy just after contract deployment.
* To avoid variable shadowing appended `Arg` after arguments name.
* @param _rewardsDistributorArg mStable Reward Distributor contract address
* @param _nameArg token name. eg imUSD Vault or GUSD Feeder Pool Vault
* @param _symbolArg token symbol. eg v-imUSD or v-fPmUSD/GUSD
*/
function initialize(
address _rewardsDistributorArg,
string calldata _nameArg,
string calldata _symbolArg
) external initializer {
InitializableRewardsDistributionRecipient._initialize(_rewardsDistributorArg);
BoostedTokenWrapper._initialize(_nameArg, _symbolArg);
platformTokenVendor = new PlatformTokenVendor(platformToken);
}
/**
* @dev Updates the reward for a given address, before executing function.
* Locks 80% of new rewards up for 6 months, vesting linearly from (time of last action + 6 months) to
* (now + 6 months). This allows rewards to be distributed close to how they were accrued, as opposed
* to locking up for a flat 6 months from the time of this fn call (allowing more passive accrual).
*/
modifier updateReward(address _account) {
_updateReward(_account);
_;
}
function _updateReward(address _account) internal {
uint256 currentTime = block.timestamp;
uint64 currentTime64 = SafeCast.toUint64(currentTime);
// Setting of global vars
(
uint256 newRewardPerToken,
uint256 newPlatformRewardPerToken,
uint256 lastApplicableTime
) = _rewardPerToken();
// If statement protects against loss in initialisation case
if (newRewardPerToken > 0 || newPlatformRewardPerToken > 0) {
rewardPerTokenStored = newRewardPerToken;
platformRewardPerTokenStored = newPlatformRewardPerToken;
lastUpdateTime = lastApplicableTime;
// Setting of personal vars based on new globals
if (_account != address(0)) {
UserData memory data = userData[_account];
uint256 earned_ = _earned(
_account,
data.rewardPerTokenPaid,
newRewardPerToken,
false
);
uint256 platformEarned_ = _earned(
_account,
data.platformRewardPerTokenPaid,
newPlatformRewardPerToken,
true
);
// If earned == 0, then it must either be the initial stake, or an action in the
// same block, since new rewards unlock after each block.
if (earned_ > 0) {
uint256 unlocked = earned_.mulTruncate(UNLOCK);
uint256 locked = earned_ - unlocked;
userRewards[_account].push(
Reward({
start: SafeCast.toUint64(LOCKUP + data.lastAction),
finish: SafeCast.toUint64(LOCKUP + currentTime),
rate: SafeCast.toUint128(locked / (currentTime - data.lastAction))
})
);
userData[_account] = UserData({
rewardPerTokenPaid: SafeCast.toUint128(newRewardPerToken),
rewards: SafeCast.toUint128(unlocked + data.rewards),
platformRewardPerTokenPaid: SafeCast.toUint128(newPlatformRewardPerToken),
platformRewards: data.platformRewards + SafeCast.toUint128(platformEarned_),
lastAction: currentTime64,
rewardCount: data.rewardCount + 1
});
} else {
userData[_account] = UserData({
rewardPerTokenPaid: SafeCast.toUint128(newRewardPerToken),
rewards: data.rewards,
platformRewardPerTokenPaid: SafeCast.toUint128(newPlatformRewardPerToken),
platformRewards: data.platformRewards + SafeCast.toUint128(platformEarned_),
lastAction: currentTime64,
rewardCount: data.rewardCount
});
}
}
} else if (_account != address(0)) {
// This should only be hit once, for first staker in initialisation case
userData[_account].lastAction = currentTime64;
}
}
/** @dev Updates the boost for a given address, after the rest of the function has executed */
modifier updateBoost(address _account) {
_;
_setBoost(_account);
}
/***************************************
ACTIONS - EXTERNAL
****************************************/
/**
* @dev Stakes a given amount of the StakingToken for the sender
* @param _amount Units of StakingToken
*/
function stake(uint256 _amount)
external
override
updateReward(msg.sender)
updateBoost(msg.sender)
{
_stake(msg.sender, _amount);
}
/**
* @dev Stakes a given amount of the StakingToken for a given beneficiary
* @param _beneficiary Staked tokens are credited to this address
* @param _amount Units of StakingToken
*/
function stake(address _beneficiary, uint256 _amount)
external
override
updateReward(_beneficiary)
updateBoost(_beneficiary)
{
_stake(_beneficiary, _amount);
}
/**
* @dev Withdraws stake from pool and claims any unlocked rewards.
* Note, this function is costly - the args for _claimRewards
* should be determined off chain and then passed to other fn
*/
function exit() external override updateReward(msg.sender) updateBoost(msg.sender) {
_withdraw(rawBalanceOf(msg.sender));
(uint256 first, uint256 last) = _unclaimedEpochs(msg.sender);
_claimRewards(first, last);
}
/**
* @dev Withdraws stake from pool and claims any unlocked rewards.
* @param _first Index of the first array element to claim
* @param _last Index of the last array element to claim
*/
function exit(uint256 _first, uint256 _last)
external
override
updateReward(msg.sender)
updateBoost(msg.sender)
{
_withdraw(rawBalanceOf(msg.sender));
_claimRewards(_first, _last);
}
/**
* @dev Withdraws given stake amount from the pool
* @param _amount Units of the staked token to withdraw
*/
function withdraw(uint256 _amount)
external
override
updateReward(msg.sender)
updateBoost(msg.sender)
{
_withdraw(_amount);
}
/**
* @dev Claims only the tokens that have been immediately unlocked, not including
* those that are in the lockers.
*/
function claimReward() external override updateReward(msg.sender) updateBoost(msg.sender) {
uint256 unlocked = userData[msg.sender].rewards;
userData[msg.sender].rewards = 0;
if (unlocked > 0) {
rewardsToken.safeTransfer(msg.sender, unlocked);
}
uint256 platformReward = _claimPlatformReward();
emit RewardPaid(msg.sender, unlocked, platformReward);
}
/**
* @dev Claims all unlocked rewards for sender.
* Note, this function is costly - the args for _claimRewards
* should be determined off chain and then passed to other fn
*/
function claimRewards() external override updateReward(msg.sender) updateBoost(msg.sender) {
(uint256 first, uint256 last) = _unclaimedEpochs(msg.sender);
_claimRewards(first, last);
}
/**
* @dev Claims all unlocked rewards for sender. Both immediately unlocked
* rewards and also locked rewards past their time lock.
* @param _first Index of the first array element to claim
* @param _last Index of the last array element to claim
*/
function claimRewards(uint256 _first, uint256 _last)
external
override
updateReward(msg.sender)
updateBoost(msg.sender)
{
_claimRewards(_first, _last);
}
/**
* @dev Pokes a given account to reset the boost
*/
function pokeBoost(address _account)
external
override
updateReward(_account)
updateBoost(_account)
{
emit Poked(_account);
}
/***************************************
ACTIONS - INTERNAL
****************************************/
/**
* @dev Claims all unlocked rewards for sender. Both immediately unlocked
* rewards and also locked rewards past their time lock.
* @param _first Index of the first array element to claim
* @param _last Index of the last array element to claim
*/
function _claimRewards(uint256 _first, uint256 _last) internal {
(uint256 unclaimed, uint256 lastTimestamp) = _unclaimedRewards(msg.sender, _first, _last);
userClaim[msg.sender] = uint64(lastTimestamp);
uint256 unlocked = userData[msg.sender].rewards;
userData[msg.sender].rewards = 0;
uint256 total = unclaimed + unlocked;
if (total > 0) {
rewardsToken.safeTransfer(msg.sender, total);
}
uint256 platformReward = _claimPlatformReward();
emit RewardPaid(msg.sender, total, platformReward);
}
/**
* @dev Claims any outstanding platform reward tokens
*/
function _claimPlatformReward() internal returns (uint256) {
uint256 platformReward = userData[msg.sender].platformRewards;
if (platformReward > 0) {
userData[msg.sender].platformRewards = 0;
platformToken.safeTransferFrom(
address(platformTokenVendor),
msg.sender,
platformReward
);
}
return platformReward;
}
/**
* @dev Internally stakes an amount by depositing from sender,
* and crediting to the specified beneficiary
* @param _beneficiary Staked tokens are credited to this address
* @param _amount Units of StakingToken
*/
function _stake(address _beneficiary, uint256 _amount) internal {
require(_amount > 0, "Cannot stake 0");
require(_beneficiary != address(0), "Invalid beneficiary address");
_stakeRaw(_beneficiary, _amount);
totalRaw += _amount;
emit Staked(_beneficiary, _amount, msg.sender);
}
/**
* @dev Withdraws raw units from the sender
* @param _amount Units of StakingToken
*/
function _withdraw(uint256 _amount) internal {
require(_amount > 0, "Cannot withdraw 0");
_withdrawRaw(_amount);
totalRaw -= _amount;
emit Withdrawn(msg.sender, _amount);
}
/***************************************
GETTERS
****************************************/
/**
* @dev Gets the RewardsToken
*/
function getRewardToken()
external
view
override(IRewardsDistributionRecipient, IRewardsRecipientWithPlatformToken)
returns (IERC20)
{
return rewardsToken;
}
/**
* @dev Gets the PlatformToken
*/
function getPlatformToken() external view override returns (IERC20) {
return platformToken;
}
/**
* @dev Gets the last applicable timestamp for this reward period
*/
function lastTimeRewardApplicable() public view override returns (uint256) {
return StableMath.min(block.timestamp, periodFinish);
}
/**
* @dev Calculates the amount of unclaimed rewards per token since last update,
* and sums with stored to give the new cumulative reward per token
* @return 'Reward' per staked token
*/
function rewardPerToken() public view override returns (uint256, uint256) {
(uint256 rewardPerToken_, uint256 platformRewardPerToken_, ) = _rewardPerToken();
return (rewardPerToken_, platformRewardPerToken_);
}
function _rewardPerToken()
internal
view
returns (
uint256 rewardPerToken_,
uint256 platformRewardPerToken_,
uint256 lastTimeRewardApplicable_
)
{
uint256 lastApplicableTime = lastTimeRewardApplicable(); // + 1 SLOAD
uint256 timeDelta = lastApplicableTime - lastUpdateTime; // + 1 SLOAD
// If this has been called twice in the same block, shortcircuit to reduce gas
if (timeDelta == 0) {
return (rewardPerTokenStored, platformRewardPerTokenStored, lastApplicableTime);
}
// new reward units to distribute = rewardRate * timeSinceLastUpdate
uint256 rewardUnitsToDistribute = rewardRate * timeDelta; // + 1 SLOAD
uint256 platformRewardUnitsToDistribute = platformRewardRate * timeDelta; // + 1 SLOAD
// If there is no StakingToken liquidity, avoid div(0)
// If there is nothing to distribute, short circuit
if (
totalSupply() == 0 ||
(rewardUnitsToDistribute == 0 && platformRewardUnitsToDistribute == 0)
) {
return (rewardPerTokenStored, platformRewardPerTokenStored, lastApplicableTime);
}
// new reward units per token = (rewardUnitsToDistribute * 1e18) / totalTokens
uint256 unitsToDistributePerToken = rewardUnitsToDistribute.divPrecisely(totalSupply());
uint256 platformUnitsToDistributePerToken = platformRewardUnitsToDistribute.divPrecisely(
totalRaw
);
// return summed rate
return (
rewardPerTokenStored + unitsToDistributePerToken,
platformRewardPerTokenStored + platformUnitsToDistributePerToken,
lastApplicableTime
); // + 1 SLOAD
}
/**
* @dev Returned the units of IMMEDIATELY claimable rewards a user has to receive. Note - this
* does NOT include the majority of rewards which will be locked up.
* @param _account User address
* @return Total reward amount earned
* @return Platform reward claimable
*/
function earned(address _account) public view override returns (uint256, uint256) {
(uint256 rewardPerToken_, uint256 platformRewardPerToken_) = rewardPerToken();
uint256 newEarned = _earned(
_account,
userData[_account].rewardPerTokenPaid,
rewardPerToken_,
false
);
uint256 immediatelyUnlocked = newEarned.mulTruncate(UNLOCK);
return (
immediatelyUnlocked + userData[_account].rewards,
_earned(
_account,
userData[_account].platformRewardPerTokenPaid,
platformRewardPerToken_,
true
)
);
}
/**
* @dev Calculates all unclaimed reward data, finding both immediately unlocked rewards
* and those that have passed their time lock.
* @param _account User address
* @return amount Total units of unclaimed rewards
* @return first Index of the first userReward that has unlocked
* @return last Index of the last userReward that has unlocked
*/
function unclaimedRewards(address _account)
external
view
override
returns (
uint256 amount,
uint256 first,
uint256 last,
uint256 platformAmount
)
{
(first, last) = _unclaimedEpochs(_account);
(uint256 unlocked, ) = _unclaimedRewards(_account, first, last);
(uint256 earned_, uint256 platformEarned_) = earned(_account);
amount = unlocked + earned_;
platformAmount = platformEarned_;
}
/** @dev Returns only the most recently earned rewards */
function _earned(
address _account,
uint256 _userRewardPerTokenPaid,
uint256 _currentRewardPerToken,
bool _useRawBalance
) internal view returns (uint256) {
// current rate per token - rate user previously received
uint256 userRewardDelta = _currentRewardPerToken - _userRewardPerTokenPaid;
// Short circuit if there is nothing new to distribute
if (userRewardDelta == 0) {
return 0;
}
// new reward = staked tokens * difference in rate
uint256 bal = _useRawBalance ? rawBalanceOf(_account) : balanceOf(_account);
return bal.mulTruncate(userRewardDelta);
}
/**
* @dev Gets the first and last indexes of array elements containing unclaimed rewards
*/
function _unclaimedEpochs(address _account)
internal
view
returns (uint256 first, uint256 last)
{
uint64 lastClaim = userClaim[_account];
uint256 firstUnclaimed = _findFirstUnclaimed(lastClaim, _account);
uint256 lastUnclaimed = _findLastUnclaimed(_account);
return (firstUnclaimed, lastUnclaimed);
}
/**
* @dev Sums the cumulative rewards from a valid range
*/
function _unclaimedRewards(
address _account,
uint256 _first,
uint256 _last
) internal view returns (uint256 amount, uint256 latestTimestamp) {
uint256 currentTime = block.timestamp;
uint64 lastClaim = userClaim[_account];
// Check for no rewards unlocked
uint256 totalLen = userRewards[_account].length;
if (_first == 0 && _last == 0) {
if (totalLen == 0 || currentTime <= userRewards[_account][0].start) {
return (0, currentTime);
}
}
// If there are previous unlocks, check for claims that would leave them untouchable
if (_first > 0) {
require(
lastClaim >= userRewards[_account][_first - 1].finish,
"Invalid _first arg: Must claim earlier entries"
);
}
uint256 count = _last - _first + 1;
for (uint256 i = 0; i < count; i++) {
uint256 id = _first + i;
Reward memory rwd = userRewards[_account][id];
require(currentTime >= rwd.start && lastClaim <= rwd.finish, "Invalid epoch");
uint256 endTime = StableMath.min(rwd.finish, currentTime);
uint256 startTime = StableMath.max(rwd.start, lastClaim);
uint256 unclaimed = (endTime - startTime) * rwd.rate;
amount += unclaimed;
}
// Calculate last relevant timestamp here to allow users to avoid issue of OOG errors
// by claiming rewards in batches.
latestTimestamp = StableMath.min(currentTime, userRewards[_account][_last].finish);
}
/**
* @dev Uses binarysearch to find the unclaimed lockups for a given account
*/
function _findFirstUnclaimed(uint64 _lastClaim, address _account)
internal
view
returns (uint256 first)
{
uint256 len = userRewards[_account].length;
if (len == 0) return 0;
// Binary search
uint256 min = 0;
uint256 max = len - 1;
// Will be always enough for 128-bit numbers
for (uint256 i = 0; i < 128; i++) {
if (min >= max) break;
uint256 mid = (min + max + 1) / 2;
if (_lastClaim > userRewards[_account][mid].start) {
min = mid;
} else {
max = mid - 1;
}
}
return min;
}
/**
* @dev Uses binarysearch to find the unclaimed lockups for a given account
*/
function _findLastUnclaimed(address _account) internal view returns (uint256 first) {
uint256 len = userRewards[_account].length;
if (len == 0) return 0;
// Binary search
uint256 min = 0;
uint256 max = len - 1;
// Will be always enough for 128-bit numbers
for (uint256 i = 0; i < 128; i++) {
if (min >= max) break;
uint256 mid = (min + max + 1) / 2;
if (block.timestamp > userRewards[_account][mid].start) {
min = mid;
} else {
max = mid - 1;
}
}
return min;
}
/***************************************
ADMIN
****************************************/
/**
* @dev Notifies the contract that new rewards have been added.
* Calculates an updated rewardRate based on the rewards in period.
* @param _reward Units of RewardToken that have been added to the pool
*/
function notifyRewardAmount(uint256 _reward)
external
override(IRewardsDistributionRecipient, IRewardsRecipientWithPlatformToken)
onlyRewardsDistributor
updateReward(address(0))
{
require(_reward < 1e24, "Cannot notify with more than a million units");
uint256 newPlatformRewards = platformToken.balanceOf(address(this));
if (newPlatformRewards > 0) {
platformToken.safeTransfer(address(platformTokenVendor), newPlatformRewards);
}
uint256 currentTime = block.timestamp;
// If previous period over, reset rewardRate
if (currentTime >= periodFinish) {
rewardRate = _reward / DURATION;
platformRewardRate = newPlatformRewards / DURATION;
}
// If additional reward to existing period, calc sum
else {
uint256 remaining = periodFinish - currentTime;
uint256 leftoverReward = remaining * rewardRate;
rewardRate = (_reward + leftoverReward) / DURATION;
uint256 leftoverPlatformReward = remaining * platformRewardRate;
platformRewardRate = (newPlatformRewards + leftoverPlatformReward) / DURATION;
}
lastUpdateTime = currentTime;
periodFinish = currentTime + DURATION;
emit RewardAdded(_reward, newPlatformRewards);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_nexus","type":"address"},{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_boostDirector","type":"address"},{"internalType":"uint256","name":"_priceCoeff","type":"uint256"},{"internalType":"uint256","name":"_boostCoeff","type":"uint256"},{"internalType":"address","name":"_rewardsToken","type":"address"},{"internalType":"address","name":"_platformToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Poked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"platformReward","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"platformReward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"payer","type":"address"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"DURATION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCKUP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNLOCK","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boostCoeff","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boostDirector","outputs":[{"internalType":"contract IBoostDirector","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_first","type":"uint256"},{"internalType":"uint256","name":"_last","type":"uint256"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_first","type":"uint256"},{"internalType":"uint256","name":"_last","type":"uint256"}],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPlatformToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardsDistributorArg","type":"address"},{"internalType":"string","name":"_nameArg","type":"string"},{"internalType":"string","name":"_symbolArg","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nexus","outputs":[{"internalType":"contract INexus","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reward","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformRewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformRewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformTokenVendor","outputs":[{"internalType":"contract PlatformTokenVendor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"pokeBoost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"priceCoeff","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"rawBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardsDistributor","type":"address"}],"name":"setRewardsDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRaw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"unclaimedRewards","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"first","type":"uint256"},{"internalType":"uint256","name":"last","type":"uint256"},{"internalType":"uint256","name":"platformAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userClaim","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userData","outputs":[{"internalType":"uint128","name":"rewardPerTokenPaid","type":"uint128"},{"internalType":"uint128","name":"rewards","type":"uint128"},{"internalType":"uint128","name":"platformRewardPerTokenPaid","type":"uint128"},{"internalType":"uint128","name":"platformRewards","type":"uint128"},{"internalType":"uint64","name":"lastAction","type":"uint64"},{"internalType":"uint64","name":"rewardCount","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userRewards","outputs":[{"internalType":"uint64","name":"start","type":"uint64"},{"internalType":"uint64","name":"finish","type":"uint64"},{"internalType":"uint128","name":"rate","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101606040523480156200001257600080fd5b506040516200402d3803806200402d8339810160408190526200003591620000fd565b858585858a806001600160a01b038116620000965760405162461bcd60e51b815260206004820152601560248201527f4e657875732061646472657373206973207a65726f0000000000000000000000604482015260640160405180910390fd5b6001600160601b0319606091821b811660805295811b861660a05293841b851660c052506101009190915260e05292831b811661012052911b1661014052506200017f9350505050565b80516001600160a01b0381168114620000f857600080fd5b919050565b600080600080600080600060e0888a03121562000118578283fd5b6200012388620000e0565b96506200013360208901620000e0565b95506200014360408901620000e0565b945060608801519350608088015192506200016160a08901620000e0565b91506200017160c08901620000e0565b905092959891949750929550565b60805160601c60a05160601c60c05160601c60e051610100516101205160601c6101405160601c613de26200024b600039600081816105f2015281816107b301528181610b9201528181610c3301528181610f57015261228c0152600081816104ff0152818161078b015281816110ce01526119940152600081816104120152611a46015260008181610803015261267a0152600081816106730152611aac015260008181610556015281816125e30152612aef01526000818161061d01526123e20152613de26000f3fe60806040523480156200001157600080fd5b5060043610620002d35760003560e01c806380faa57d1162000189578063c891091311620000e1578063df136d651162000093578063df136d6514620007d5578063e882025a14620007df578063e9fad8ee14620007e9578063ebe2b12b14620007f3578063f62aa97514620007fd578063f9ce7d47146200082557620002d3565b8063c891091314620006a9578063c8f33c91146200075a578063cd3daf9d1462000764578063cf7bf6b7146200076e578063d1af0c7d1462000785578063d1b812cd14620007ad57620002d3565b8063a3f5c1d2116200013b578063a3f5c1d21462000617578063a694fc3a146200063f578063adc9772e1462000656578063b43082ec146200066d578063b88a802f1462000695578063c5869a06146200069f57620002d3565b806380faa57d1462000582578063845aef4b146200058c578063906571471462000597578063949813b814620005ae57806395d89b4114620005e65780639ed374f714620005f057620002d3565b8063372500ab116200023d57806363c2a20a11620001ef57806363c2a20a146200049f57806367ba3d9014620004e657806369940d7914620004fd57806370a08231146200052457806372f702f314620005505780637b0a47ee146200057857620002d3565b8063372500ab146200040257806338d3eb38146200040c5780633c6b16ab14620004345780633f2a5540146200044b578063523993da1462000478578063594dd432146200048857620002d3565b80631976214311620002975780631976214314620003965780631be0528914620003af5780632056797114620003ba5780632af9cc4114620003c45780632e1a7d4d14620003db578063313ce56714620003f257620002d3565b80628cc26214620002d857806306fdde0314620003095780630a6b433f146200032257806312064c34146200036757806318160ddd146200038d575b600080fd5b620002ef620002e936600462002f08565b62000839565b604080519283526020830191909152015b60405180910390f35b6200031362000915565b60405162000300919062003090565b6200034e6200033336600462002f08565b6043602052600090815260409020546001600160401b031681565b6040516001600160401b03909116815260200162000300565b6200037e6200037836600462002f08565b620009af565b60405190815260200162000300565b6036546200037e565b620003ad620003a736600462002f08565b620009ce565b005b6200034e62093a8081565b6200037e603a5481565b620003ad620003d536600462003050565b620009fa565b620003ad620003ec3660046200301e565b62000a39565b6040516012815260200162000300565b620003ad62000a61565b6200037e7f000000000000000000000000000000000000000000000000000000000000000081565b620003ad620004453660046200301e565b62000a9d565b6033546200045f906001600160a01b031681565b6040516001600160a01b03909116815260200162000300565b6200034e670494654067e1000081565b620003ad6200049936600462003050565b62000d67565b620004b6620004b036600462002fce565b62000d80565b604080516001600160401b0394851681529390921660208401526001600160801b03169082015260600162000300565b6200037e620004f736600462002f08565b62000dd3565b7f00000000000000000000000000000000000000000000000000000000000000006200045f565b6200037e6200053536600462002f08565b6001600160a01b031660009081526037602052604090205490565b6200045f7f000000000000000000000000000000000000000000000000000000000000000081565b6200037e603c5481565b6200037e62000e0a565b6200037e62eff10081565b620003ad620005a836600462002f46565b62000e1f565b620005c5620005bf36600462002f08565b62000fed565b60408051948552602085019390935291830152606082015260800162000300565b6200031362001043565b7f00000000000000000000000000000000000000000000000000000000000000006200045f565b6200045f7f000000000000000000000000000000000000000000000000000000000000000081565b620003ad620006503660046200301e565b62001054565b620003ad6200066736600462002fce565b6200106d565b6200045f7f000000000000000000000000000000000000000000000000000000000000000081565b620003ad62001086565b6200037e60405481565b6200070e620006ba36600462002f08565b6041602052600090815260409020805460018201546002909201546001600160801b0380831693600160801b93849004821693818316939104909116906001600160401b0380821691600160401b90041686565b604080516001600160801b039788168152958716602087015293861693850193909352931660608301526001600160401b0392831660808301529190911660a082015260c00162000300565b6200037e603e5481565b620002ef6200114d565b620003ad6200077f36600462002f08565b62001169565b6200045f7f000000000000000000000000000000000000000000000000000000000000000081565b6200045f7f000000000000000000000000000000000000000000000000000000000000000081565b6200037e603f5481565b6200037e603d5481565b620003ad620011b6565b6200037e603b5481565b6200037e7f000000000000000000000000000000000000000000000000000000000000000081565b6039546200045f906001600160a01b031681565b600080600080620008496200114d565b6001600160a01b03871660009081526041602052604081205492945090925090620008819087906001600160801b03168584620011e0565b905060006200089982670494654067e100006200124f565b6001600160a01b038816600090815260416020526040902054909150620008d190600160801b90046001600160801b031682620030f3565b6001600160a01b038816600090815260416020526040902060019081015462000908918a916001600160801b0316908790620011e0565b9550955050505050915091565b6060603480546200092690620031bf565b80601f01602080910402602001604051908101604052809291908181526020018280546200095490620031bf565b8015620009a55780601f106200097957610100808354040283529160200191620009a5565b820191906000526020600020905b8154815290600101906020018083116200098757829003601f168201915b5050505050905090565b6001600160a01b0381166000908152603860205260409020545b919050565b620009d86200126d565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b3362000a0681620012db565b3362000a1c62000a1633620009af565b6200186c565b62000a2884846200190e565b62000a338162001a0f565b50505050565b3362000a4581620012db565b3362000a51836200186c565b62000a5c8162001a0f565b505050565b3362000a6d81620012db565b3360008062000a7c3362001c3e565b9150915062000a8c82826200190e565b505062000a998162001a0f565b5050565b6033546001600160a01b0316331462000afd5760405162461bcd60e51b815260206004820181905260248201527f43616c6c6572206973206e6f7420726577617264206469737472696275746f7260448201526064015b60405180910390fd5b600062000b0a81620012db565b69d3c21bcecceda1000000821062000b7a5760405162461bcd60e51b815260206004820152602c60248201527f43616e6e6f74206e6f746966792077697468206d6f7265207468616e2061206d60448201526b696c6c696f6e20756e69747360a01b606482015260840162000af4565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801562000bdd57600080fd5b505afa15801562000bf2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c18919062003037565b9050801562000c5d5760395462000c5d906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691168362001c8b565b603b544290811062000c935762000c7862093a808562003133565b603c5562000c8a62093a808362003133565b603d5562000d11565b600081603b5462000ca5919062003176565b90506000603c548262000cb9919062003154565b905062093a8062000ccb8288620030f3565b62000cd7919062003133565b603c55603d5460009062000cec908462003154565b905062093a8062000cfe8287620030f3565b62000d0a919062003133565b603d555050505b603e81905562000d2562093a8082620030f3565b603b5560408051858152602081018490527f6c07ee05dcf262f13abf9d87b846ee789d2f90fe991d495acd7d7fc109ee1f55910160405180910390a150505050565b3362000d7381620012db565b3362000a2884846200190e565b6042602052816000526040600020818154811062000d9d57600080fd5b6000918252602090912001546001600160401b038082169350600160401b8204169150600160801b90046001600160801b031683565b600062000e0462000de483620009af565b6001600160a01b0384166000908152603760205260409020549062001cf0565b92915050565b600062000e1a42603b5462001d13565b905090565b600054610100900460ff168062000e355750303b155b8062000e44575060005460ff16155b62000ea95760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b606482015260840162000af4565b600054610100900460ff1615801562000ed5576000805460ff1961ff0019909116610100171660011790555b62000ee086620009d8565b62000f5585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8901819004810282018101909252878152925087915086908190840183828082843760009201919091525062001d2a92505050565b7f000000000000000000000000000000000000000000000000000000000000000060405162000f849062002e15565b6001600160a01b039091168152602001604051809103906000f08015801562000fb1573d6000803e3d6000fd5b50603980546001600160a01b0319166001600160a01b0392909216919091179055801562000fe5576000805461ff00191690555b505050505050565b60008060008062000ffe8562001c3e565b909350915060006200101286858562001d6e565b509050600080620010238862000839565b9092509050620010348284620030f3565b96508093505050509193509193565b6060603580546200092690620031bf565b336200106081620012db565b3362000a5133846200212a565b816200107981620012db565b8262000a2884846200212a565b336200109281620012db565b33600081815260416020526040902080546001600160801b03808216909255600160801b9004168015620010f657620010f66001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338362001c8b565b60006200110262002231565b604080518481526020810183905291925033917fd6f2c8500df5b44f11e9e48b91ff9f1b9d81bc496d55570c2b1b75bf65243f51910160405180910390a2505062000a998162001a0f565b6000806000806200115d620022b7565b50909450925050509091565b806200117581620012db565b60405182906001600160a01b038216907fa31b3b303c759fa7ee31d89a1a6fb7eb704d8fe5c87aa4f60f54468ff121bee890600090a262000a5c8162001a0f565b33620011c281620012db565b33620011d262000a1633620009af565b60008062000a7c3362001c3e565b600080620011ef858562003176565b9050806200120257600091505062001247565b60008362001229576001600160a01b03871660009081526037602052604090205462001234565b6200123487620009af565b90506200124281836200124f565b925050505b949350505050565b6000620012668383670de0b6b3a7640000620023c3565b9392505050565b62001277620023de565b6001600160a01b0316336001600160a01b031614620012d95760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920676f7665726e6f722063616e206578656375746500000000000000604482015260640162000af4565b565b426000620012e98262002475565b90506000806000620012fa620022b7565b9250925092506000831180620013105750600082115b156200181d57603f8390556040829055603e8190556001600160a01b0386161562001817576001600160a01b0386166000908152604160209081526040808320815160c08101835281546001600160801b03808216808452600160801b9283900482169684019690965260018401548082169584019590955293049092166060830152600201546001600160401b038082166080840152600160401b9091041660a08201529190620013c69089908784620011e0565b90506000620013e68984604001516001600160801b0316876001620011e0565b90508115620016cd5760006200140583670494654067e100006200124f565b9050600062001415828562003176565b9050604260008c6001600160a01b03166001600160a01b0316815260200190815260200160002060405180606001604052806200146f88608001516001600160401b031662eff100620014699190620030f3565b62002475565b6001600160401b0316815260200162001490620014698e62eff100620030f3565b6001600160401b03168152602001620014cf88608001516001600160401b03168e620014bd919062003176565b620014c9908662003133565b620024df565b6001600160801b0390811690915282546001810184556000938452602093849020835191018054948401516040948501518416600160801b026001600160401b03918216600160401b0267ffffffffffffffff60401b199290941667ffffffffffffffff1990971696909617169190911790911692909217909155805160c08101909152806200155f8a620024df565b6001600160801b031681526020016200158c87602001516001600160801b031685620014c99190620030f3565b6001600160801b03168152602001620015a589620024df565b6001600160801b03168152602001620015be85620024df565b8760600151620015cf9190620030c5565b6001600160801b031681526020018a6001600160401b031681526020018660a001516001620015ff91906200310e565b6001600160401b039081169091526001600160a01b038d1660009081526041602090815260409182902084518154928601516001600160801b03908116600160801b9081029282166001600160801b03199586161782169290921783559386015160018301805460608901518716909302918616929094169190911790931692909217905560808301516002909101805460a0909401518316600160401b0267ffffffffffffffff60401b199290931667ffffffffffffffff19909416939093171617905550620018139050565b6040518060c00160405280620016e388620024df565b6001600160801b0316815260200184602001516001600160801b031681526020016200170f87620024df565b6001600160801b031681526020016200172883620024df565b8560600151620017399190620030c5565b6001600160801b0390811682526001600160401b03808b1660208085019190915260a08089015183166040958601526001600160a01b038f1660009081526041835285902086518154938801518616600160801b9081029187166001600160801b03199586161787169190911782559587015160018201805460608a01518816909802918716979094169690961790941694909417905560808401516002909201805494909301518116600160401b0267ffffffffffffffff60401b199290911667ffffffffffffffff1990941693909317169190911790555b5050505b62000fe5565b6001600160a01b0386161562000fe5576001600160a01b038616600090815260416020526040902060020180546001600160401b03861667ffffffffffffffff19909116179055505050505050565b60008111620018b25760405162461bcd60e51b8152602060048201526011602482015270043616e6e6f74207769746864726177203607c1b604482015260640162000af4565b620018bd8162002546565b80603a6000828254620018d1919062003176565b909155505060405181815233907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d59060200160405180910390a250565b6000806200191e33858562001d6e565b336000908152604360209081526040808320805467ffffffffffffffff19166001600160401b0386161790556041909152812080546001600160801b03808216909255939550919350600160801b90920416906200197d8285620030f3565b90508015620019bc57620019bc6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338362001c8b565b6000620019c862002231565b604080518481526020810183905291925033917fd6f2c8500df5b44f11e9e48b91ff9f1b9d81bc496d55570c2b1b75bf65243f51910160405180910390a250505050505050565b6001600160a01b03811660009081526038602090815260408083205460379092528220549091670de0b6b3a7640000908162001a6c7f00000000000000000000000000000000000000000000000000000000000000008662003154565b62001a78919062003133565b9050670de0b6b3a7640000811062001b405760405163f8b2cb4f60e01b81526001600160a01b0386811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063f8b2cb4f90602401602060405180830381600087803b15801562001af357600080fd5b505af115801562001b08573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001b2e919062003037565b905062001b3c828262002621565b9250505b600062001b4e85846200124f565b905083811462000fe557808460365462001b69919062003176565b62001b759190620030f3565b6036556001600160a01b03861660009081526037602052604090208190558381111562001bec576001600160a01b03861660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef62001bd5878562003176565b60405190815260200160405180910390a362000fe5565b60006001600160a01b0387167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef62001c25848862003176565b60405190815260200160405180910390a3505050505050565b6001600160a01b03811660009081526043602052604081205481906001600160401b03168162001c6f82866200272d565b9050600062001c7e8662002845565b9194509092505050915091565b6040516001600160a01b03831660248201526044810182905262000a5c90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915262002958565b60008162001d07670de0b6b3a76400008562003154565b62001266919062003133565b600081831162001d24578262001266565b50919050565b62001d436033805460ff60a01b1916600160a01b179055565b815162001d5890603490602085019062002e23565b50805162000a5c90603590602084019062002e23565b6001600160a01b0383166000908152604360209081526040808320546042909252822054829142916001600160401b03909116908615801562001daf575085155b1562001e255780158062001e0f57506001600160a01b0388166000908152604260205260408120805490919062001df657634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b03168311155b1562001e25576000839450945050505062002122565b861562001ef8576001600160a01b038816600090815260426020526040902062001e5160018962003176565b8154811062001e7057634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b03600160401b9091048116908316101562001ef85760405162461bcd60e51b815260206004820152602e60248201527f496e76616c6964205f6669727374206172673a204d75737420636c61696d206560448201526d61726c69657220656e747269657360901b606482015260840162000af4565b600062001f06888862003176565b62001f13906001620030f3565b905060005b81811015620020b857600062001f2f828b620030f3565b6001600160a01b038c166000908152604260205260408120805492935090918390811062001f6d57634e487b7160e01b600052603260045260246000fd5b60009182526020918290206040805160608101825292909101546001600160401b03808216808552600160401b830490911694840194909452600160801b90046001600160801b0316908201529150871080159062001fe2575080602001516001600160401b0316866001600160401b031611155b620020205760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840cae0dec6d609b1b604482015260640162000af4565b60006200203b82602001516001600160401b03168962001d13565b905060006200206183600001516001600160401b0316896001600160401b031662002a31565b9050600083604001516001600160801b0316828462002081919062003176565b6200208d919062003154565b90506200209b818d620030f3565b9b5050505050508080620020af90620031f6565b91505062001f18565b506001600160a01b038916600090815260426020526040902080546200211b9186918a908110620020f957634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160401b90046001600160401b031662001d13565b9450505050505b935093915050565b600081116200216d5760405162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b604482015260640162000af4565b6001600160a01b038216620021c55760405162461bcd60e51b815260206004820152601b60248201527f496e76616c69642062656e656669636961727920616464726573730000000000604482015260640162000af4565b620021d1828262002a49565b80603a6000828254620021e59190620030f3565b9091555050604080518281523360208201526001600160a01b038416917f9f9e4044c5742cca66ca090b21552bac14645e68bad7a92364a9d9ff18111a1c910160405180910390a25050565b33600090815260416020526040812060010154600160801b90046001600160801b0316801562000e1a5733600081815260416020526040902060010180546001600160801b0316905560395462000e1a916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169216908462002b2f565b600080600080620022c762000e0a565b90506000603e5482620022db919062003176565b905080620022f75750603f5460405490945092509050620023be565b600081603c5462002309919062003154565b9050600082603d546200231d919062003154565b90506200232960365490565b15806200233e5750811580156200233e575080155b156200235b57603f546040548596509650965050505050620023be565b6000620023736200236b60365490565b849062001cf0565b905060006200238e603a548462001cf090919063ffffffff16565b905081603f54620023a09190620030f3565b81604054620023b09190620030f3565b879850985098505050505050505b909192565b600081620023d2848662003154565b62001247919062003133565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b1580156200243a57600080fd5b505afa1580156200244f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e1a919062002f27565b6000600160401b8210620024db5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b606482015260840162000af4565b5090565b6000600160801b8210620024db5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b606482015260840162000af4565b603354600160a01b900460ff16620025a15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000af4565b6033805460ff60a01b191690553360009081526038602052604081208054839290620025cf90849062003176565b909155506200260b90506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338362001c8b565b506033805460ff60a01b1916600160a01b179055565b600081620026395750670de0b6b3a764000062000e04565b6000620026546200264e85620f424062003154565b62002b69565b90506000620026638262002b69565b9050600062002673828462003154565b905080600a7f0000000000000000000000000000000000000000000000000000000000000000620026af88697f0e10af47c1c700000062001d13565b620026bb919062003154565b620026c7919062003133565b620026db90670de0b6b3a764000062003154565b620026e7919062003133565b9350620027236729a2241af62c00006200271d670de0b6b3a76400006200271788670d99a8cec7e20000620030f3565b62002a31565b62001d13565b9695505050505050565b6001600160a01b038116600090815260426020526040812054806200275757600091505062000e04565b6000806200276760018462003176565b905060005b60808110156200283a5781831062002784576200283a565b60006002620027948486620030f3565b620027a1906001620030f3565b620027ad919062003133565b6001600160a01b038816600090815260426020526040902080549192509082908110620027ea57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b039081169089161115620028145780935062002824565b6200282160018262003176565b92505b50806200283181620031f6565b9150506200276c565b509095945050505050565b6001600160a01b038116600090815260426020526040812054806200286f576000915050620009c9565b6000806200287f60018462003176565b905060005b60808110156200294e578183106200289c576200294e565b60006002620028ac8486620030f3565b620028b9906001620030f3565b620028c5919062003133565b6001600160a01b0388166000908152604260205260409020805491925090829081106200290257634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b0316421115620029285780935062002938565b6200293560018262003176565b92505b50806200294581620031f6565b91505062002884565b5090949350505050565b6000620029af826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662002d0d9092919063ffffffff16565b80519091501562000a5c5780806020019051810190620029d0919062002ffc565b62000a5c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000af4565b600081831162002a42578162001266565b5090919050565b603354600160a01b900460ff1662002aa45760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000af4565b6033805460ff60a01b191690556001600160a01b0382166000908152603860205260408120805483929062002adb908490620030f3565b9091555062002b1890506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633308462002b2f565b50506033805460ff60a01b1916600160a01b179055565b6040516001600160a01b038085166024830152831660448201526064810182905262000a339085906323b872dd60e01b9060840162001cb8565b60008162002b7a57506000620009c9565b816001600160801b821062002b945760809190911c9060401b5b600160401b821062002bab5760409190911c9060201b5b640100000000821062002bc35760209190911c9060101b5b62010000821062002bd95760109190911c9060081b5b610100821062002bee5760089190911c9060041b5b6010821062002c025760049190911c9060021b5b6008821062002c0f5760011b5b600162002c1d828662003133565b62002c299083620030f3565b901c9050600162002c3b828662003133565b62002c479083620030f3565b901c9050600162002c59828662003133565b62002c659083620030f3565b901c9050600162002c77828662003133565b62002c839083620030f3565b901c9050600162002c95828662003133565b62002ca19083620030f3565b901c9050600162002cb3828662003133565b62002cbf9083620030f3565b901c9050600162002cd1828662003133565b62002cdd9083620030f3565b901c9050600062002cef828662003133565b905080821062002d00578062002d02565b815b9350505050620009c9565b606062001247848460008585843b62002d695760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000af4565b600080866001600160a01b0316858760405162002d87919062003072565b60006040518083038185875af1925050503d806000811462002dc6576040519150601f19603f3d011682016040523d82523d6000602084013e62002dcb565b606091505b5091509150620012428282866060831562002de857508162001266565b82511562002df95782518084602001fd5b8160405162461bcd60e51b815260040162000af4919062003090565b610b69806200324483390190565b82805462002e3190620031bf565b90600052602060002090601f01602090048101928262002e55576000855562002ea0565b82601f1062002e7057805160ff191683800117855562002ea0565b8280016001018555821562002ea0579182015b8281111562002ea057825182559160200191906001019062002e83565b50620024db9291505b80821115620024db576000815560010162002ea9565b60008083601f84011262002ed1578182fd5b5081356001600160401b0381111562002ee8578182fd5b60208301915083602082850101111562002f0157600080fd5b9250929050565b60006020828403121562002f1a578081fd5b813562001266816200322a565b60006020828403121562002f39578081fd5b815162001266816200322a565b60008060008060006060868803121562002f5e578081fd5b853562002f6b816200322a565b945060208601356001600160401b038082111562002f87578283fd5b62002f9589838a0162002ebf565b9096509450604088013591508082111562002fae578283fd5b5062002fbd8882890162002ebf565b969995985093965092949392505050565b6000806040838503121562002fe1578182fd5b823562002fee816200322a565b946020939093013593505050565b6000602082840312156200300e578081fd5b8151801515811462001266578182fd5b60006020828403121562003030578081fd5b5035919050565b60006020828403121562003049578081fd5b5051919050565b6000806040838503121562003063578182fd5b50508035926020909101359150565b600082516200308681846020870162003190565b9190910192915050565b6000602082528251806020840152620030b181604085016020870162003190565b601f01601f19169190910160400192915050565b60006001600160801b03808316818516808303821115620030ea57620030ea62003214565b01949350505050565b6000821982111562003109576200310962003214565b500190565b60006001600160401b03808316818516808303821115620030ea57620030ea62003214565b6000826200314f57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161562003171576200317162003214565b500290565b6000828210156200318b576200318b62003214565b500390565b60005b83811015620031ad57818101518382015260200162003193565b8381111562000a335750506000910152565b600281046001821680620031d457607f821691505b6020821081141562001d2457634e487b7160e01b600052602260045260246000fd5b60006000198214156200320d576200320d62003214565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146200324057600080fd5b5056fe60c06040523480156200001157600080fd5b5060405162000b6938038062000b698339810160408190526200003491620004ad565b33606081811b60a05282901b6001600160601b031916608052620000669082906200006d602090811b6200010617901c565b5062000575565b62000093816000846001600160a01b0316620000be60201b62000135179092919060201c565b620000ba81600019846001600160a01b0316620000be60201b62000135179092919060201c565b5050565b8015806200014c5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156200010f57600080fd5b505afa15801562000124573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200014a9190620004d6565b155b620001c45760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091526200021c9185916200022116565b505050565b60006200027d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620002ff60201b62000285179092919060201c565b8051909150156200021c57808060200190518101906200029e91906200048b565b6200021c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620001bb565b60606200031084846000856200031a565b90505b9392505050565b6060824710156200037d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620001bb565b843b620003cd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001bb565b600080866001600160a01b03168587604051620003eb9190620004ef565b60006040518083038185875af1925050503d80600081146200042a576040519150601f19603f3d011682016040523d82523d6000602084013e6200042f565b606091505b509092509050620004428282866200044d565b979650505050505050565b606083156200045e57508162000313565b8251156200046f5782518084602001fd5b8160405162461bcd60e51b8152600401620001bb91906200050d565b6000602082840312156200049d578081fd5b8151801515811462000313578182fd5b600060208284031215620004bf578081fd5b81516001600160a01b038116811462000313578182fd5b600060208284031215620004e8578081fd5b5051919050565b600082516200050381846020870162000542565b9190910192915050565b60006020825282518060208401526200052e81604085016020870162000542565b601f01601f19169190910160400192915050565b60005b838110156200055f57818101518382015260200162000545565b838111156200056f576000848401525b50505050565b60805160601c60a05160601c6105be620005ab60003960008181604b015260e0015260008181608e015260bf01526105be6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063488a49e314610046578063d1b812cd14610089578063d8245bb9146100b0575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6100b86100ba565b005b6101047f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610106565b565b61011b6001600160a01b038316826000610135565b6101316001600160a01b03831682600019610135565b5050565b8015806101be5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561018457600080fd5b505afa158015610198573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bc91906104f1565b155b61022e5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084015b60405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261028090849061029e565b505050565b60606102948484600085610370565b90505b9392505050565b60006102f3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166102859092919063ffffffff16565b805190915015610280578080602001905181019061031191906104d1565b6102805760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610225565b6060824710156103d15760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610225565b843b61041f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610225565b600080866001600160a01b0316858760405161043b9190610509565b60006040518083038185875af1925050503d8060008114610478576040519150601f19603f3d011682016040523d82523d6000602084013e61047d565b606091505b509150915061048d828286610498565b979650505050505050565b606083156104a7575081610297565b8251156104b75782518084602001fd5b8160405162461bcd60e51b81526004016102259190610525565b6000602082840312156104e2578081fd5b81518015158114610297578182fd5b600060208284031215610502578081fd5b5051919050565b6000825161051b818460208701610558565b9190910192915050565b6000602082528251806020840152610544816040850160208701610558565b601f01601f19169190910160400192915050565b60005b8381101561057357818101518382015260200161055b565b83811115610582576000848401525b5050505056fea26469706673582212208838c99418c2fb1b6066b8d85d9292abc5fd50cb76c79cd3d0b382708da20b6864736f6c63430008020033a2646970667358221220877ea06ffccc72129161deabbdeaf9b4a6bc268366fcadafe70ce7d8c8d8609764736f6c63430008020033000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb30000000000000000000000004eaa01974b6594c0ee62ffd7fee56cf11e6af936000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd35920000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000009000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd2000000000000000000000000dbdb4d16eda451d0503b854cf79d55697f90c8df
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620002d35760003560e01c806380faa57d1162000189578063c891091311620000e1578063df136d651162000093578063df136d6514620007d5578063e882025a14620007df578063e9fad8ee14620007e9578063ebe2b12b14620007f3578063f62aa97514620007fd578063f9ce7d47146200082557620002d3565b8063c891091314620006a9578063c8f33c91146200075a578063cd3daf9d1462000764578063cf7bf6b7146200076e578063d1af0c7d1462000785578063d1b812cd14620007ad57620002d3565b8063a3f5c1d2116200013b578063a3f5c1d21462000617578063a694fc3a146200063f578063adc9772e1462000656578063b43082ec146200066d578063b88a802f1462000695578063c5869a06146200069f57620002d3565b806380faa57d1462000582578063845aef4b146200058c578063906571471462000597578063949813b814620005ae57806395d89b4114620005e65780639ed374f714620005f057620002d3565b8063372500ab116200023d57806363c2a20a11620001ef57806363c2a20a146200049f57806367ba3d9014620004e657806369940d7914620004fd57806370a08231146200052457806372f702f314620005505780637b0a47ee146200057857620002d3565b8063372500ab146200040257806338d3eb38146200040c5780633c6b16ab14620004345780633f2a5540146200044b578063523993da1462000478578063594dd432146200048857620002d3565b80631976214311620002975780631976214314620003965780631be0528914620003af5780632056797114620003ba5780632af9cc4114620003c45780632e1a7d4d14620003db578063313ce56714620003f257620002d3565b80628cc26214620002d857806306fdde0314620003095780630a6b433f146200032257806312064c34146200036757806318160ddd146200038d575b600080fd5b620002ef620002e936600462002f08565b62000839565b604080519283526020830191909152015b60405180910390f35b6200031362000915565b60405162000300919062003090565b6200034e6200033336600462002f08565b6043602052600090815260409020546001600160401b031681565b6040516001600160401b03909116815260200162000300565b6200037e6200037836600462002f08565b620009af565b60405190815260200162000300565b6036546200037e565b620003ad620003a736600462002f08565b620009ce565b005b6200034e62093a8081565b6200037e603a5481565b620003ad620003d536600462003050565b620009fa565b620003ad620003ec3660046200301e565b62000a39565b6040516012815260200162000300565b620003ad62000a61565b6200037e7f0000000000000000000000000000000000000000000000000de0b6b3a764000081565b620003ad620004453660046200301e565b62000a9d565b6033546200045f906001600160a01b031681565b6040516001600160a01b03909116815260200162000300565b6200034e670494654067e1000081565b620003ad6200049936600462003050565b62000d67565b620004b6620004b036600462002fce565b62000d80565b604080516001600160401b0394851681529390921660208401526001600160801b03169082015260600162000300565b6200037e620004f736600462002f08565b62000dd3565b7f000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd26200045f565b6200037e6200053536600462002f08565b6001600160a01b031660009081526037602052604090205490565b6200045f7f0000000000000000000000004eaa01974b6594c0ee62ffd7fee56cf11e6af93681565b6200037e603c5481565b6200037e62000e0a565b6200037e62eff10081565b620003ad620005a836600462002f46565b62000e1f565b620005c5620005bf36600462002f08565b62000fed565b60408051948552602085019390935291830152606082015260800162000300565b6200031362001043565b7f000000000000000000000000dbdb4d16eda451d0503b854cf79d55697f90c8df6200045f565b6200045f7f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb381565b620003ad620006503660046200301e565b62001054565b620003ad6200066736600462002fce565b6200106d565b6200045f7f000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd359281565b620003ad62001086565b6200037e60405481565b6200070e620006ba36600462002f08565b6041602052600090815260409020805460018201546002909201546001600160801b0380831693600160801b93849004821693818316939104909116906001600160401b0380821691600160401b90041686565b604080516001600160801b039788168152958716602087015293861693850193909352931660608301526001600160401b0392831660808301529190911660a082015260c00162000300565b6200037e603e5481565b620002ef6200114d565b620003ad6200077f36600462002f08565b62001169565b6200045f7f000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd281565b6200045f7f000000000000000000000000dbdb4d16eda451d0503b854cf79d55697f90c8df81565b6200037e603f5481565b6200037e603d5481565b620003ad620011b6565b6200037e603b5481565b6200037e7f000000000000000000000000000000000000000000000000000000000000000981565b6039546200045f906001600160a01b031681565b600080600080620008496200114d565b6001600160a01b03871660009081526041602052604081205492945090925090620008819087906001600160801b03168584620011e0565b905060006200089982670494654067e100006200124f565b6001600160a01b038816600090815260416020526040902054909150620008d190600160801b90046001600160801b031682620030f3565b6001600160a01b038816600090815260416020526040902060019081015462000908918a916001600160801b0316908790620011e0565b9550955050505050915091565b6060603480546200092690620031bf565b80601f01602080910402602001604051908101604052809291908181526020018280546200095490620031bf565b8015620009a55780601f106200097957610100808354040283529160200191620009a5565b820191906000526020600020905b8154815290600101906020018083116200098757829003601f168201915b5050505050905090565b6001600160a01b0381166000908152603860205260409020545b919050565b620009d86200126d565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b3362000a0681620012db565b3362000a1c62000a1633620009af565b6200186c565b62000a2884846200190e565b62000a338162001a0f565b50505050565b3362000a4581620012db565b3362000a51836200186c565b62000a5c8162001a0f565b505050565b3362000a6d81620012db565b3360008062000a7c3362001c3e565b9150915062000a8c82826200190e565b505062000a998162001a0f565b5050565b6033546001600160a01b0316331462000afd5760405162461bcd60e51b815260206004820181905260248201527f43616c6c6572206973206e6f7420726577617264206469737472696275746f7260448201526064015b60405180910390fd5b600062000b0a81620012db565b69d3c21bcecceda1000000821062000b7a5760405162461bcd60e51b815260206004820152602c60248201527f43616e6e6f74206e6f746966792077697468206d6f7265207468616e2061206d60448201526b696c6c696f6e20756e69747360a01b606482015260840162000af4565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000dbdb4d16eda451d0503b854cf79d55697f90c8df6001600160a01b0316906370a082319060240160206040518083038186803b15801562000bdd57600080fd5b505afa15801562000bf2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c18919062003037565b9050801562000c5d5760395462000c5d906001600160a01b037f000000000000000000000000dbdb4d16eda451d0503b854cf79d55697f90c8df811691168362001c8b565b603b544290811062000c935762000c7862093a808562003133565b603c5562000c8a62093a808362003133565b603d5562000d11565b600081603b5462000ca5919062003176565b90506000603c548262000cb9919062003154565b905062093a8062000ccb8288620030f3565b62000cd7919062003133565b603c55603d5460009062000cec908462003154565b905062093a8062000cfe8287620030f3565b62000d0a919062003133565b603d555050505b603e81905562000d2562093a8082620030f3565b603b5560408051858152602081018490527f6c07ee05dcf262f13abf9d87b846ee789d2f90fe991d495acd7d7fc109ee1f55910160405180910390a150505050565b3362000d7381620012db565b3362000a2884846200190e565b6042602052816000526040600020818154811062000d9d57600080fd5b6000918252602090912001546001600160401b038082169350600160401b8204169150600160801b90046001600160801b031683565b600062000e0462000de483620009af565b6001600160a01b0384166000908152603760205260409020549062001cf0565b92915050565b600062000e1a42603b5462001d13565b905090565b600054610100900460ff168062000e355750303b155b8062000e44575060005460ff16155b62000ea95760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b606482015260840162000af4565b600054610100900460ff1615801562000ed5576000805460ff1961ff0019909116610100171660011790555b62000ee086620009d8565b62000f5585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8901819004810282018101909252878152925087915086908190840183828082843760009201919091525062001d2a92505050565b7f000000000000000000000000dbdb4d16eda451d0503b854cf79d55697f90c8df60405162000f849062002e15565b6001600160a01b039091168152602001604051809103906000f08015801562000fb1573d6000803e3d6000fd5b50603980546001600160a01b0319166001600160a01b0392909216919091179055801562000fe5576000805461ff00191690555b505050505050565b60008060008062000ffe8562001c3e565b909350915060006200101286858562001d6e565b509050600080620010238862000839565b9092509050620010348284620030f3565b96508093505050509193509193565b6060603580546200092690620031bf565b336200106081620012db565b3362000a5133846200212a565b816200107981620012db565b8262000a2884846200212a565b336200109281620012db565b33600081815260416020526040902080546001600160801b03808216909255600160801b9004168015620010f657620010f66001600160a01b037f000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd216338362001c8b565b60006200110262002231565b604080518481526020810183905291925033917fd6f2c8500df5b44f11e9e48b91ff9f1b9d81bc496d55570c2b1b75bf65243f51910160405180910390a2505062000a998162001a0f565b6000806000806200115d620022b7565b50909450925050509091565b806200117581620012db565b60405182906001600160a01b038216907fa31b3b303c759fa7ee31d89a1a6fb7eb704d8fe5c87aa4f60f54468ff121bee890600090a262000a5c8162001a0f565b33620011c281620012db565b33620011d262000a1633620009af565b60008062000a7c3362001c3e565b600080620011ef858562003176565b9050806200120257600091505062001247565b60008362001229576001600160a01b03871660009081526037602052604090205462001234565b6200123487620009af565b90506200124281836200124f565b925050505b949350505050565b6000620012668383670de0b6b3a7640000620023c3565b9392505050565b62001277620023de565b6001600160a01b0316336001600160a01b031614620012d95760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920676f7665726e6f722063616e206578656375746500000000000000604482015260640162000af4565b565b426000620012e98262002475565b90506000806000620012fa620022b7565b9250925092506000831180620013105750600082115b156200181d57603f8390556040829055603e8190556001600160a01b0386161562001817576001600160a01b0386166000908152604160209081526040808320815160c08101835281546001600160801b03808216808452600160801b9283900482169684019690965260018401548082169584019590955293049092166060830152600201546001600160401b038082166080840152600160401b9091041660a08201529190620013c69089908784620011e0565b90506000620013e68984604001516001600160801b0316876001620011e0565b90508115620016cd5760006200140583670494654067e100006200124f565b9050600062001415828562003176565b9050604260008c6001600160a01b03166001600160a01b0316815260200190815260200160002060405180606001604052806200146f88608001516001600160401b031662eff100620014699190620030f3565b62002475565b6001600160401b0316815260200162001490620014698e62eff100620030f3565b6001600160401b03168152602001620014cf88608001516001600160401b03168e620014bd919062003176565b620014c9908662003133565b620024df565b6001600160801b0390811690915282546001810184556000938452602093849020835191018054948401516040948501518416600160801b026001600160401b03918216600160401b0267ffffffffffffffff60401b199290941667ffffffffffffffff1990971696909617169190911790911692909217909155805160c08101909152806200155f8a620024df565b6001600160801b031681526020016200158c87602001516001600160801b031685620014c99190620030f3565b6001600160801b03168152602001620015a589620024df565b6001600160801b03168152602001620015be85620024df565b8760600151620015cf9190620030c5565b6001600160801b031681526020018a6001600160401b031681526020018660a001516001620015ff91906200310e565b6001600160401b039081169091526001600160a01b038d1660009081526041602090815260409182902084518154928601516001600160801b03908116600160801b9081029282166001600160801b03199586161782169290921783559386015160018301805460608901518716909302918616929094169190911790931692909217905560808301516002909101805460a0909401518316600160401b0267ffffffffffffffff60401b199290931667ffffffffffffffff19909416939093171617905550620018139050565b6040518060c00160405280620016e388620024df565b6001600160801b0316815260200184602001516001600160801b031681526020016200170f87620024df565b6001600160801b031681526020016200172883620024df565b8560600151620017399190620030c5565b6001600160801b0390811682526001600160401b03808b1660208085019190915260a08089015183166040958601526001600160a01b038f1660009081526041835285902086518154938801518616600160801b9081029187166001600160801b03199586161787169190911782559587015160018201805460608a01518816909802918716979094169690961790941694909417905560808401516002909201805494909301518116600160401b0267ffffffffffffffff60401b199290911667ffffffffffffffff1990941693909317169190911790555b5050505b62000fe5565b6001600160a01b0386161562000fe5576001600160a01b038616600090815260416020526040902060020180546001600160401b03861667ffffffffffffffff19909116179055505050505050565b60008111620018b25760405162461bcd60e51b8152602060048201526011602482015270043616e6e6f74207769746864726177203607c1b604482015260640162000af4565b620018bd8162002546565b80603a6000828254620018d1919062003176565b909155505060405181815233907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d59060200160405180910390a250565b6000806200191e33858562001d6e565b336000908152604360209081526040808320805467ffffffffffffffff19166001600160401b0386161790556041909152812080546001600160801b03808216909255939550919350600160801b90920416906200197d8285620030f3565b90508015620019bc57620019bc6001600160a01b037f000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd216338362001c8b565b6000620019c862002231565b604080518481526020810183905291925033917fd6f2c8500df5b44f11e9e48b91ff9f1b9d81bc496d55570c2b1b75bf65243f51910160405180910390a250505050505050565b6001600160a01b03811660009081526038602090815260408083205460379092528220549091670de0b6b3a7640000908162001a6c7f0000000000000000000000000000000000000000000000000de0b6b3a76400008662003154565b62001a78919062003133565b9050670de0b6b3a7640000811062001b405760405163f8b2cb4f60e01b81526001600160a01b0386811660048301526000917f000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd35929091169063f8b2cb4f90602401602060405180830381600087803b15801562001af357600080fd5b505af115801562001b08573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001b2e919062003037565b905062001b3c828262002621565b9250505b600062001b4e85846200124f565b905083811462000fe557808460365462001b69919062003176565b62001b759190620030f3565b6036556001600160a01b03861660009081526037602052604090208190558381111562001bec576001600160a01b03861660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef62001bd5878562003176565b60405190815260200160405180910390a362000fe5565b60006001600160a01b0387167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef62001c25848862003176565b60405190815260200160405180910390a3505050505050565b6001600160a01b03811660009081526043602052604081205481906001600160401b03168162001c6f82866200272d565b9050600062001c7e8662002845565b9194509092505050915091565b6040516001600160a01b03831660248201526044810182905262000a5c90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915262002958565b60008162001d07670de0b6b3a76400008562003154565b62001266919062003133565b600081831162001d24578262001266565b50919050565b62001d436033805460ff60a01b1916600160a01b179055565b815162001d5890603490602085019062002e23565b50805162000a5c90603590602084019062002e23565b6001600160a01b0383166000908152604360209081526040808320546042909252822054829142916001600160401b03909116908615801562001daf575085155b1562001e255780158062001e0f57506001600160a01b0388166000908152604260205260408120805490919062001df657634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b03168311155b1562001e25576000839450945050505062002122565b861562001ef8576001600160a01b038816600090815260426020526040902062001e5160018962003176565b8154811062001e7057634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b03600160401b9091048116908316101562001ef85760405162461bcd60e51b815260206004820152602e60248201527f496e76616c6964205f6669727374206172673a204d75737420636c61696d206560448201526d61726c69657220656e747269657360901b606482015260840162000af4565b600062001f06888862003176565b62001f13906001620030f3565b905060005b81811015620020b857600062001f2f828b620030f3565b6001600160a01b038c166000908152604260205260408120805492935090918390811062001f6d57634e487b7160e01b600052603260045260246000fd5b60009182526020918290206040805160608101825292909101546001600160401b03808216808552600160401b830490911694840194909452600160801b90046001600160801b0316908201529150871080159062001fe2575080602001516001600160401b0316866001600160401b031611155b620020205760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840cae0dec6d609b1b604482015260640162000af4565b60006200203b82602001516001600160401b03168962001d13565b905060006200206183600001516001600160401b0316896001600160401b031662002a31565b9050600083604001516001600160801b0316828462002081919062003176565b6200208d919062003154565b90506200209b818d620030f3565b9b5050505050508080620020af90620031f6565b91505062001f18565b506001600160a01b038916600090815260426020526040902080546200211b9186918a908110620020f957634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160401b90046001600160401b031662001d13565b9450505050505b935093915050565b600081116200216d5760405162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b604482015260640162000af4565b6001600160a01b038216620021c55760405162461bcd60e51b815260206004820152601b60248201527f496e76616c69642062656e656669636961727920616464726573730000000000604482015260640162000af4565b620021d1828262002a49565b80603a6000828254620021e59190620030f3565b9091555050604080518281523360208201526001600160a01b038416917f9f9e4044c5742cca66ca090b21552bac14645e68bad7a92364a9d9ff18111a1c910160405180910390a25050565b33600090815260416020526040812060010154600160801b90046001600160801b0316801562000e1a5733600081815260416020526040902060010180546001600160801b0316905560395462000e1a916001600160a01b037f000000000000000000000000dbdb4d16eda451d0503b854cf79d55697f90c8df81169216908462002b2f565b600080600080620022c762000e0a565b90506000603e5482620022db919062003176565b905080620022f75750603f5460405490945092509050620023be565b600081603c5462002309919062003154565b9050600082603d546200231d919062003154565b90506200232960365490565b15806200233e5750811580156200233e575080155b156200235b57603f546040548596509650965050505050620023be565b6000620023736200236b60365490565b849062001cf0565b905060006200238e603a548462001cf090919063ffffffff16565b905081603f54620023a09190620030f3565b81604054620023b09190620030f3565b879850985098505050505050505b909192565b600081620023d2848662003154565b62001247919062003133565b60007f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b1580156200243a57600080fd5b505afa1580156200244f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e1a919062002f27565b6000600160401b8210620024db5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b606482015260840162000af4565b5090565b6000600160801b8210620024db5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b606482015260840162000af4565b603354600160a01b900460ff16620025a15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000af4565b6033805460ff60a01b191690553360009081526038602052604081208054839290620025cf90849062003176565b909155506200260b90506001600160a01b037f0000000000000000000000004eaa01974b6594c0ee62ffd7fee56cf11e6af93616338362001c8b565b506033805460ff60a01b1916600160a01b179055565b600081620026395750670de0b6b3a764000062000e04565b6000620026546200264e85620f424062003154565b62002b69565b90506000620026638262002b69565b9050600062002673828462003154565b905080600a7f0000000000000000000000000000000000000000000000000000000000000009620026af88697f0e10af47c1c700000062001d13565b620026bb919062003154565b620026c7919062003133565b620026db90670de0b6b3a764000062003154565b620026e7919062003133565b9350620027236729a2241af62c00006200271d670de0b6b3a76400006200271788670d99a8cec7e20000620030f3565b62002a31565b62001d13565b9695505050505050565b6001600160a01b038116600090815260426020526040812054806200275757600091505062000e04565b6000806200276760018462003176565b905060005b60808110156200283a5781831062002784576200283a565b60006002620027948486620030f3565b620027a1906001620030f3565b620027ad919062003133565b6001600160a01b038816600090815260426020526040902080549192509082908110620027ea57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b039081169089161115620028145780935062002824565b6200282160018262003176565b92505b50806200283181620031f6565b9150506200276c565b509095945050505050565b6001600160a01b038116600090815260426020526040812054806200286f576000915050620009c9565b6000806200287f60018462003176565b905060005b60808110156200294e578183106200289c576200294e565b60006002620028ac8486620030f3565b620028b9906001620030f3565b620028c5919062003133565b6001600160a01b0388166000908152604260205260409020805491925090829081106200290257634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b0316421115620029285780935062002938565b6200293560018262003176565b92505b50806200294581620031f6565b91505062002884565b5090949350505050565b6000620029af826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662002d0d9092919063ffffffff16565b80519091501562000a5c5780806020019051810190620029d0919062002ffc565b62000a5c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000af4565b600081831162002a42578162001266565b5090919050565b603354600160a01b900460ff1662002aa45760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000af4565b6033805460ff60a01b191690556001600160a01b0382166000908152603860205260408120805483929062002adb908490620030f3565b9091555062002b1890506001600160a01b037f0000000000000000000000004eaa01974b6594c0ee62ffd7fee56cf11e6af9361633308462002b2f565b50506033805460ff60a01b1916600160a01b179055565b6040516001600160a01b038085166024830152831660448201526064810182905262000a339085906323b872dd60e01b9060840162001cb8565b60008162002b7a57506000620009c9565b816001600160801b821062002b945760809190911c9060401b5b600160401b821062002bab5760409190911c9060201b5b640100000000821062002bc35760209190911c9060101b5b62010000821062002bd95760109190911c9060081b5b610100821062002bee5760089190911c9060041b5b6010821062002c025760049190911c9060021b5b6008821062002c0f5760011b5b600162002c1d828662003133565b62002c299083620030f3565b901c9050600162002c3b828662003133565b62002c479083620030f3565b901c9050600162002c59828662003133565b62002c659083620030f3565b901c9050600162002c77828662003133565b62002c839083620030f3565b901c9050600162002c95828662003133565b62002ca19083620030f3565b901c9050600162002cb3828662003133565b62002cbf9083620030f3565b901c9050600162002cd1828662003133565b62002cdd9083620030f3565b901c9050600062002cef828662003133565b905080821062002d00578062002d02565b815b9350505050620009c9565b606062001247848460008585843b62002d695760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000af4565b600080866001600160a01b0316858760405162002d87919062003072565b60006040518083038185875af1925050503d806000811462002dc6576040519150601f19603f3d011682016040523d82523d6000602084013e62002dcb565b606091505b5091509150620012428282866060831562002de857508162001266565b82511562002df95782518084602001fd5b8160405162461bcd60e51b815260040162000af4919062003090565b610b69806200324483390190565b82805462002e3190620031bf565b90600052602060002090601f01602090048101928262002e55576000855562002ea0565b82601f1062002e7057805160ff191683800117855562002ea0565b8280016001018555821562002ea0579182015b8281111562002ea057825182559160200191906001019062002e83565b50620024db9291505b80821115620024db576000815560010162002ea9565b60008083601f84011262002ed1578182fd5b5081356001600160401b0381111562002ee8578182fd5b60208301915083602082850101111562002f0157600080fd5b9250929050565b60006020828403121562002f1a578081fd5b813562001266816200322a565b60006020828403121562002f39578081fd5b815162001266816200322a565b60008060008060006060868803121562002f5e578081fd5b853562002f6b816200322a565b945060208601356001600160401b038082111562002f87578283fd5b62002f9589838a0162002ebf565b9096509450604088013591508082111562002fae578283fd5b5062002fbd8882890162002ebf565b969995985093965092949392505050565b6000806040838503121562002fe1578182fd5b823562002fee816200322a565b946020939093013593505050565b6000602082840312156200300e578081fd5b8151801515811462001266578182fd5b60006020828403121562003030578081fd5b5035919050565b60006020828403121562003049578081fd5b5051919050565b6000806040838503121562003063578182fd5b50508035926020909101359150565b600082516200308681846020870162003190565b9190910192915050565b6000602082528251806020840152620030b181604085016020870162003190565b601f01601f19169190910160400192915050565b60006001600160801b03808316818516808303821115620030ea57620030ea62003214565b01949350505050565b6000821982111562003109576200310962003214565b500190565b60006001600160401b03808316818516808303821115620030ea57620030ea62003214565b6000826200314f57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161562003171576200317162003214565b500290565b6000828210156200318b576200318b62003214565b500390565b60005b83811015620031ad57818101518382015260200162003193565b8381111562000a335750506000910152565b600281046001821680620031d457607f821691505b6020821081141562001d2457634e487b7160e01b600052602260045260246000fd5b60006000198214156200320d576200320d62003214565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146200324057600080fd5b5056fe60c06040523480156200001157600080fd5b5060405162000b6938038062000b698339810160408190526200003491620004ad565b33606081811b60a05282901b6001600160601b031916608052620000669082906200006d602090811b6200010617901c565b5062000575565b62000093816000846001600160a01b0316620000be60201b62000135179092919060201c565b620000ba81600019846001600160a01b0316620000be60201b62000135179092919060201c565b5050565b8015806200014c5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156200010f57600080fd5b505afa15801562000124573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200014a9190620004d6565b155b620001c45760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091526200021c9185916200022116565b505050565b60006200027d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620002ff60201b62000285179092919060201c565b8051909150156200021c57808060200190518101906200029e91906200048b565b6200021c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620001bb565b60606200031084846000856200031a565b90505b9392505050565b6060824710156200037d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620001bb565b843b620003cd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001bb565b600080866001600160a01b03168587604051620003eb9190620004ef565b60006040518083038185875af1925050503d80600081146200042a576040519150601f19603f3d011682016040523d82523d6000602084013e6200042f565b606091505b509092509050620004428282866200044d565b979650505050505050565b606083156200045e57508162000313565b8251156200046f5782518084602001fd5b8160405162461bcd60e51b8152600401620001bb91906200050d565b6000602082840312156200049d578081fd5b8151801515811462000313578182fd5b600060208284031215620004bf578081fd5b81516001600160a01b038116811462000313578182fd5b600060208284031215620004e8578081fd5b5051919050565b600082516200050381846020870162000542565b9190910192915050565b60006020825282518060208401526200052e81604085016020870162000542565b601f01601f19169190910160400192915050565b60005b838110156200055f57818101518382015260200162000545565b838111156200056f576000848401525b50505050565b60805160601c60a05160601c6105be620005ab60003960008181604b015260e0015260008181608e015260bf01526105be6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063488a49e314610046578063d1b812cd14610089578063d8245bb9146100b0575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6100b86100ba565b005b6101047f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610106565b565b61011b6001600160a01b038316826000610135565b6101316001600160a01b03831682600019610135565b5050565b8015806101be5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561018457600080fd5b505afa158015610198573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bc91906104f1565b155b61022e5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084015b60405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261028090849061029e565b505050565b60606102948484600085610370565b90505b9392505050565b60006102f3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166102859092919063ffffffff16565b805190915015610280578080602001905181019061031191906104d1565b6102805760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610225565b6060824710156103d15760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610225565b843b61041f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610225565b600080866001600160a01b0316858760405161043b9190610509565b60006040518083038185875af1925050503d8060008114610478576040519150601f19603f3d011682016040523d82523d6000602084013e61047d565b606091505b509150915061048d828286610498565b979650505050505050565b606083156104a7575081610297565b8251156104b75782518084602001fd5b8160405162461bcd60e51b81526004016102259190610525565b6000602082840312156104e2578081fd5b81518015158114610297578182fd5b600060208284031215610502578081fd5b5051919050565b6000825161051b818460208701610558565b9190910192915050565b6000602082528251806020840152610544816040850160208701610558565b601f01601f19169190910160400192915050565b60005b8381101561057357818101518382015260200161055b565b83811115610582576000848401525b5050505056fea26469706673582212208838c99418c2fb1b6066b8d85d9292abc5fd50cb76c79cd3d0b382708da20b6864736f6c63430008020033a2646970667358221220877ea06ffccc72129161deabbdeaf9b4a6bc268366fcadafe70ce7d8c8d8609764736f6c63430008020033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb30000000000000000000000004eaa01974b6594c0ee62ffd7fee56cf11e6af936000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd35920000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000009000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd2000000000000000000000000dbdb4d16eda451d0503b854cf79d55697f90c8df
-----Decoded View---------------
Arg [0] : _nexus (address): 0xAFcE80b19A8cE13DEc0739a1aaB7A028d6845Eb3
Arg [1] : _stakingToken (address): 0x4eaa01974B6594C0Ee62fFd7FEE56CF11E6af936
Arg [2] : _boostDirector (address): 0xBa05FD2f20AE15B0D3f20DDc6870FeCa6ACd3592
Arg [3] : _priceCoeff (uint256): 1000000000000000000
Arg [4] : _boostCoeff (uint256): 9
Arg [5] : _rewardsToken (address): 0xa3BeD4E1c75D00fa6f4E5E6922DB7261B5E9AcD2
Arg [6] : _platformToken (address): 0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
Arg [1] : 0000000000000000000000004eaa01974b6594c0ee62ffd7fee56cf11e6af936
Arg [2] : 000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd3592
Arg [3] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [5] : 000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd2
Arg [6] : 000000000000000000000000dbdb4d16eda451d0503b854cf79d55697f90c8df
Deployed Bytecode Sourcemap
50915:26427:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69377:707;;;;;;:::i;:::-;;:::i;:::-;;;;12557:25:1;;;12613:2;12598:18;;12591:34;;;;12530:18;69377:707:0;;;;;;;;37060:91;;;:::i;:::-;;;;;;;:::i;53096:43::-;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;53096:43:0;;;;;;-1:-1:-1;;;;;13194:31:1;;;13176:50;;13164:2;13149:18;53096:43:0;13131:101:1;37946:118:0;;;;;;:::i;:::-;;:::i;:::-;;;12068:25:1;;;12056:2;12041:18;37946:118:0;12023:76:1;37451:98:0;37522:19;;37451:98;;12491:142;;;;;;:::i;:::-;;:::i;:::-;;52044:40;;52078:6;52044:40;;51914:23;;;;;;61136:246;;;;;;:::i;:::-;;:::i;61525:180::-;;;;;;:::i;:::-;;:::i;37262:84::-;;;37336:2;13795:36:1;;13783:2;13768:18;37262:84:0;13750:87:1;62499:209:0;;;:::i;35981:35::-;;;;;75941:1398;;;;;;:::i;:::-;;:::i;11792:33::-;;;;;-1:-1:-1;;;;;11792:33:0;;;;;;-1:-1:-1;;;;;3546:32:1;;;3528:51;;3516:2;3501:18;11792:33:0;3483:102:1;52273:37:0;;52305:5;52273:37;;63008:208;;;;;;:::i;:::-;;:::i;53042:47::-;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;13490:15:1;;;13472:34;;13542:15;;;;13537:2;13522:18;;13515:43;-1:-1:-1;;;;;13594:47:1;13574:18;;;13567:75;13423:2;13408:18;53042:47:0;13390:258:1;38238:148:0;;;;;;:::i;:::-;;:::i;66152:212::-;66344:12;66152:212;;37690:119;;;;;;:::i;:::-;-1:-1:-1;;;;;37775:26:0;37748:7;37775:26;;;:16;:26;;;;;;;37690:119;35378:36;;;;;52464:25;;;;;;66630:146;;;:::i;52158:41::-;;52191:8;52158:41;;55044:392;;;;;;:::i;:::-;;:::i;70486:537::-;;;;;;:::i;:::-;;:::i;:::-;;;;12867:25:1;;;12923:2;12908:18;;12901:34;;;;12951:18;;;12944:34;13009:2;12994:18;;12987:34;12854:3;12839:19;70486:537:0;12821:206:1;37159:95:0;;;:::i;66426:107::-;66512:13;66426:107;;8887:29;;;;;59802:186;;;;;;:::i;:::-;;:::i;60214:214::-;;;;;;:::i;:::-;;:::i;35421:45::-;;;;;61857:429;;;:::i;52898:43::-;;;;;;52950:44;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;52950:44:0;;;;-1:-1:-1;;;52950:44:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;52950:44:0;;;;-1:-1:-1;;;52950:44:0;;;;;;;;;-1:-1:-1;;;;;11596:15:1;;;11578:34;;11648:15;;;11643:2;11628:18;;11621:43;11700:15;;;11680:18;;;11673:43;;;;11752:15;;11747:2;11732:18;;11725:43;-1:-1:-1;;;;;11842:15:1;;;11836:3;11821:19;;11814:44;11895:15;;;;11889:3;11874:19;;11867:44;11512:3;11497:19;52950:44:0;11479:438:1;52649:29:0;;;;;;67002:233;;;:::i;63296:180::-;;;;;;:::i;:::-;;:::i;51608:36::-;;;;;51725:37;;;;;52767:35;;;;;;52561:33;;;;;;60660:245;;;:::i;52373:27::-;;;;;;35923:35;;;;;51826:46;;;;;-1:-1:-1;;;;;51826:46:0;;;69377:707;69441:7;69450;69471:23;69496:31;69531:16;:14;:16::i;:::-;-1:-1:-1;;;;;69623:18:0;;69558:17;69623:18;;;:8;:18;;;;;:37;69470:77;;-1:-1:-1;69470:77:0;;-1:-1:-1;69558:17:0;69578:143;;69600:8;;-1:-1:-1;;;;;69623:37:0;69470:77;69558:17;69578:7;:143::i;:::-;69558:163;-1:-1:-1;69732:27:0;69762:29;69558:163;52305:5;69762:21;:29::i;:::-;-1:-1:-1;;;;;69846:18:0;;;;;;:8;:18;;;;;:26;69732:59;;-1:-1:-1;69824:48:0;;-1:-1:-1;;;69846:26:0;;-1:-1:-1;;;;;69846:26:0;69732:59;69824:48;:::i;:::-;-1:-1:-1;;;;;69940:18:0;;;;;;:8;:18;;;;;:45;;;;;69887:178;;69913:8;;-1:-1:-1;;;;;69940:45:0;;70004:23;;69887:7;:178::i;:::-;69802:274;;;;;;;;69377:707;;;:::o;37060:91::-;37105:13;37138:5;37131:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37060:91;:::o;37946:118::-;-1:-1:-1;;;;;38034:22:0;;38007:7;38034:22;;;:12;:22;;;;;;37946:118;;;;:::o;12491:142::-;9321:15;:13;:15::i;:::-;12585:18:::1;:40:::0;;-1:-1:-1;;;;;;12585:40:0::1;-1:-1:-1::0;;;;;12585:40:0;;;::::1;::::0;;;::::1;::::0;;12491:142::o;61136:246::-;61239:10;55913:23;55927:8;55913:13;:23::i;:::-;61272:10:::1;61300:35:::2;61310:24;61323:10;61310:12;:24::i;:::-;61300:9;:35::i;:::-;61346:28;61360:6;61368:5;61346:13;:28::i;:::-;59503:19:::1;59513:8;59503:9;:19::i;:::-;55947:1;61136:246:::0;;;:::o;61525:180::-;61618:10;55913:23;55927:8;55913:13;:23::i;:::-;61651:10:::1;61679:18:::2;61689:7;61679:9;:18::i;:::-;59503:19:::1;59513:8;59503:9;:19::i;:::-;55947:1;61525:180:::0;;:::o;62499:209::-;62554:10;55913:23;55927:8;55913:13;:23::i;:::-;62578:10:::1;62602:13:::2;62617:12:::0;62633:28:::2;62650:10;62633:16;:28::i;:::-;62601:60;;;;62674:26;62688:5;62695:4;62674:13;:26::i;:::-;59491:1;;59503:19:::1;59513:8;59503:9;:19::i;:::-;55947:1;62499:209:::0;:::o;75941:1398::-;12245:18;;-1:-1:-1;;;;;12245:18:0;12231:10;:32;12223:77;;;;-1:-1:-1;;;12223:77:0;;6860:2:1;12223:77:0;;;6842:21:1;;;6879:18;;;6872:30;6938:34;6918:18;;;6911:62;6990:18;;12223:77:0;;;;;;;;;76151:1:::1;55913:23;55927:8;55913:13;:23::i;:::-;76189:4:::2;76179:7;:14;76171:71;;;::::0;-1:-1:-1;;;76171:71:0;;6104:2:1;76171:71:0::2;::::0;::::2;6086:21:1::0;6143:2;6123:18;;;6116:30;6182:34;6162:18;;;6155:62;-1:-1:-1;;;6233:18:1;;;6226:42;6285:19;;76171:71:0::2;6076:234:1::0;76171:71:0::2;76284:38;::::0;-1:-1:-1;;;76284:38:0;;76316:4:::2;76284:38;::::0;::::2;3528:51:1::0;76255:26:0::2;::::0;76284:13:::2;-1:-1:-1::0;;;;;76284:23:0::2;::::0;::::2;::::0;3501:18:1;;76284:38:0::2;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76255:67:::0;-1:-1:-1;76337:22:0;;76333:131:::2;;76411:19;::::0;76376:76:::2;::::0;-1:-1:-1;;;;;76376:13:0::2;:26:::0;::::2;::::0;76411:19:::2;76433:18:::0;76376:26:::2;:76::i;:::-;76597:12;::::0;76498:15:::2;::::0;76582:27;::::2;76578:607;;76639:18;52078:6;76639:7:::0;:18:::2;:::i;:::-;76626:10;:31:::0;76693:29:::2;52078:6;76693:18:::0;:29:::2;:::i;:::-;76672:18;:50:::0;76578:607:::2;;;76826:17;76861:11;76846:12;;:26;;;;:::i;:::-;76826:46;;76889:22;76926:10;;76914:9;:22;;;;:::i;:::-;76889:47:::0;-1:-1:-1;52078:6:0::2;76965:24;76889:47:::0;76965:7;:24:::2;:::i;:::-;76964:37;;;;:::i;:::-;76951:10;:50:::0;77063:18:::2;::::0;77018:30:::2;::::0;77051::::2;::::0;:9;:30:::2;:::i;:::-;77018:63:::0;-1:-1:-1;52078:6:0::2;77118:43;77018:63:::0;77118:18;:43:::2;:::i;:::-;77117:56;;;;:::i;:::-;77096:18;:77:::0;-1:-1:-1;;;76578:607:0::2;77197:14;:28:::0;;;77251:22:::2;52078:6;77214:11:::0;77251:22:::2;:::i;:::-;77236:12;:37:::0;77291:40:::2;::::0;;12557:25:1;;;12613:2;12598:18;;12591:34;;;77291:40:0::2;::::0;12530:18:1;77291:40:0::2;;;;;;;55947:1;;12311::::1;75941:1398:::0;:::o;63008:208::-;63119:10;55913:23;55927:8;55913:13;:23::i;:::-;63152:10:::1;63180:28:::2;63194:6;63202:5;63180:13;:28::i;53042:47::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;53042:47:0;;;;-1:-1:-1;;;;53042:47:0;;;;-1:-1:-1;;;;53042:47:0;;-1:-1:-1;;;;;53042:47:0;;:::o;38238:148::-;38295:7;38322:56;38355:22;38368:8;38355:12;:22::i;:::-;-1:-1:-1;;;;;37775:26:0;;37748:7;37775:26;;;:16;:26;;;;;;38322:32;;:56::i;:::-;38315:63;38238:148;-1:-1:-1;;38238:148:0:o;66630:146::-;66696:7;66723:45;66738:15;66755:12;;66723:14;:45::i;:::-;66716:52;;66630:146;:::o;55044:392::-;43150:12;;;;;;;;:31;;-1:-1:-1;44063:4:0;44130:17;44175:7;43166:15;43150:47;;;-1:-1:-1;43186:11:0;;;;43185:12;43150:47;43128:143;;;;-1:-1:-1;;;43128:143:0;;9558:2:1;43128:143:0;;;9540:21:1;9597:2;9577:18;;;9570:30;9636:34;9616:18;;;9609:62;-1:-1:-1;;;9687:18:1;;;9680:44;9741:19;;43128:143:0;9530:236:1;43128:143:0;43284:19;43307:12;;;;;;43306:13;43330:99;;;;43365:12;:19;;-1:-1:-1;;;;43365:19:0;;;;;43399:18;43380:4;43399:18;;;43330:99;55216:77:::1;55270:22;55216:53;:77::i;:::-;55304:53;55336:8;;55304:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;55304:53:0::1;::::0;;::::1;;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;-1:-1:-1;55346:10:0;;-1:-1:-1;55346:10:0;;;;55304:53;::::1;55346:10:::0;;;;55304:53;::::1;;::::0;::::1;::::0;;;;-1:-1:-1;55304:31:0::1;::::0;-1:-1:-1;;;55304:53:0:i:1;:::-;55414:13;55390:38;;;;;:::i;:::-;-1:-1:-1::0;;;;;3546:32:1;;;3528:51;;3516:2;3501:18;55390:38:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;55368:19:0::1;:60:::0;;-1:-1:-1;;;;;;55368:60:0::1;-1:-1:-1::0;;;;;55368:60:0;;;::::1;::::0;;;::::1;::::0;;43455:67;;;;43505:5;43490:20;;-1:-1:-1;;43490:20:0;;;43455:67;55044:392;;;;;;:::o;70486:537::-;70612:14;70641:13;70669:12;70696:22;70762:26;70779:8;70762:16;:26::i;:::-;70746:42;;-1:-1:-1;70746:42:0;-1:-1:-1;70800:16:0;70822:40;70840:8;70746:42;;70822:17;:40::i;:::-;70799:63;;;70874:15;70891:23;70918:16;70925:8;70918:6;:16::i;:::-;70873:61;;-1:-1:-1;70873:61:0;-1:-1:-1;70954:18:0;70873:61;70954:8;:18;:::i;:::-;70945:27;;71000:15;70983:32;;70486:537;;;;;;;;:::o;37159:95::-;37206:13;37239:7;37232:14;;;;;:::i;59802:186::-;59892:10;55913:23;55927:8;55913:13;:23::i;:::-;59925:10:::1;59953:27:::2;59960:10;59972:7;59953:6;:27::i;60214:214::-:0;60326:12;55913:23;55927:8;55913:13;:23::i;:::-;60361:12:::1;60391:29:::2;60398:12;60412:7;60391:6;:29::i;61857:429::-:0;61911:10;55913:23;55927:8;55913:13;:23::i;:::-;61935:10:::1;61958:16:::2;61977:20:::0;;;:8:::2;:20;::::0;;;;:28;;-1:-1:-1;;;;;62016:32:0;;::::2;::::0;;;-1:-1:-1;;;61977:28:0;::::2;;62065:12:::0;;62061:92:::2;;62094:47;-1:-1:-1::0;;;;;62094:12:0::2;:25;62120:10;62132:8:::0;62094:25:::2;:47::i;:::-;62165:22;62190;:20;:22::i;:::-;62230:48;::::0;;12557:25:1;;;12613:2;12598:18;;12591:34;;;62165:47:0;;-1:-1:-1;62241:10:0::2;::::0;62230:48:::2;::::0;12530:18:1;62230:48:0::2;;;;;;;59491:1;;59503:19:::1;59513:8;59503:9;:19::i;67002:233::-:0;67058:7;67067;67088:23;67113:31;67150:17;:15;:17::i;:::-;-1:-1:-1;67087:80:0;;-1:-1:-1;67087:80:0;-1:-1:-1;;;67002:233:0;;:::o;63296:180::-;63391:8;55913:23;55927:8;55913:13;:23::i;:::-;63453:15:::2;::::0;63422:8;;-1:-1:-1;;;;;63453:15:0;::::2;::::0;::::2;::::0;;;::::2;59503:19:::1;59513:8;59503:9;:19::i;60660:245::-:0;60707:10;55913:23;55927:8;55913:13;:23::i;:::-;60731:10:::1;60754:35:::2;60764:24;60777:10;60764:12;:24::i;60754:35::-;60801:13;60816:12:::0;60832:28:::2;60849:10;60832:16;:28::i;71094:687::-:0;71281:7;;71394:48;71419:23;71394:22;:48;:::i;:::-;71368:74;-1:-1:-1;71521:20:0;71517:61;;71565:1;71558:8;;;;;71517:61;71648:11;71662:14;:61;;-1:-1:-1;;;;;37775:26:0;;37748:7;37775:26;;;:16;:26;;;;;;71662:61;;;71679:22;71692:8;71679:12;:22::i;:::-;71648:75;-1:-1:-1;71741:32:0;71648:75;71757:15;71741;:32::i;:::-;71734:39;;;;71094:687;;;;;;;:::o;28117:135::-;28183:7;28210:34;28227:1;28230;26491:4;28210:16;:34::i;:::-;28203:41;28117:135;-1:-1:-1;;;28117:135:0:o;9364:121::-;9436:11;:9;:11::i;:::-;-1:-1:-1;;;;;9422:25:0;:10;-1:-1:-1;;;;;9422:25:0;;9414:63;;;;-1:-1:-1;;;9414:63:0;;8451:2:1;9414:63:0;;;8433:21:1;8490:2;8470:18;;;8463:30;8529:27;8509:18;;;8502:55;8574:18;;9414:63:0;8423:175:1;9414:63:0;9364:121::o;55964:3369::-;56047:15;56025:19;56096:30;56047:15;56096:17;:30::i;:::-;56073:53;;56189:25;56229:33;56277:26;56317:17;:15;:17::i;:::-;56174:160;;;;;;56439:1;56419:17;:21;:54;;;;56472:1;56444:25;:29;56419:54;56415:2911;;;56490:20;:40;;;56545:28;:56;;;56616:14;:35;;;-1:-1:-1;;;;;56734:22:0;;;56730:2393;;-1:-1:-1;;;;;56800:18:0;;56777:20;56800:18;;;:8;:18;;;;;;;;56777:41;;;;;;;;;-1:-1:-1;;;;;56777:41:0;;;;;;-1:-1:-1;;;56777:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;56777:41:0;;;;;;;-1:-1:-1;;;56777:41:0;;;;;;;;;:20;56855:171;;56809:8;;56962:17;56777:20;56855:7;:171::i;:::-;56837:189;;57045:23;57071:186;57101:8;57132:4;:31;;;-1:-1:-1;;;;;57071:186:0;57186:25;57234:4;57071:7;:186::i;:::-;57045:212;-1:-1:-1;57455:11:0;;57451:1657;;57491:16;57510:27;:7;52305:5;57510:19;:27::i;:::-;57491:46;-1:-1:-1;57560:14:0;57577:18;57491:46;57577:7;:18;:::i;:::-;57560:35;;57620:11;:21;57632:8;-1:-1:-1;;;;;57620:21:0;-1:-1:-1;;;;;57620:21:0;;;;;;;;;;;;57673:291;;;;;;;;57718:43;57745:4;:15;;;-1:-1:-1;;;;;57736:24:0;52191:8;57736:24;;;;:::i;:::-;57718:17;:43::i;:::-;-1:-1:-1;;;;;57673:291:0;;;;;57800:39;57818:20;57827:11;52191:8;57818:20;:::i;57800:39::-;-1:-1:-1;;;;;57673:291:0;;;;;57876:60;57919:4;:15;;;-1:-1:-1;;;;;57905:29:0;:11;:29;;;;:::i;:::-;57895:40;;:6;:40;:::i;:::-;57876:18;:60::i;:::-;-1:-1:-1;;;;;57673:291:0;;;;;;57620:367;;;;;;;-1:-1:-1;57620:367:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57620:367:0;-1:-1:-1;;;;;57620:367:0;;;-1:-1:-1;;;57620:367:0;-1:-1:-1;;;;57620:367:0;;;;-1:-1:-1;;57620:367:0;;;;;;;;;;;;;;;;;;;;;;58033:510;;;;;;;;;58089:37;58108:17;58089:18;:37::i;:::-;-1:-1:-1;;;;;58033:510:0;;;;;58162:43;58192:4;:12;;;-1:-1:-1;;;;;58181:23:0;:8;:23;;;;:::i;58162:43::-;-1:-1:-1;;;;;58033:510:0;;;;;58260:45;58279:25;58260:18;:45::i;:::-;-1:-1:-1;;;;;58033:510:0;;;;;58372:35;58391:15;58372:18;:35::i;:::-;58349:4;:20;;;:58;;;;:::i;:::-;-1:-1:-1;;;;;58033:510:0;;;;;58446:13;-1:-1:-1;;;;;58033:510:0;;;;;58499:4;:16;;;58518:1;58499:20;;;;:::i;:::-;-1:-1:-1;;;;;58033:510:0;;;;;;-1:-1:-1;;;;;58012:18:0;;;;;;:8;:18;;;;;;;;;:531;;;;;;;;-1:-1:-1;;;;;58012:531:0;;;-1:-1:-1;;;58012:531:0;;;;;;-1:-1:-1;;;;;;58012:531:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;58012:531:0;-1:-1:-1;;;;58012:531:0;;;;-1:-1:-1;;58012:531:0;;;;;;;;;;;-1:-1:-1;57451:1657:0;;-1:-1:-1;57451:1657:0;;58613:475;;;;;;;;58669:37;58688:17;58669:18;:37::i;:::-;-1:-1:-1;;;;;58613:475:0;;;;;58742:4;:12;;;-1:-1:-1;;;;;58613:475:0;;;;;58809:45;58828:25;58809:18;:45::i;:::-;-1:-1:-1;;;;;58613:475:0;;;;;58921:35;58940:15;58921:18;:35::i;:::-;58898:4;:20;;;:58;;;;:::i;:::-;-1:-1:-1;;;;;58613:475:0;;;;;-1:-1:-1;;;;;58613:475:0;;;;;;;;;;;59048:16;;;;;58613:475;;;;;;;-1:-1:-1;;;;;58592:18:0;;-1:-1:-1;58592:18:0;;;:8;:18;;;;;:496;;;;;;;;;;-1:-1:-1;;;58592:496:0;;;;;;-1:-1:-1;;;;;;58592:496:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;58592:496:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;58592:496:0;-1:-1:-1;;;;58592:496:0;;;;-1:-1:-1;;58592:496:0;;;;;;;;;;;;;;57451:1657;56730:2393;;;;56415:2911;;;-1:-1:-1;;;;;59144:22:0;;;59140:186;;-1:-1:-1;;;;;59269:18:0;;;;;;:8;:18;;;;;:29;;:45;;-1:-1:-1;;;;;59269:45:0;;-1:-1:-1;;59269:45:0;;;;;;55964:3369;;;;;;:::o;65754:213::-;65828:1;65818:7;:11;65810:41;;;;-1:-1:-1;;;65810:41:0;;8805:2:1;65810:41:0;;;8787:21:1;8844:2;8824:18;;;8817:30;-1:-1:-1;;;8863:18:1;;;8856:47;8920:18;;65810:41:0;8777:167:1;65810:41:0;65862:21;65875:7;65862:12;:21::i;:::-;65906:7;65894:8;;:19;;;;;;;:::i;:::-;;;;-1:-1:-1;;65929:30:0;;12068:25:1;;;65939:10:0;;65929:30;;12056:2:1;12041:18;65929:30:0;;;;;;;65754:213;:::o;63907:600::-;63982:17;64001:21;64026:44;64044:10;64056:6;64064:5;64026:17;:44::i;:::-;64091:10;64081:21;;;;:9;:21;;;;;;;;:45;;-1:-1:-1;;64081:45:0;-1:-1:-1;;;;;64081:45:0;;;;;64158:8;:20;;;;;:28;;-1:-1:-1;;;;;64197:32:0;;;;;;63981:89;;-1:-1:-1;64081:45:0;;-1:-1:-1;;;;64158:28:0;;;;;64258:20;64158:28;63981:89;64258:20;:::i;:::-;64242:36;-1:-1:-1;64295:9:0;;64291:86;;64321:44;-1:-1:-1;;;;;64321:12:0;:25;64347:10;64359:5;64321:25;:44::i;:::-;64389:22;64414;:20;:22::i;:::-;64454:45;;;12557:25:1;;;12613:2;12598:18;;12591:34;;;64389:47:0;;-1:-1:-1;64465:10:0;;64454:45;;12530:18:1;64454:45:0;;;;;;;63907:600;;;;;;;:::o;39308:1132::-;-1:-1:-1;;;;;39386:22:0;;39365:18;39386:22;;;:12;:22;;;;;;;;;39444:16;:26;;;;;;39386:22;;35867:4;;;39645:23;39658:10;39386:22;39645:23;:::i;:::-;39644:32;;;;:::i;:::-;39620:56;;35719:4;39691:13;:28;39687:183;;39759:34;;-1:-1:-1;;;39759:34:0;;-1:-1:-1;;;;;3546:32:1;;;39759:34:0;;;3528:51:1;39736:20:0;;39759:13;:24;;;;;;3501:18:1;;39759:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39736:57;;39816:42;39830:13;39845:12;39816:13;:42::i;:::-;39808:50;;39687:183;;39882:25;39910:29;:10;39933:5;39910:22;:29::i;:::-;39882:57;;39977:14;39956:17;:35;39952:481;;40069:17;40052:14;40030:19;;:36;;;;:::i;:::-;:56;;;;:::i;:::-;40008:19;:78;-1:-1:-1;;;;;40101:26:0;;;;;;:16;:26;;;;;:46;;;40168:34;;;40164:258;;;-1:-1:-1;;;;;40228:66:0;;40245:1;40228:66;40259:34;40279:14;40259:17;:34;:::i;:::-;40228:66;;12068:25:1;;;12056:2;12041:18;40228:66:0;;;;;;;40164:258;;;40367:1;-1:-1:-1;;;;;40340:66:0;;;40371:34;40388:17;40371:14;:34;:::i;:::-;40340:66;;12068:25:1;;;12056:2;12041:18;40340:66:0;;;;;;;39308:1132;;;;;;:::o;71899:377::-;-1:-1:-1;;;;;72057:19:0;;71993:13;72057:19;;;:9;:19;;;;;;71993:13;;-1:-1:-1;;;;;72057:19:0;71993:13;72114:40;72057:19;72067:8;72114:19;:40::i;:::-;72089:65;;72165:21;72189:28;72208:8;72189:18;:28::i;:::-;72238:14;;-1:-1:-1;72165:52:0;;-1:-1:-1;;;71899:377:0;;;:::o;21308:211::-;21452:58;;-1:-1:-1;;;;;4162:32:1;;21452:58:0;;;4144:51:1;4211:18;;;4204:34;;;21425:86:0;;21445:5;;-1:-1:-1;;;21475:23:0;4117:18:1;;21452:58:0;;;;-1:-1:-1;;21452:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;21452:58:0;-1:-1:-1;;;;;;21452:58:0;;;;;;;;;;21425:19;:86::i;30247:195::-;30314:7;30433:1;30415:14;26491:4;30415:1;:14;:::i;:::-;30414:20;;;;:::i;32869:106::-;32927:7;32958:1;32954;:5;:13;;32966:1;32954:13;;;-1:-1:-1;32962:1:0;32869:106;-1:-1:-1;32869:106:0:o;36867:185::-;36958:28;25430:11;:18;;-1:-1:-1;;;;25430:18:0;-1:-1:-1;;;25430:18:0;;;24954:502;36958:28;36997:16;;;;:5;;:16;;;;;:::i;:::-;-1:-1:-1;37024:20:0;;;;:7;;:20;;;;;:::i;72362:1661::-;-1:-1:-1;;;;;72614:19:0;;72495:14;72614:19;;;:9;:19;;;;;;;;;72707:11;:21;;;;;:28;72495:14;;72569:15;;-1:-1:-1;;;;;72614:19:0;;;;72750:11;;:25;;;;-1:-1:-1;72765:10:0;;72750:25;72746:183;;;72796:13;;;:62;;-1:-1:-1;;;;;;72828:21:0;;;;;;:11;:21;;;;;:24;;:21;;;:24;;-1:-1:-1;;;72828:24:0;;;;;;;;;;;;;;;;;;:30;-1:-1:-1;;;;;72828:30:0;72813:45;;;72796:62;72792:126;;;72887:1;72890:11;72879:23;;;;;;;;;72792:126;73037:10;;73033:204;;-1:-1:-1;;;;;73103:21:0;;;;;;:11;:21;;;;;73125:10;73134:1;73125:6;:10;:::i;:::-;73103:33;;;;;;-1:-1:-1;;;73103:33:0;;;;;;;;;;;;;;;;;;:40;-1:-1:-1;;;;;;;;73103:40:0;;;;;73090:53;;;;;73064:161;;;;-1:-1:-1;;;73064:161:0;;7221:2:1;73064:161:0;;;7203:21:1;7260:2;7240:18;;;7233:30;7299:34;7279:18;;;7272:62;-1:-1:-1;;;7350:18:1;;;7343:44;7404:19;;73064:161:0;7193:236:1;73064:161:0;73249:13;73265:14;73273:6;73265:5;:14;:::i;:::-;:18;;73282:1;73265:18;:::i;:::-;73249:34;;73299:9;73294:488;73318:5;73314:1;:9;73294:488;;;73345:10;73358;73367:1;73358:6;:10;:::i;:::-;-1:-1:-1;;;;;73403:21:0;;73383:17;73403:21;;;:11;:21;;;;;:25;;73345:23;;-1:-1:-1;73383:17:0;;73345:23;;73403:25;;;;-1:-1:-1;;;73403:25:0;;;;;;;;;;;;;;;;;;73383:45;;;;;;;;73403:25;;;;73383:45;-1:-1:-1;;;;;73383:45:0;;;;;;-1:-1:-1;;;73383:45:0;;;;;;;;;;;;-1:-1:-1;;;73383:45:0;;-1:-1:-1;;;;;73383:45:0;;;;;;-1:-1:-1;73453:24:0;;;;;:51;;;73494:3;:10;;;-1:-1:-1;;;;;73481:23:0;:9;-1:-1:-1;;;;;73481:23:0;;;73453:51;73445:77;;;;-1:-1:-1;;;73445:77:0;;10331:2:1;73445:77:0;;;10313:21:1;10370:2;10350:18;;;10343:30;-1:-1:-1;;;10389:18:1;;;10382:43;10442:18;;73445:77:0;10303:163:1;73445:77:0;73539:15;73557:39;73572:3;:10;;;-1:-1:-1;;;;;73557:39:0;73584:11;73557:14;:39::i;:::-;73539:57;;73611:17;73631:36;73646:3;:9;;;-1:-1:-1;;;;;73631:36:0;73657:9;-1:-1:-1;;;;;73631:36:0;:14;:36::i;:::-;73611:56;;73682:17;73726:3;:8;;;-1:-1:-1;;;;;73702:32:0;73713:9;73703:7;:19;;;;:::i;:::-;73702:32;;;;:::i;:::-;73682:52;-1:-1:-1;73751:19:0;73682:52;73751:19;;:::i;:::-;;;73294:488;;;;;73325:3;;;;;:::i;:::-;;;;73294:488;;;-1:-1:-1;;;;;;73979:21:0;;;;;;:11;:21;;;;;:28;;73951:64;;73966:11;;74001:5;;73979:28;;;;-1:-1:-1;;;73979:28:0;;;;;;;;;;;;;;;;;;:35;-1:-1:-1;;;73979:35:0;;-1:-1:-1;;;;;73979:35:0;73951:14;:64::i;:::-;73933:82;;72362:1661;;;;;;;;;;;:::o;65299:330::-;65392:1;65382:7;:11;65374:38;;;;-1:-1:-1;;;65374:38:0;;6517:2:1;65374:38:0;;;6499:21:1;6556:2;6536:18;;;6529:30;-1:-1:-1;;;6575:18:1;;;6568:44;6629:18;;65374:38:0;6489:164:1;65374:38:0;-1:-1:-1;;;;;65431:26:0;;65423:66;;;;-1:-1:-1;;;65423:66:0;;5748:2:1;65423:66:0;;;5730:21:1;5787:2;5767:18;;;5760:30;5826:29;5806:18;;;5799:57;5873:18;;65423:66:0;5720:177:1;65423:66:0;65502:32;65512:12;65526:7;65502:9;:32::i;:::-;65557:7;65545:8;;:19;;;;;;;:::i;:::-;;;;-1:-1:-1;;65580:41:0;;;12278:25:1;;;65610:10:0;12334:2:1;12319:18;;12312:60;-1:-1:-1;;;;;65580:41:0;;;;;12251:18:1;65580:41:0;;;;;;;65299:330;;:::o;64592:441::-;64696:10;64642:7;64687:20;;;:8;:20;;;;;:36;;;-1:-1:-1;;;64687:36:0;;-1:-1:-1;;;;;64687:36:0;64738:18;;64734:260;;64782:10;64812:1;64773:20;;;:8;:20;;;;;:36;;:40;;-1:-1:-1;;;;;64773:40:0;;;64885:19;;64828:154;;-1:-1:-1;;;;;64828:13:0;:30;;;64885:19;;64953:14;64828:30;:154::i;67243:1812::-;67334:23;67372:31;67418:33;67479:26;67508;:24;:26::i;:::-;67479:55;;67558:17;67599:14;;67578:18;:35;;;;:::i;:::-;67558:55;-1:-1:-1;67729:14:0;67725:126;;-1:-1:-1;67768:20:0;;67790:28;;67768:20;;-1:-1:-1;67790:28:0;-1:-1:-1;67820:18:0;-1:-1:-1;67760:79:0;;67725:126;67939:31;67986:9;67973:10;;:22;;;;:::i;:::-;67939:56;;68019:39;68082:9;68061:18;;:30;;;;:::i;:::-;68019:72;;68258:13;37522:19;;37451:98;;68258:13;:18;;:105;;-1:-1:-1;68294:28:0;;:68;;;;-1:-1:-1;68326:36:0;;68294:68;68240:241;;;68398:20;;68420:28;;68450:18;68390:79;;;;;;;;;;;;68240:241;68579:33;68615:51;68652:13;37522:19;;37451:98;;68652:13;68615:23;;:36;:51::i;:::-;68579:87;;68677:41;68721:78;68780:8;;68721:31;:44;;:78;;;;:::i;:::-;68677:122;;68886:25;68863:20;;:48;;;;:::i;:::-;68957:33;68926:28;;:64;;;;:::i;:::-;69005:18;68841:193;;;;;;;;;;;;67243:1812;;;;:::o;28725:286::-;28845:7;28998:5;28989;28993:1;28989;:5;:::i;:::-;28988:15;;;;:::i;9971:95::-;10015:7;10042:5;-1:-1:-1;;;;;10042:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;45110:178::-;45166:6;-1:-1:-1;;;45193:5:0;:13;45185:64;;;;-1:-1:-1;;;45185:64:0;;9151:2:1;45185:64:0;;;9133:21:1;9190:2;9170:18;;;9163:30;9229:34;9209:18;;;9202:62;-1:-1:-1;;;9280:18:1;;;9273:36;9326:19;;45185:64:0;9123:228:1;45185:64:0;-1:-1:-1;45274:5:0;45110:178::o;44628:183::-;44685:7;-1:-1:-1;;;44713:5:0;:14;44705:66;;;;-1:-1:-1;;;44705:66:0;;7636:2:1;44705:66:0;;;7618:21:1;7675:2;7655:18;;;7648:30;7714:34;7694:18;;;7687:62;-1:-1:-1;;;7765:18:1;;;7758:37;7812:19;;44705:66:0;7608:229:1;38854:172:0;25955:11;;-1:-1:-1;;;25955:11:0;;;;25947:55;;;;-1:-1:-1;;;25947:55:0;;11084:2:1;25947:55:0;;;11066:21:1;11123:2;11103:18;;;11096:30;11162:33;11142:18;;;11135:61;11213:18;;25947:55:0;11056:181:1;25947:55:0;26080:11;:19;;-1:-1:-1;;;;26080:19:0;;;38939:10:::1;26094:5:::0;38926:24;;;:12:::1;:24;::::0;;;;:35;;38954:7;;26094:5;38926:35:::1;::::0;38954:7;;38926:35:::1;:::i;:::-;::::0;;;-1:-1:-1;38972:46:0::1;::::0;-1:-1:-1;;;;;;38972:12:0::1;:25;38998:10;39010:7:::0;38972:25:::1;:46::i;:::-;-1:-1:-1::0;26260:11:0;:18;;-1:-1:-1;;;;26260:18:0;-1:-1:-1;;;26260:18:0;;;38854:172::o;40644:607::-;40763:13;40798:18;40794:40;;-1:-1:-1;35867:4:0;40818:16;;40794:40;40892:13;40908:31;40918:20;:14;40935:3;40918:20;:::i;:::-;40908:9;:31::i;:::-;40892:47;;40950:13;40966:16;40976:5;40966:9;:16::i;:::-;40950:32;-1:-1:-1;40993:19:0;41015:13;40950:32;41015:5;:13;:::i;:::-;40993:35;;41146:11;41119:2;41105:10;41063:39;41078:13;35766:9;41063:14;:39::i;:::-;:52;;;;:::i;:::-;41062:59;;;;:::i;:::-;41061:68;;41125:4;41061:68;:::i;:::-;41060:97;;;;:::i;:::-;41039:118;-1:-1:-1;41176:67:0;35819:4;41202:40;35867:4;41228:13;41039:118;35911:5;41228:13;:::i;:::-;41202:14;:40::i;:::-;41176:14;:67::i;:::-;41168:75;40644:607;-1:-1:-1;;;;;;40644:607:0:o;74130:692::-;-1:-1:-1;;;;;74291:21:0;;74246:13;74291:21;;;:11;:21;;;;;:28;74334:8;74330:22;;74351:1;74344:8;;;;;74330:22;74389:11;;74429:7;74435:1;74429:3;:7;:::i;:::-;74415:21;;74506:9;74501:293;74525:3;74521:1;:7;74501:293;;;74561:3;74554;:10;74550:21;;74566:5;;74550:21;74586:11;74618:1;74601:9;74607:3;74601;:9;:::i;:::-;:13;;74613:1;74601:13;:::i;:::-;74600:19;;;;:::i;:::-;-1:-1:-1;;;;;74651:21:0;;;;;;:11;:21;;;;;:26;;74586:33;;-1:-1:-1;74651:21:0;74586:33;;74651:26;;;;-1:-1:-1;;;74651:26:0;;;;;;;;;;;;;;;;;;:32;-1:-1:-1;;;;;74651:32:0;;;74638:45;;;;74634:149;;;74710:3;74704:9;;74634:149;;;74760:7;74766:1;74760:3;:7;:::i;:::-;74754:13;;74634:149;-1:-1:-1;74530:3:0;;;;:::i;:::-;;;;74501:293;;;-1:-1:-1;74811:3:0;;74130:692;-1:-1:-1;;;;;74130:692:0:o;74929:645::-;-1:-1:-1;;;;;75038:21:0;;74998:13;75038:21;;;:11;:21;;;;;:28;75081:8;75077:22;;75098:1;75091:8;;;;;75077:22;75136:11;;75176:7;75182:1;75176:3;:7;:::i;:::-;75162:21;;75253:9;75248:298;75272:3;75268:1;:7;75248:298;;;75308:3;75301;:10;75297:21;;75313:5;;75297:21;75333:11;75365:1;75348:9;75354:3;75348;:9;:::i;:::-;:13;;75360:1;75348:13;:::i;:::-;75347:19;;;;:::i;:::-;-1:-1:-1;;;;;75403:21:0;;;;;;:11;:21;;;;;:26;;75333:33;;-1:-1:-1;75403:21:0;75333:33;;75403:26;;;;-1:-1:-1;;;75403:26:0;;;;;;;;;;;;;;;;;;:32;-1:-1:-1;;;;;75403:32:0;75385:15;:50;75381:154;;;75462:3;75456:9;;75381:154;;;75512:7;75518:1;75512:3;:7;:::i;:::-;75506:13;;75381:154;-1:-1:-1;75277:3:0;;;;:::i;:::-;;;;75248:298;;;-1:-1:-1;75563:3:0;;74929:645;-1:-1:-1;;;;74929:645:0:o;24058:811::-;24482:23;24508:106;24550:4;24508:106;;;;;;;;;;;;;;;;;24516:5;-1:-1:-1;;;;;24508:27:0;;;:106;;;;;:::i;:::-;24629:17;;24482:132;;-1:-1:-1;24629:21:0;24625:237;;24784:10;24773:30;;;;;;;;;;;;:::i;:::-;24765:85;;;;-1:-1:-1;;;24765:85:0;;10673:2:1;24765:85:0;;;10655:21:1;10712:2;10692:18;;;10685:30;10751:34;10731:18;;;10724:62;-1:-1:-1;;;10802:18:1;;;10795:40;10852:19;;24765:85:0;10645:232:1;33170:106:0;33228:7;33259:1;33255;:5;:13;;33267:1;33255:13;;;-1:-1:-1;33263:1:0;;33170:106;-1:-1:-1;33170:106:0:o;38522:212::-;25955:11;;-1:-1:-1;;;25955:11:0;;;;25947:55;;;;-1:-1:-1;;;25947:55:0;;11084:2:1;25947:55:0;;;11066:21:1;11123:2;11103:18;;;11096:30;11162:33;11142:18;;;11135:61;11213:18;;25947:55:0;11056:181:1;25947:55:0;26080:11;:19;;-1:-1:-1;;;;26080:19:0;;;-1:-1:-1;;;;;38613:26:0;::::1;26094:5:::0;38613:26;;;:12:::1;:26;::::0;;;;:37;;38643:7;;26094:5;38613:37:::1;::::0;38643:7;;38613:37:::1;:::i;:::-;::::0;;;-1:-1:-1;38661:65:0::1;::::0;-1:-1:-1;;;;;;38661:12:0::1;:29;38691:10;38711:4;38718:7:::0;38661:29:::1;:65::i;:::-;-1:-1:-1::0;;26260:11:0;:18;;-1:-1:-1;;;;26260:18:0;-1:-1:-1;;;26260:18:0;;;38522:212::o;21527:285::-;21725:68;;-1:-1:-1;;;;;3848:15:1;;;21725:68:0;;;3830:34:1;3900:15;;3880:18;;;3873:43;3932:18;;;3925:34;;;21671:133:0;;21705:5;;-1:-1:-1;;;21748:27:0;3765:18:1;;21725:68:0;3747:218:1;33822:1273:0;33870:9;33896:6;33892:1196;;-1:-1:-1;33911:1:0;33904:8;;33892:1196;33956:1;33984;-1:-1:-1;;;34004:41:0;;34000:119;;34073:3;34066:10;;;;;34101:2;34095:8;34000:119;-1:-1:-1;;;34137:2:0;:25;34133:102;;34190:2;34183:9;;;;;34217:2;34211:8;34133:102;34259:11;34253:2;:17;34249:94;;34298:2;34291:9;;;;;34325:2;34319:8;34249:94;34367:7;34361:2;:13;34357:89;;34402:2;34395:9;;;;;34429:1;34423:7;34357:89;34470:5;34464:2;:11;34460:86;;34503:1;34496:8;;;;;34529:1;34523:7;34460:86;34570:4;34564:2;:10;34560:85;;34602:1;34595:8;;;;;34628:1;34622:7;34560:85;34669:3;34663:2;:9;34659:57;;34699:1;34693:7;34659:57;34749:1;34739:5;34743:1;34739;:5;:::i;:::-;34735:9;;:1;:9;:::i;:::-;34734:16;;;-1:-1:-1;34784:1:0;34774:5;34734:16;34774:1;:5;:::i;:::-;34770:9;;:1;:9;:::i;:::-;34769:16;;;-1:-1:-1;34819:1:0;34809:5;34769:16;34809:1;:5;:::i;:::-;34805:9;;:1;:9;:::i;:::-;34804:16;;;-1:-1:-1;34854:1:0;34844:5;34804:16;34844:1;:5;:::i;:::-;34840:9;;:1;:9;:::i;:::-;34839:16;;;-1:-1:-1;34889:1:0;34879:5;34839:16;34879:1;:5;:::i;:::-;34875:9;;:1;:9;:::i;:::-;34874:16;;;-1:-1:-1;34924:1:0;34914:5;34874:16;34914:1;:5;:::i;:::-;34910:9;;:1;:9;:::i;:::-;34909:16;;;-1:-1:-1;34959:1:0;34949:5;34909:16;34949:1;:5;:::i;:::-;34945:9;;:1;:9;:::i;:::-;34944:16;;;-1:-1:-1;35012:10:0;35025:5;34944:16;35025:1;:5;:::i;:::-;35012:18;;35064:2;35060:1;:6;:15;;35073:2;35060:15;;;35069:1;35060:15;35045:31;;;;;;;16626:229;16763:12;16795:52;16817:6;16825:4;16831:1;16834:12;16763;14064:20;;18046:60;;;;-1:-1:-1;;;18046:60:0;;9973:2:1;18046:60:0;;;9955:21:1;10012:2;9992:18;;;9985:30;10051:31;10031:18;;;10024:59;10100:18;;18046:60:0;9945:179:1;18046:60:0;18180:12;18194:23;18221:6;-1:-1:-1;;;;;18221:11:0;18241:5;18249:4;18221:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18179:75;;;;18272:52;18290:7;18299:10;18311:12;20615;20644:7;20640:595;;;-1:-1:-1;20675:10:0;20668:17;;20640:595;20789:17;;:21;20785:439;;21052:10;21046:17;21113:15;21100:10;21096:2;21092:19;21085:44;21000:148;21195:12;21188:20;;-1:-1:-1;;;21188:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:376:1;;;130:3;123:4;115:6;111:17;107:27;97:2;;155:8;145;138:26;97:2;-1:-1:-1;185:20:1;;-1:-1:-1;;;;;217:30:1;;214:2;;;267:8;257;250:26;214:2;311:4;303:6;299:17;287:29;;363:3;356:4;347:6;339;335:19;331:30;328:39;325:2;;;380:1;377;370:12;325:2;87:303;;;;;:::o;395:257::-;;507:2;495:9;486:7;482:23;478:32;475:2;;;528:6;520;513:22;475:2;572:9;559:23;591:31;616:5;591:31;:::i;657:261::-;;780:2;768:9;759:7;755:23;751:32;748:2;;;801:6;793;786:22;748:2;838:9;832:16;857:31;882:5;857:31;:::i;923:886::-;;;;;;1109:2;1097:9;1088:7;1084:23;1080:32;1077:2;;;1130:6;1122;1115:22;1077:2;1174:9;1161:23;1193:31;1218:5;1193:31;:::i;:::-;1243:5;-1:-1:-1;1299:2:1;1284:18;;1271:32;-1:-1:-1;;;;;1352:14:1;;;1349:2;;;1384:6;1376;1369:22;1349:2;1428:59;1479:7;1470:6;1459:9;1455:22;1428:59;:::i;:::-;1506:8;;-1:-1:-1;1402:85:1;-1:-1:-1;1594:2:1;1579:18;;1566:32;;-1:-1:-1;1610:16:1;;;1607:2;;;1644:6;1636;1629:22;1607:2;;1688:61;1741:7;1730:8;1719:9;1715:24;1688:61;:::i;:::-;1067:742;;;;-1:-1:-1;1067:742:1;;-1:-1:-1;1768:8:1;;1662:87;1067:742;-1:-1:-1;;;1067:742:1:o;1814:325::-;;;1943:2;1931:9;1922:7;1918:23;1914:32;1911:2;;;1964:6;1956;1949:22;1911:2;2008:9;1995:23;2027:31;2052:5;2027:31;:::i;:::-;2077:5;2129:2;2114:18;;;;2101:32;;-1:-1:-1;;;1901:238:1:o;2144:297::-;;2264:2;2252:9;2243:7;2239:23;2235:32;2232:2;;;2285:6;2277;2270:22;2232:2;2322:9;2316:16;2375:5;2368:13;2361:21;2354:5;2351:32;2341:2;;2402:6;2394;2387:22;2446:190;;2558:2;2546:9;2537:7;2533:23;2529:32;2526:2;;;2579:6;2571;2564:22;2526:2;-1:-1:-1;2607:23:1;;2516:120;-1:-1:-1;2516:120:1:o;2641:194::-;;2764:2;2752:9;2743:7;2739:23;2735:32;2732:2;;;2785:6;2777;2770:22;2732:2;-1:-1:-1;2813:16:1;;2722:113;-1:-1:-1;2722:113:1:o;2840:258::-;;;2969:2;2957:9;2948:7;2944:23;2940:32;2937:2;;;2990:6;2982;2975:22;2937:2;-1:-1:-1;;3018:23:1;;;3088:2;3073:18;;;3060:32;;-1:-1:-1;2927:171:1:o;3103:274::-;;3270:6;3264:13;3286:53;3332:6;3327:3;3320:4;3312:6;3308:17;3286:53;:::i;:::-;3355:16;;;;;3240:137;-1:-1:-1;;3240:137:1:o;5158:383::-;;5307:2;5296:9;5289:21;5339:6;5333:13;5382:6;5377:2;5366:9;5362:18;5355:34;5398:66;5457:6;5452:2;5441:9;5437:18;5432:2;5424:6;5420:15;5398:66;:::i;:::-;5525:2;5504:15;-1:-1:-1;;5500:29:1;5485:45;;;;5532:2;5481:54;;5279:262;-1:-1:-1;;5279:262:1:o;13842:253::-;;-1:-1:-1;;;;;13971:2:1;13968:1;13964:10;14001:2;13998:1;13994:10;14032:3;14028:2;14024:12;14019:3;14016:21;14013:2;;;14040:18;;:::i;:::-;14076:13;;13890:205;-1:-1:-1;;;;13890:205:1:o;14100:128::-;;14171:1;14167:6;14164:1;14161:13;14158:2;;;14177:18;;:::i;:::-;-1:-1:-1;14213:9:1;;14148:80::o;14233:236::-;;-1:-1:-1;;;;;14345:2:1;14342:1;14338:10;14375:2;14372:1;14368:10;14406:3;14402:2;14398:12;14393:3;14390:21;14387:2;;;14414:18;;:::i;14474:217::-;;14540:1;14530:2;;-1:-1:-1;;;14565:31:1;;14619:4;14616:1;14609:15;14647:4;14572:1;14637:15;14530:2;-1:-1:-1;14676:9:1;;14520:171::o;14696:168::-;;14802:1;14798;14794:6;14790:14;14787:1;14784:21;14779:1;14772:9;14765:17;14761:45;14758:2;;;14809:18;;:::i;:::-;-1:-1:-1;14849:9:1;;14748:116::o;14869:125::-;;14937:1;14934;14931:8;14928:2;;;14942:18;;:::i;:::-;-1:-1:-1;14979:9:1;;14918:76::o;14999:258::-;15071:1;15081:113;15095:6;15092:1;15089:13;15081:113;;;15171:11;;;15165:18;15152:11;;;15145:39;15117:2;15110:10;15081:113;;;15212:6;15209:1;15206:13;15203:2;;;-1:-1:-1;;15247:1:1;15229:16;;15222:27;15052:205::o;15262:380::-;15347:1;15337:12;;15394:1;15384:12;;;15405:2;;15459:4;15451:6;15447:17;15437:27;;15405:2;15512;15504:6;15501:14;15481:18;15478:38;15475:2;;;15558:10;15553:3;15549:20;15546:1;15539:31;15593:4;15590:1;15583:15;15621:4;15618:1;15611:15;15647:135;;-1:-1:-1;;15707:17:1;;15704:2;;;15727:18;;:::i;:::-;-1:-1:-1;15774:1:1;15763:13;;15694:88::o;15787:127::-;15848:10;15843:3;15839:20;15836:1;15829:31;15879:4;15876:1;15869:15;15903:4;15900:1;15893:15;15919:131;-1:-1:-1;;;;;15994:31:1;;15984:42;;15974:2;;16040:1;16037;16030:12;15974:2;15964:86;:::o
Swarm Source
ipfs://877ea06ffccc72129161deabbdeaf9b4a6bc268366fcadafe70ce7d8c8d86097
Loading...
Loading
Loading...
Loading
OVERVIEW
Logic contract for mStable Alchemix USD (alUSD) Feeder Pool Savings Vault (v-fPmUSD/alUSD).Net Worth in USD
$0.00
Net Worth in ETH
0
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.