Feature Tip: Add private address tag to any address under My Name Tag !
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:
BoostedSavingsVault
Compiler Version
v0.8.2+commit.661d1103
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-09-08
*/
// SPDX-License-Identifier: AGPL-3.0-or-later
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 IBoostedVaultWithLockup {
/**
* @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);
/**
* @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);
/**
* @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
);
}
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 Modifier to allow function calls only from the ProxyAdmin.
*/
modifier onlyProxyAdmin() {
require(msg.sender == _proxyAdmin(), "Only ProxyAdmin can execute");
_;
}
/**
* @dev Modifier to allow function calls only from the Manager.
*/
modifier onlyManager() {
require(msg.sender == _manager(), "Only manager 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 Staking Module address from the Nexus
* @return Address of the Staking Module contract
*/
function _staking() internal view returns (address) {
return nexus.getModule(KEY_STAKING);
}
/**
* @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);
}
/**
* @dev Return MetaToken Module address from the Nexus
* @return Address of the MetaToken Module contract
*/
function _metaToken() internal view returns (address) {
return nexus.getModule(KEY_META_TOKEN);
}
/**
* @dev Return OracleHub Module address from the Nexus
* @return Address of the OracleHub Module contract
*/
function _oracleHub() internal view returns (address) {
return nexus.getModule(KEY_ORACLE_HUB);
}
/**
* @dev Return Manager Module address from the Nexus
* @return Address of the Manager Module contract
*/
function _manager() internal view returns (address) {
return nexus.getModule(KEY_MANAGER);
}
/**
* @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);
}
}
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 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 9e38 / 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
*/
constructor(
address _stakingToken,
address _boostDirector,
uint256 _priceCoeff,
uint256 _boostCoeff
) {
stakingToken = IERC20(_stakingToken);
boostDirector = IBoostDirector(_boostDirector);
priceCoeff = _priceCoeff;
boostCoeff = _boostCoeff;
}
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));
}
}
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);
}
}
// Internal
// Libs
/**
* @title BoostedSavingsVault
* @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
*/
contract BoostedSavingsVault is
IBoostedVaultWithLockup,
Initializable,
InitializableRewardsDistributionRecipient,
BoostedTokenWrapper
{
using SafeERC20 for IERC20;
using StableMath for uint256;
using SafeCast for uint256;
event RewardAdded(uint256 reward);
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);
IERC20 public immutable rewardsToken;
uint64 public constant DURATION = 7 days;
// Length of token lockup, after rewards are earned
uint256 public constant LOCKUP = 26 weeks;
// Percentage of earned tokens unlocked immediately
uint64 public constant UNLOCK = 33e16;
// Timestamp for current period finish
uint256 public periodFinish;
// RewardRate for the rest of the PERIOD
uint256 public rewardRate;
// Last time any user took action
uint256 public lastUpdateTime;
// Ever increasing rewardPerToken rate, based on % of total supply
uint256 public rewardPerTokenStored;
mapping(address => UserData) public userData;
// Locked reward tracking
mapping(address => Reward[]) public userRewards;
mapping(address => uint64) public userClaim;
struct UserData {
uint128 rewardPerTokenPaid;
uint128 rewards;
uint64 lastAction;
uint64 rewardCount;
}
struct Reward {
uint64 start;
uint64 finish;
uint128 rate;
}
constructor(
address _nexus,
address _stakingToken,
address _boostDirector,
uint256 _priceCoeff,
uint256 _coeff,
address _rewardsToken
)
InitializableRewardsDistributionRecipient(_nexus)
BoostedTokenWrapper(_stakingToken, _boostDirector, _priceCoeff, _coeff)
{
rewardsToken = IERC20(_rewardsToken);
}
/**
* @dev StakingRewards is a TokenWrapper and RewardRecipient
* Constants added to bytecode at deployTime to reduce SLOAD cost
*/
function initialize(
address _rewardsDistributor,
string calldata _nameArg,
string calldata _symbolArg
) external initializer {
InitializableRewardsDistributionRecipient._initialize(_rewardsDistributor);
BoostedTokenWrapper._initialize(_nameArg, _symbolArg);
}
/**
* @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 lastApplicableTime) = _rewardPerToken();
// If statement protects against loss in initialisation case
if (newRewardPerToken > 0) {
rewardPerTokenStored = newRewardPerToken;
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);
// 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),
lastAction: currentTime64,
rewardCount: data.rewardCount + 1
});
} else {
userData[_account] = UserData({
rewardPerTokenPaid: SafeCast.toUint128(newRewardPerToken),
rewards: data.rewards,
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);
emit RewardPaid(msg.sender, unlocked);
}
}
/**
* @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);
emit RewardPaid(msg.sender, total);
}
}
/**
* @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);
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);
emit Withdrawn(msg.sender, _amount);
}
/***************************************
GETTERS
****************************************/
/**
* @dev Gets the RewardsToken
*/
function getRewardToken() external view override returns (IERC20) {
return rewardsToken;
}
/**
* @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 rewardPerToken_, ) = _rewardPerToken();
return rewardPerToken_;
}
function _rewardPerToken()
internal
view
returns (uint256 rewardPerToken_, 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, lastApplicableTime);
}
// new reward units to distribute = rewardRate * timeSinceLastUpdate
uint256 rewardUnitsToDistribute = rewardRate * timeDelta; // + 1 SLOAD
uint256 supply = totalSupply(); // + 1 SLOAD
// If there is no StakingToken liquidity, avoid div(0)
// If there is nothing to distribute, short circuit
if (supply == 0 || rewardUnitsToDistribute == 0) {
return (rewardPerTokenStored, lastApplicableTime);
}
// new reward units per token = (rewardUnitsToDistribute * 1e18) / totalTokens
uint256 unitsToDistributePerToken = rewardUnitsToDistribute.divPrecisely(supply);
// return summed rate
return (rewardPerTokenStored + unitsToDistributePerToken, 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
*/
function earned(address _account) public view override returns (uint256) {
uint256 newEarned = _earned(
_account,
userData[_account].rewardPerTokenPaid,
rewardPerToken()
);
uint256 immediatelyUnlocked = newEarned.mulTruncate(UNLOCK);
return immediatelyUnlocked + userData[_account].rewards;
}
/**
* @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
)
{
(first, last) = _unclaimedEpochs(_account);
(uint256 unlocked, ) = _unclaimedRewards(_account, first, last);
amount = unlocked + earned(_account);
}
/** @dev Returns only the most recently earned rewards */
function _earned(
address _account,
uint256 _userRewardPerTokenPaid,
uint256 _currentRewardPerToken
) internal view returns (uint256) {
// current rate per token - rate user previously received
uint256 userRewardDelta = _currentRewardPerToken - _userRewardPerTokenPaid; // + 1 SLOAD
// Short circuit if there is nothing new to distribute
if (userRewardDelta == 0) {
return 0;
}
// new reward = staked tokens * difference in rate
uint256 userNewReward = balanceOf(_account).mulTruncate(userRewardDelta); // + 1 SLOAD
// add to previous rewards
return userNewReward;
}
/**
* @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
onlyRewardsDistributor
updateReward(address(0))
{
require(_reward < 1e24, "Cannot notify with more than a million units");
uint256 currentTime = block.timestamp;
// If previous period over, reset rewardRate
if (currentTime >= periodFinish) {
rewardRate = _reward / DURATION;
}
// If additional reward to existing period, calc sum
else {
uint256 remaining = periodFinish - currentTime;
uint256 leftover = remaining * rewardRate;
rewardRate = (_reward + leftover) / DURATION;
}
lastUpdateTime = currentTime;
periodFinish = currentTime + DURATION;
emit RewardAdded(_reward);
}
}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":"_coeff","type":"uint256"},{"internalType":"address","name":"_rewardsToken","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"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","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"}],"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":"getRewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardsDistributor","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":[{"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"}],"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":"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"}],"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":"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
6101406040523480156200001257600080fd5b5060405162002c3638038062002c368339810160408190526200003591620000f6565b8484848489806001600160a01b038116620000965760405162461bcd60e51b815260206004820152601560248201527f4e657875732061646472657373206973207a65726f0000000000000000000000604482015260640160405180910390fd5b6001600160601b0319606091821b811660805295811b861660a05293841b851660c052506101009190915260e0529190911b166101205250620001649350505050565b80516001600160a01b0381168114620000f157600080fd5b919050565b60008060008060008060c087890312156200010f578182fd5b6200011a87620000d9565b95506200012a60208801620000d9565b94506200013a60408801620000d9565b935060608701519250608087015191506200015860a08801620000d9565b90509295509295509295565b60805160601c60a05160601c60c05160601c60e051610100516101205160601c612a37620001ff6000396000818161043e0152818161064501528181610cbc01526113c601526000818161036501526114600152600081816106860152611f1d01526000818161056801526114c201526000818161049001528181611e91015261227801526000818161051b0152611c9d0152612a376000f3fe608060405234801561001057600080fd5b50600436106102525760003560e01c806372f702f311610146578063b43082ec116100c3578063cf7bf6b711610087578063cf7bf6b71461062d578063d1af0c7d14610640578063df136d6514610667578063e9fad8ee14610670578063ebe2b12b14610678578063f62aa9751461068157610252565b8063b43082ec14610563578063b88a802f1461058a578063c891091314610592578063c8f33c911461061c578063cd3daf9d1461062557610252565b8063949813b81161010a578063949813b8146104e057806395d89b411461050e578063a3f5c1d214610516578063a694fc3a1461053d578063adc9772e1461055057610252565b806372f702f31461048b5780637b0a47ee146104b257806380faa57d146104bb578063845aef4b146104c357806390657147146104cd57610252565b8063372500ab116101d4578063594dd43211610198578063594dd432146103d457806363c2a20a146103e757806367ba3d901461042957806369940d791461043c57806370a082311461046257610252565b8063372500ab1461035857806338d3eb38146103605780633c6b16ab146103875780633f2a55401461039a578063523993da146103c557610252565b8063197621431161021b57806319762143146103045780631be05289146103195780632af9cc41146103235780632e1a7d4d14610336578063313ce5671461034957610252565b80628cc2621461025757806306fdde031461027d5780630a6b433f1461029257806312064c34146102d357806318160ddd146102fc575b600080fd5b61026a61026536600461271c565b6106a8565b6040519081526020015b60405180910390f35b610285610735565b604051610274919061288b565b6102bb6102a036600461271c565b603f602052600090815260409020546001600160401b031681565b6040516001600160401b039091168152602001610274565b61026a6102e136600461271c565b6001600160a01b031660009081526038602052604090205490565b60365461026a565b61031761031236600461271c565b6107c7565b005b6102bb62093a8081565b61031761033136600461284e565b6107f1565b61031761034436600461281e565b61082e565b60405160128152602001610274565b610317610850565b61026a7f000000000000000000000000000000000000000000000000000000000000000081565b61031761039536600461281e565b610884565b6033546103ad906001600160a01b031681565b6040516001600160a01b039091168152602001610274565b6102bb670494654067e1000081565b6103176103e236600461284e565b610a0b565b6103fa6103f53660046127d3565b610a20565b604080516001600160401b0394851681529390921660208401526001600160801b031690820152606001610274565b61026a61043736600461271c565b610a72565b7f00000000000000000000000000000000000000000000000000000000000000006103ad565b61026a61047036600461271c565b6001600160a01b031660009081526037602052604090205490565b6103ad7f000000000000000000000000000000000000000000000000000000000000000081565b61026a603a5481565b61026a610aa5565b61026a62eff10081565b6103176104db366004612754565b610ab8565b6104f36104ee36600461271c565b610bff565b60408051938452602084019290925290820152606001610274565b610285610c3f565b6103ad7f000000000000000000000000000000000000000000000000000000000000000081565b61031761054b36600461281e565b610c4e565b61031761055e3660046127d3565b610c63565b6103ad7f000000000000000000000000000000000000000000000000000000000000000081565b610317610c78565b6105e26105a036600461271c565b603d60205260009081526040902080546001909101546001600160801b0380831692600160801b900416906001600160401b0380821691600160401b90041684565b604080516001600160801b0395861681529490931660208501526001600160401b0391821692840192909252166060820152608001610274565b61026a603b5481565b61026a610d23565b61031761063b36600461271c565b610d35565b6103ad7f000000000000000000000000000000000000000000000000000000000000000081565b61026a603c5481565b610317610d7e565b61026a60395481565b61026a7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b0381166000908152603d602052604081205481906106df9084906001600160801b03166106da610d23565b610dad565b905060006106f582670494654067e10000610e02565b6001600160a01b0385166000908152603d602052604090205490915061072b90600160801b90046001600160801b0316826128be565b925050505b919050565b60606034805461074490612983565b80601f016020809104026020016040519081016040528092919081815260200182805461077090612983565b80156107bd5780601f10610792576101008083540402835291602001916107bd565b820191906000526020600020905b8154815290600101906020018083116107a057829003601f168201915b5050505050905090565b6107cf610e17565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b336107fb81610e81565b33600081815260386020526040902054610815905b6112c1565b61081f8484611346565b6108288161142a565b50505050565b3361083881610e81565b33610842836112c1565b61084b8161142a565b505050565b3361085a81610e81565b3360008061086733611641565b915091506108758282611346565b50506108808161142a565b5050565b6033546001600160a01b031633146108e35760405162461bcd60e51b815260206004820181905260248201527f43616c6c6572206973206e6f7420726577617264206469737472696275746f7260448201526064015b60405180910390fd5b60006108ee81610e81565b69d3c21bcecceda1000000821061095c5760405162461bcd60e51b815260206004820152602c60248201527f43616e6e6f74206e6f746966792077697468206d6f7265207468616e2061206d60448201526b696c6c696f6e20756e69747360a01b60648201526084016108da565b6039544290811061097c5761097462093a8084612901565b603a556109be565b60008160395461098c9190612940565b90506000603a548261099e9190612921565b905062093a806109ae82876128be565b6109b89190612901565b603a5550505b603b8190556109d062093a80826128be565b6039556040518381527fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9060200160405180910390a1505050565b33610a1581610e81565b3361081f8484611346565b603e6020528160005260406000208181548110610a3c57600080fd5b6000918252602090912001546001600160401b038082169350600160401b8204169150600160801b90046001600160801b031683565b6001600160a01b0381166000908152603860209081526040808320546037909252822054610a9f9161168a565b92915050565b6000610ab3426039546116a9565b905090565b600054610100900460ff1680610acd5750303b155b80610adb575060005460ff16155b610b3e5760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b60648201526084016108da565b600054610100900460ff16158015610b69576000805460ff1961ff0019909116610100171660011790555b610b72866107cf565b610be585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815292508791508690819084018382808284376000920191909152506116be92505050565b8015610bf7576000805461ff00191690555b505050505050565b6000806000610c0d84611641565b90925090506000610c1f8584846116fd565b509050610c2b856106a8565b610c3590826128be565b9350509193909250565b60606035805461074490612983565b33610c5881610e81565b336108423384611a92565b81610c6d81610e81565b8261081f8484611a92565b33610c8281610e81565b336000818152603d6020526040902080546001600160801b03808216909255600160801b9004168015610d1957610ce36001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383611b7a565b60405181815233907fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e04869060200160405180910390a25b506108808161142a565b600080610d2e611bdd565b5091505090565b80610d3f81610e81565b60405182906001600160a01b038216907fa31b3b303c759fa7ee31d89a1a6fb7eb704d8fe5c87aa4f60f54468ff121bee890600090a261084b8161142a565b33610d8881610e81565b33600081815260386020526040902054610da190610810565b60008061086733611641565b600080610dba8484612940565b905080610dcb576000915050610dfb565b6000610df682610df0886001600160a01b031660009081526037602052604090205490565b90610e02565b925050505b9392505050565b6000610dfb8383670de0b6b3a7640000611c7a565b610e1f611c99565b6001600160a01b0316336001600160a01b031614610e7f5760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920676f7665726e6f722063616e20657865637574650000000000000060448201526064016108da565b565b426000610e8d82611d2c565b9050600080610e9a611bdd565b9092509050811561127557603c829055603b8190556001600160a01b03851615611270576001600160a01b0385166000908152603d60209081526040808320815160808101835281546001600160801b03808216808452600160801b90920416948201949094526001909101546001600160401b0380821693830193909352600160401b900490911660608201529190610f3690889086610dad565b90508015611199576000610f5282670494654067e10000610e02565b90506000610f608284612940565b9050603e60008a6001600160a01b03166001600160a01b031681526020019081526020016000206040518060600160405280610fb687604001516001600160401b031662eff100610fb191906128be565b611d2c565b6001600160401b03168152602001610fd4610fb18c62eff1006128be565b6001600160401b0316815260200161100d87604001516001600160401b03168c610ffe9190612940565b6110089086612901565b611d94565b6001600160801b0390811690915282546001810184556000938452602093849020835191018054948401516040948501518416600160801b026001600160401b03918216600160401b0267ffffffffffffffff60401b199290941667ffffffffffffffff19909716969096171691909117909116929092179091558051608081019091528061109b88611d94565b6001600160801b031681526020016110c586602001516001600160801b03168561100891906128be565b6001600160801b03168152602001886001600160401b03168152602001856060015160016110f391906128d6565b6001600160401b039081169091526001600160a01b038b166000908152603d602090815260409182902084518154928601516001600160801b03908116600160801b029181166001600160801b03199094169390931790921691909117815590830151600190910180546060909401518316600160401b0267ffffffffffffffff60401b199290931667ffffffffffffffff1990941693909317161790555061126d9050565b60405180608001604052806111ad86611d94565b6001600160801b0390811682526020858101518216818401526001600160401b03808a166040808601919091526060808901518316958101959095526001600160a01b038d166000908152603d845281902086518154948801518616600160801b029086166001600160801b031990951694909417909416929092178355908401516001909201805494909301518116600160401b0267ffffffffffffffff60401b199290911667ffffffffffffffff1990941693909317169190911790555b50505b6112ba565b6001600160a01b038516156112ba576001600160a01b0385166000908152603d60205260409020600101805467ffffffffffffffff19166001600160401b0385161790555b5050505050565b600081116113055760405162461bcd60e51b8152602060048201526011602482015270043616e6e6f74207769746864726177203607c1b60448201526064016108da565b61130e81611df9565b60405181815233907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d59060200160405180910390a250565b6000806113543385856116fd565b336000908152603f60209081526040808320805467ffffffffffffffff19166001600160401b038616179055603d909152812080546001600160801b03808216909255939550919350600160801b90920416906113b182856128be565b90508015610bf7576113ed6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383611b7a565b60405181815233907fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e04869060200160405180910390a2505050505050565b6001600160a01b03811660009081526038602090815260408083205460379092528220549091670de0b6b3a764000090816114857f000000000000000000000000000000000000000000000000000000000000000086612921565b61148f9190612901565b9050670de0b6b3a764000081106115505760405163f8b2cb4f60e01b81526001600160a01b0386811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063f8b2cb4f90602401602060405180830381600087803b15801561150857600080fd5b505af115801561151c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115409190612836565b905061154c8282611ece565b9250505b600061155c8584610e02565b9050838114610bf75780846036546115749190612940565b61157e91906128be565b6036556001600160a01b0386166000908152603760205260409020819055838111156115f1576001600160a01b03861660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6115db8785612940565b60405190815260200160405180910390a3610bf7565b60006001600160a01b0387167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6116288488612940565b60405190815260200160405180910390a3505050505050565b6001600160a01b0381166000908152603f602052604081205481906001600160401b0316816116708286611fc0565b9050600061167d866120c3565b9194509092505050915091565b60008161169f670de0b6b3a764000085612921565b610dfb9190612901565b60008183116116b85782610dfb565b50919050565b6116d66033805460ff60a01b1916600160a01b179055565b81516116e9906034906020850190612646565b50805161084b906035906020840190612646565b6001600160a01b0383166000908152603f6020908152604080832054603e909252822054829142916001600160401b03909116908615801561173d575085155b156117ae5780158061179a57506001600160a01b0388166000908152603e60205260408120805490919061178157634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b03168311155b156117ae5760008394509450505050611a8a565b861561187b576001600160a01b0388166000908152603e602052604090206117d7600189612940565b815481106117f557634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b03600160401b9091048116908316101561187b5760405162461bcd60e51b815260206004820152602e60248201527f496e76616c6964205f6669727374206172673a204d75737420636c61696d206560448201526d61726c69657220656e747269657360901b60648201526084016108da565b60006118878888612940565b6118929060016128be565b905060005b81811015611a235760006118ab828b6128be565b6001600160a01b038c166000908152603e6020526040812080549293509091839081106118e857634e487b7160e01b600052603260045260246000fd5b60009182526020918290206040805160608101825292909101546001600160401b03808216808552600160401b830490911694840194909452600160801b90046001600160801b0316908201529150871080159061195c575080602001516001600160401b0316866001600160401b031611155b6119985760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840cae0dec6d609b1b60448201526064016108da565b60006119b182602001516001600160401b0316896116a9565b905060006119d583600001516001600160401b0316896001600160401b03166121c1565b9050600083604001516001600160801b031682846119f39190612940565b6119fd9190612921565b9050611a09818d6128be565b9b5050505050508080611a1b906129b8565b915050611897565b506001600160a01b0389166000908152603e602052604090208054611a839186918a908110611a6257634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160401b90046001600160401b03166116a9565b9450505050505b935093915050565b60008111611ad35760405162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b60448201526064016108da565b6001600160a01b038216611b295760405162461bcd60e51b815260206004820152601b60248201527f496e76616c69642062656e65666963696172792061646472657373000000000060448201526064016108da565b611b3382826121d7565b604080518281523360208201526001600160a01b038416917f9f9e4044c5742cca66ca090b21552bac14645e68bad7a92364a9d9ff18111a1c910160405180910390a25050565b6040516001600160a01b03831660248201526044810182905261084b90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526122b7565b6000806000611bea610aa5565b90506000603b5482611bfc9190612940565b905080611c105750603c5492509050611c76565b600081603a54611c209190612921565b90506000611c2d60365490565b9050801580611c3a575081155b15611c5057603c54849550955050505050611c76565b6000611c5c838361168a565b905080603c54611c6c91906128be565b9650939450505050505b9091565b600081611c878486612921565b611c919190612901565b949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b158015611cf457600080fd5b505afa158015611d08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab39190612738565b6000600160401b8210611d905760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016108da565b5090565b6000600160801b8210611d905760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b60648201526084016108da565b603354600160a01b900460ff16611e525760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108da565b6033805460ff60a01b191690553360009081526038602052604081208054839290611e7e908490612940565b90915550611eb890506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383611b7a565b506033805460ff60a01b1916600160a01b179055565b600081611ee45750670de0b6b3a7640000610a9f565b6000611efb611ef685620f4240612921565b612389565b90506000611f0882612389565b90506000611f168284612921565b905080600a7f0000000000000000000000000000000000000000000000000000000000000000611f5088697f0e10af47c1c70000006116a9565b611f5a9190612921565b611f649190612901565b611f7690670de0b6b3a7640000612921565b611f809190612901565b9350611fb66729a2241af62c0000611fb1670de0b6b3a7640000611fac88670d99a8cec7e200006128be565b6121c1565b6116a9565b9695505050505050565b6001600160a01b0381166000908152603e602052604081205480611fe8576000915050610a9f565b600080611ff6600184612940565b905060005b60808110156120b857818310612010576120b8565b6000600261201e84866128be565b6120299060016128be565b6120339190612901565b6001600160a01b0388166000908152603e602052604090208054919250908290811061206f57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b039081169089161115612097578093506120a5565b6120a2600182612940565b92505b50806120b0816129b8565b915050611ffb565b509095945050505050565b6001600160a01b0381166000908152603e6020526040812054806120eb576000915050610730565b6000806120f9600184612940565b905060005b60808110156121b757818310612113576121b7565b6000600261212184866128be565b61212c9060016128be565b6121369190612901565b6001600160a01b0388166000908152603e602052604090208054919250908290811061217257634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b0316421115612196578093506121a4565b6121a1600182612940565b92505b50806121af816129b8565b9150506120fe565b5090949350505050565b60008183116121d05781610dfb565b5090919050565b603354600160a01b900460ff166122305760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108da565b6033805460ff60a01b191690556001600160a01b038216600090815260386020526040812080548392906122659084906128be565b909155506122a090506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084612503565b50506033805460ff60a01b1916600160a01b179055565b600061230c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661253b9092919063ffffffff16565b80519091501561084b578080602001905181019061232a91906127fe565b61084b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108da565b60008161239857506000610730565b816001600160801b82106123b15760809190911c9060401b5b600160401b82106123c75760409190911c9060201b5b64010000000082106123de5760209190911c9060101b5b6201000082106123f35760109190911c9060081b5b61010082106124075760089190911c9060041b5b6010821061241a5760049190911c9060021b5b600882106124265760011b5b60016124328286612901565b61243c90836128be565b901c9050600161244c8286612901565b61245690836128be565b901c905060016124668286612901565b61247090836128be565b901c905060016124808286612901565b61248a90836128be565b901c9050600161249a8286612901565b6124a490836128be565b901c905060016124b48286612901565b6124be90836128be565b901c905060016124ce8286612901565b6124d890836128be565b901c905060006124e88286612901565b90508082106124f757806124f9565b815b9350505050610730565b6040516001600160a01b03808516602483015283166044820152606481018290526108289085906323b872dd60e01b90608401611ba6565b6060611c91848460008585843b6125945760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108da565b600080866001600160a01b031685876040516125b0919061286f565b60006040518083038185875af1925050503d80600081146125ed576040519150601f19603f3d011682016040523d82523d6000602084013e6125f2565b606091505b509150915061260282828661260d565b979650505050505050565b6060831561261c575081610dfb565b82511561262c5782518084602001fd5b8160405162461bcd60e51b81526004016108da919061288b565b82805461265290612983565b90600052602060002090601f01602090048101928261267457600085556126ba565b82601f1061268d57805160ff19168380011785556126ba565b828001600101855582156126ba579182015b828111156126ba57825182559160200191906001019061269f565b50611d909291505b80821115611d9057600081556001016126c2565b60008083601f8401126126e7578182fd5b5081356001600160401b038111156126fd578182fd5b60208301915083602082850101111561271557600080fd5b9250929050565b60006020828403121561272d578081fd5b8135610dfb816129e9565b600060208284031215612749578081fd5b8151610dfb816129e9565b60008060008060006060868803121561276b578081fd5b8535612776816129e9565b945060208601356001600160401b0380821115612791578283fd5b61279d89838a016126d6565b909650945060408801359150808211156127b5578283fd5b506127c2888289016126d6565b969995985093965092949392505050565b600080604083850312156127e5578182fd5b82356127f0816129e9565b946020939093013593505050565b60006020828403121561280f578081fd5b81518015158114610dfb578182fd5b60006020828403121561282f578081fd5b5035919050565b600060208284031215612847578081fd5b5051919050565b60008060408385031215612860578182fd5b50508035926020909101359150565b60008251612881818460208701612957565b9190910192915050565b60006020825282518060208401526128aa816040850160208701612957565b601f01601f19169190910160400192915050565b600082198211156128d1576128d16129d3565b500190565b60006001600160401b038083168185168083038211156128f8576128f86129d3565b01949350505050565b60008261291c57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161561293b5761293b6129d3565b500290565b600082821015612952576129526129d3565b500390565b60005b8381101561297257818101518382015260200161295a565b838111156108285750506000910152565b60028104600182168061299757607f821691505b602082108114156116b857634e487b7160e01b600052602260045260246000fd5b60006000198214156129cc576129cc6129d3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146129fe57600080fd5b5056fea2646970667358221220990c0b652b36ef5f6cad2b869241b1ed7f2e26644ceda9c0764f38cede57a09564736f6c63430008020033000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3000000000000000000000000fe842e95f8911dcc21c943a1daa4bd641a1381c6000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd35920000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000009000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102525760003560e01c806372f702f311610146578063b43082ec116100c3578063cf7bf6b711610087578063cf7bf6b71461062d578063d1af0c7d14610640578063df136d6514610667578063e9fad8ee14610670578063ebe2b12b14610678578063f62aa9751461068157610252565b8063b43082ec14610563578063b88a802f1461058a578063c891091314610592578063c8f33c911461061c578063cd3daf9d1461062557610252565b8063949813b81161010a578063949813b8146104e057806395d89b411461050e578063a3f5c1d214610516578063a694fc3a1461053d578063adc9772e1461055057610252565b806372f702f31461048b5780637b0a47ee146104b257806380faa57d146104bb578063845aef4b146104c357806390657147146104cd57610252565b8063372500ab116101d4578063594dd43211610198578063594dd432146103d457806363c2a20a146103e757806367ba3d901461042957806369940d791461043c57806370a082311461046257610252565b8063372500ab1461035857806338d3eb38146103605780633c6b16ab146103875780633f2a55401461039a578063523993da146103c557610252565b8063197621431161021b57806319762143146103045780631be05289146103195780632af9cc41146103235780632e1a7d4d14610336578063313ce5671461034957610252565b80628cc2621461025757806306fdde031461027d5780630a6b433f1461029257806312064c34146102d357806318160ddd146102fc575b600080fd5b61026a61026536600461271c565b6106a8565b6040519081526020015b60405180910390f35b610285610735565b604051610274919061288b565b6102bb6102a036600461271c565b603f602052600090815260409020546001600160401b031681565b6040516001600160401b039091168152602001610274565b61026a6102e136600461271c565b6001600160a01b031660009081526038602052604090205490565b60365461026a565b61031761031236600461271c565b6107c7565b005b6102bb62093a8081565b61031761033136600461284e565b6107f1565b61031761034436600461281e565b61082e565b60405160128152602001610274565b610317610850565b61026a7f0000000000000000000000000000000000000000000000000de0b6b3a764000081565b61031761039536600461281e565b610884565b6033546103ad906001600160a01b031681565b6040516001600160a01b039091168152602001610274565b6102bb670494654067e1000081565b6103176103e236600461284e565b610a0b565b6103fa6103f53660046127d3565b610a20565b604080516001600160401b0394851681529390921660208401526001600160801b031690820152606001610274565b61026a61043736600461271c565b610a72565b7f000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd26103ad565b61026a61047036600461271c565b6001600160a01b031660009081526037602052604090205490565b6103ad7f000000000000000000000000fe842e95f8911dcc21c943a1daa4bd641a1381c681565b61026a603a5481565b61026a610aa5565b61026a62eff10081565b6103176104db366004612754565b610ab8565b6104f36104ee36600461271c565b610bff565b60408051938452602084019290925290820152606001610274565b610285610c3f565b6103ad7f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb381565b61031761054b36600461281e565b610c4e565b61031761055e3660046127d3565b610c63565b6103ad7f000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd359281565b610317610c78565b6105e26105a036600461271c565b603d60205260009081526040902080546001909101546001600160801b0380831692600160801b900416906001600160401b0380821691600160401b90041684565b604080516001600160801b0395861681529490931660208501526001600160401b0391821692840192909252166060820152608001610274565b61026a603b5481565b61026a610d23565b61031761063b36600461271c565b610d35565b6103ad7f000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd281565b61026a603c5481565b610317610d7e565b61026a60395481565b61026a7f000000000000000000000000000000000000000000000000000000000000000981565b6001600160a01b0381166000908152603d602052604081205481906106df9084906001600160801b03166106da610d23565b610dad565b905060006106f582670494654067e10000610e02565b6001600160a01b0385166000908152603d602052604090205490915061072b90600160801b90046001600160801b0316826128be565b925050505b919050565b60606034805461074490612983565b80601f016020809104026020016040519081016040528092919081815260200182805461077090612983565b80156107bd5780601f10610792576101008083540402835291602001916107bd565b820191906000526020600020905b8154815290600101906020018083116107a057829003601f168201915b5050505050905090565b6107cf610e17565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b336107fb81610e81565b33600081815260386020526040902054610815905b6112c1565b61081f8484611346565b6108288161142a565b50505050565b3361083881610e81565b33610842836112c1565b61084b8161142a565b505050565b3361085a81610e81565b3360008061086733611641565b915091506108758282611346565b50506108808161142a565b5050565b6033546001600160a01b031633146108e35760405162461bcd60e51b815260206004820181905260248201527f43616c6c6572206973206e6f7420726577617264206469737472696275746f7260448201526064015b60405180910390fd5b60006108ee81610e81565b69d3c21bcecceda1000000821061095c5760405162461bcd60e51b815260206004820152602c60248201527f43616e6e6f74206e6f746966792077697468206d6f7265207468616e2061206d60448201526b696c6c696f6e20756e69747360a01b60648201526084016108da565b6039544290811061097c5761097462093a8084612901565b603a556109be565b60008160395461098c9190612940565b90506000603a548261099e9190612921565b905062093a806109ae82876128be565b6109b89190612901565b603a5550505b603b8190556109d062093a80826128be565b6039556040518381527fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9060200160405180910390a1505050565b33610a1581610e81565b3361081f8484611346565b603e6020528160005260406000208181548110610a3c57600080fd5b6000918252602090912001546001600160401b038082169350600160401b8204169150600160801b90046001600160801b031683565b6001600160a01b0381166000908152603860209081526040808320546037909252822054610a9f9161168a565b92915050565b6000610ab3426039546116a9565b905090565b600054610100900460ff1680610acd5750303b155b80610adb575060005460ff16155b610b3e5760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b60648201526084016108da565b600054610100900460ff16158015610b69576000805460ff1961ff0019909116610100171660011790555b610b72866107cf565b610be585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815292508791508690819084018382808284376000920191909152506116be92505050565b8015610bf7576000805461ff00191690555b505050505050565b6000806000610c0d84611641565b90925090506000610c1f8584846116fd565b509050610c2b856106a8565b610c3590826128be565b9350509193909250565b60606035805461074490612983565b33610c5881610e81565b336108423384611a92565b81610c6d81610e81565b8261081f8484611a92565b33610c8281610e81565b336000818152603d6020526040902080546001600160801b03808216909255600160801b9004168015610d1957610ce36001600160a01b037f000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd2163383611b7a565b60405181815233907fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e04869060200160405180910390a25b506108808161142a565b600080610d2e611bdd565b5091505090565b80610d3f81610e81565b60405182906001600160a01b038216907fa31b3b303c759fa7ee31d89a1a6fb7eb704d8fe5c87aa4f60f54468ff121bee890600090a261084b8161142a565b33610d8881610e81565b33600081815260386020526040902054610da190610810565b60008061086733611641565b600080610dba8484612940565b905080610dcb576000915050610dfb565b6000610df682610df0886001600160a01b031660009081526037602052604090205490565b90610e02565b925050505b9392505050565b6000610dfb8383670de0b6b3a7640000611c7a565b610e1f611c99565b6001600160a01b0316336001600160a01b031614610e7f5760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920676f7665726e6f722063616e20657865637574650000000000000060448201526064016108da565b565b426000610e8d82611d2c565b9050600080610e9a611bdd565b9092509050811561127557603c829055603b8190556001600160a01b03851615611270576001600160a01b0385166000908152603d60209081526040808320815160808101835281546001600160801b03808216808452600160801b90920416948201949094526001909101546001600160401b0380821693830193909352600160401b900490911660608201529190610f3690889086610dad565b90508015611199576000610f5282670494654067e10000610e02565b90506000610f608284612940565b9050603e60008a6001600160a01b03166001600160a01b031681526020019081526020016000206040518060600160405280610fb687604001516001600160401b031662eff100610fb191906128be565b611d2c565b6001600160401b03168152602001610fd4610fb18c62eff1006128be565b6001600160401b0316815260200161100d87604001516001600160401b03168c610ffe9190612940565b6110089086612901565b611d94565b6001600160801b0390811690915282546001810184556000938452602093849020835191018054948401516040948501518416600160801b026001600160401b03918216600160401b0267ffffffffffffffff60401b199290941667ffffffffffffffff19909716969096171691909117909116929092179091558051608081019091528061109b88611d94565b6001600160801b031681526020016110c586602001516001600160801b03168561100891906128be565b6001600160801b03168152602001886001600160401b03168152602001856060015160016110f391906128d6565b6001600160401b039081169091526001600160a01b038b166000908152603d602090815260409182902084518154928601516001600160801b03908116600160801b029181166001600160801b03199094169390931790921691909117815590830151600190910180546060909401518316600160401b0267ffffffffffffffff60401b199290931667ffffffffffffffff1990941693909317161790555061126d9050565b60405180608001604052806111ad86611d94565b6001600160801b0390811682526020858101518216818401526001600160401b03808a166040808601919091526060808901518316958101959095526001600160a01b038d166000908152603d845281902086518154948801518616600160801b029086166001600160801b031990951694909417909416929092178355908401516001909201805494909301518116600160401b0267ffffffffffffffff60401b199290911667ffffffffffffffff1990941693909317169190911790555b50505b6112ba565b6001600160a01b038516156112ba576001600160a01b0385166000908152603d60205260409020600101805467ffffffffffffffff19166001600160401b0385161790555b5050505050565b600081116113055760405162461bcd60e51b8152602060048201526011602482015270043616e6e6f74207769746864726177203607c1b60448201526064016108da565b61130e81611df9565b60405181815233907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d59060200160405180910390a250565b6000806113543385856116fd565b336000908152603f60209081526040808320805467ffffffffffffffff19166001600160401b038616179055603d909152812080546001600160801b03808216909255939550919350600160801b90920416906113b182856128be565b90508015610bf7576113ed6001600160a01b037f000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd2163383611b7a565b60405181815233907fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e04869060200160405180910390a2505050505050565b6001600160a01b03811660009081526038602090815260408083205460379092528220549091670de0b6b3a764000090816114857f0000000000000000000000000000000000000000000000000de0b6b3a764000086612921565b61148f9190612901565b9050670de0b6b3a764000081106115505760405163f8b2cb4f60e01b81526001600160a01b0386811660048301526000917f000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd35929091169063f8b2cb4f90602401602060405180830381600087803b15801561150857600080fd5b505af115801561151c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115409190612836565b905061154c8282611ece565b9250505b600061155c8584610e02565b9050838114610bf75780846036546115749190612940565b61157e91906128be565b6036556001600160a01b0386166000908152603760205260409020819055838111156115f1576001600160a01b03861660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6115db8785612940565b60405190815260200160405180910390a3610bf7565b60006001600160a01b0387167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6116288488612940565b60405190815260200160405180910390a3505050505050565b6001600160a01b0381166000908152603f602052604081205481906001600160401b0316816116708286611fc0565b9050600061167d866120c3565b9194509092505050915091565b60008161169f670de0b6b3a764000085612921565b610dfb9190612901565b60008183116116b85782610dfb565b50919050565b6116d66033805460ff60a01b1916600160a01b179055565b81516116e9906034906020850190612646565b50805161084b906035906020840190612646565b6001600160a01b0383166000908152603f6020908152604080832054603e909252822054829142916001600160401b03909116908615801561173d575085155b156117ae5780158061179a57506001600160a01b0388166000908152603e60205260408120805490919061178157634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b03168311155b156117ae5760008394509450505050611a8a565b861561187b576001600160a01b0388166000908152603e602052604090206117d7600189612940565b815481106117f557634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b03600160401b9091048116908316101561187b5760405162461bcd60e51b815260206004820152602e60248201527f496e76616c6964205f6669727374206172673a204d75737420636c61696d206560448201526d61726c69657220656e747269657360901b60648201526084016108da565b60006118878888612940565b6118929060016128be565b905060005b81811015611a235760006118ab828b6128be565b6001600160a01b038c166000908152603e6020526040812080549293509091839081106118e857634e487b7160e01b600052603260045260246000fd5b60009182526020918290206040805160608101825292909101546001600160401b03808216808552600160401b830490911694840194909452600160801b90046001600160801b0316908201529150871080159061195c575080602001516001600160401b0316866001600160401b031611155b6119985760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840cae0dec6d609b1b60448201526064016108da565b60006119b182602001516001600160401b0316896116a9565b905060006119d583600001516001600160401b0316896001600160401b03166121c1565b9050600083604001516001600160801b031682846119f39190612940565b6119fd9190612921565b9050611a09818d6128be565b9b5050505050508080611a1b906129b8565b915050611897565b506001600160a01b0389166000908152603e602052604090208054611a839186918a908110611a6257634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160401b90046001600160401b03166116a9565b9450505050505b935093915050565b60008111611ad35760405162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b60448201526064016108da565b6001600160a01b038216611b295760405162461bcd60e51b815260206004820152601b60248201527f496e76616c69642062656e65666963696172792061646472657373000000000060448201526064016108da565b611b3382826121d7565b604080518281523360208201526001600160a01b038416917f9f9e4044c5742cca66ca090b21552bac14645e68bad7a92364a9d9ff18111a1c910160405180910390a25050565b6040516001600160a01b03831660248201526044810182905261084b90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526122b7565b6000806000611bea610aa5565b90506000603b5482611bfc9190612940565b905080611c105750603c5492509050611c76565b600081603a54611c209190612921565b90506000611c2d60365490565b9050801580611c3a575081155b15611c5057603c54849550955050505050611c76565b6000611c5c838361168a565b905080603c54611c6c91906128be565b9650939450505050505b9091565b600081611c878486612921565b611c919190612901565b949350505050565b60007f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b158015611cf457600080fd5b505afa158015611d08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab39190612738565b6000600160401b8210611d905760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016108da565b5090565b6000600160801b8210611d905760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b60648201526084016108da565b603354600160a01b900460ff16611e525760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108da565b6033805460ff60a01b191690553360009081526038602052604081208054839290611e7e908490612940565b90915550611eb890506001600160a01b037f000000000000000000000000fe842e95f8911dcc21c943a1daa4bd641a1381c6163383611b7a565b506033805460ff60a01b1916600160a01b179055565b600081611ee45750670de0b6b3a7640000610a9f565b6000611efb611ef685620f4240612921565b612389565b90506000611f0882612389565b90506000611f168284612921565b905080600a7f0000000000000000000000000000000000000000000000000000000000000009611f5088697f0e10af47c1c70000006116a9565b611f5a9190612921565b611f649190612901565b611f7690670de0b6b3a7640000612921565b611f809190612901565b9350611fb66729a2241af62c0000611fb1670de0b6b3a7640000611fac88670d99a8cec7e200006128be565b6121c1565b6116a9565b9695505050505050565b6001600160a01b0381166000908152603e602052604081205480611fe8576000915050610a9f565b600080611ff6600184612940565b905060005b60808110156120b857818310612010576120b8565b6000600261201e84866128be565b6120299060016128be565b6120339190612901565b6001600160a01b0388166000908152603e602052604090208054919250908290811061206f57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b039081169089161115612097578093506120a5565b6120a2600182612940565b92505b50806120b0816129b8565b915050611ffb565b509095945050505050565b6001600160a01b0381166000908152603e6020526040812054806120eb576000915050610730565b6000806120f9600184612940565b905060005b60808110156121b757818310612113576121b7565b6000600261212184866128be565b61212c9060016128be565b6121369190612901565b6001600160a01b0388166000908152603e602052604090208054919250908290811061217257634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160401b0316421115612196578093506121a4565b6121a1600182612940565b92505b50806121af816129b8565b9150506120fe565b5090949350505050565b60008183116121d05781610dfb565b5090919050565b603354600160a01b900460ff166122305760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108da565b6033805460ff60a01b191690556001600160a01b038216600090815260386020526040812080548392906122659084906128be565b909155506122a090506001600160a01b037f000000000000000000000000fe842e95f8911dcc21c943a1daa4bd641a1381c616333084612503565b50506033805460ff60a01b1916600160a01b179055565b600061230c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661253b9092919063ffffffff16565b80519091501561084b578080602001905181019061232a91906127fe565b61084b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108da565b60008161239857506000610730565b816001600160801b82106123b15760809190911c9060401b5b600160401b82106123c75760409190911c9060201b5b64010000000082106123de5760209190911c9060101b5b6201000082106123f35760109190911c9060081b5b61010082106124075760089190911c9060041b5b6010821061241a5760049190911c9060021b5b600882106124265760011b5b60016124328286612901565b61243c90836128be565b901c9050600161244c8286612901565b61245690836128be565b901c905060016124668286612901565b61247090836128be565b901c905060016124808286612901565b61248a90836128be565b901c9050600161249a8286612901565b6124a490836128be565b901c905060016124b48286612901565b6124be90836128be565b901c905060016124ce8286612901565b6124d890836128be565b901c905060006124e88286612901565b90508082106124f757806124f9565b815b9350505050610730565b6040516001600160a01b03808516602483015283166044820152606481018290526108289085906323b872dd60e01b90608401611ba6565b6060611c91848460008585843b6125945760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108da565b600080866001600160a01b031685876040516125b0919061286f565b60006040518083038185875af1925050503d80600081146125ed576040519150601f19603f3d011682016040523d82523d6000602084013e6125f2565b606091505b509150915061260282828661260d565b979650505050505050565b6060831561261c575081610dfb565b82511561262c5782518084602001fd5b8160405162461bcd60e51b81526004016108da919061288b565b82805461265290612983565b90600052602060002090601f01602090048101928261267457600085556126ba565b82601f1061268d57805160ff19168380011785556126ba565b828001600101855582156126ba579182015b828111156126ba57825182559160200191906001019061269f565b50611d909291505b80821115611d9057600081556001016126c2565b60008083601f8401126126e7578182fd5b5081356001600160401b038111156126fd578182fd5b60208301915083602082850101111561271557600080fd5b9250929050565b60006020828403121561272d578081fd5b8135610dfb816129e9565b600060208284031215612749578081fd5b8151610dfb816129e9565b60008060008060006060868803121561276b578081fd5b8535612776816129e9565b945060208601356001600160401b0380821115612791578283fd5b61279d89838a016126d6565b909650945060408801359150808211156127b5578283fd5b506127c2888289016126d6565b969995985093965092949392505050565b600080604083850312156127e5578182fd5b82356127f0816129e9565b946020939093013593505050565b60006020828403121561280f578081fd5b81518015158114610dfb578182fd5b60006020828403121561282f578081fd5b5035919050565b600060208284031215612847578081fd5b5051919050565b60008060408385031215612860578182fd5b50508035926020909101359150565b60008251612881818460208701612957565b9190910192915050565b60006020825282518060208401526128aa816040850160208701612957565b601f01601f19169190910160400192915050565b600082198211156128d1576128d16129d3565b500190565b60006001600160401b038083168185168083038211156128f8576128f86129d3565b01949350505050565b60008261291c57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161561293b5761293b6129d3565b500290565b600082821015612952576129526129d3565b500390565b60005b8381101561297257818101518382015260200161295a565b838111156108285750506000910152565b60028104600182168061299757607f821691505b602082108114156116b857634e487b7160e01b600052602260045260246000fd5b60006000198214156129cc576129cc6129d3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146129fe57600080fd5b5056fea2646970667358221220990c0b652b36ef5f6cad2b869241b1ed7f2e26644ceda9c0764f38cede57a09564736f6c63430008020033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3000000000000000000000000fe842e95f8911dcc21c943a1daa4bd641a1381c6000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd35920000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000009000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd2
-----Decoded View---------------
Arg [0] : _nexus (address): 0xAFcE80b19A8cE13DEc0739a1aaB7A028d6845Eb3
Arg [1] : _stakingToken (address): 0xfE842e95f8911dcc21c943a1dAA4bd641a1381c6
Arg [2] : _boostDirector (address): 0xBa05FD2f20AE15B0D3f20DDc6870FeCa6ACd3592
Arg [3] : _priceCoeff (uint256): 1000000000000000000
Arg [4] : _coeff (uint256): 9
Arg [5] : _rewardsToken (address): 0xa3BeD4E1c75D00fa6f4E5E6922DB7261B5E9AcD2
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
Arg [1] : 000000000000000000000000fe842e95f8911dcc21c943a1daa4bd641a1381c6
Arg [2] : 000000000000000000000000ba05fd2f20ae15b0d3f20ddc6870feca6acd3592
Arg [3] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [5] : 000000000000000000000000a3bed4e1c75d00fa6f4e5e6922db7261b5e9acd2
Deployed Bytecode Sourcemap
49918:20802:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63782:372;;;;;;:::i;:::-;;:::i;:::-;;;11670:25:1;;;11658:2;11643:18;63782:372:0;;;;;;;;37642:91;;;:::i;:::-;;;;;;;:::i;51240:43::-;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;51240:43:0;;;;;;-1:-1:-1;;;;;12471:31:1;;;12453:50;;12441:2;12426:18;51240:43:0;12408:101:1;38528:118:0;;;;;;:::i;:::-;-1:-1:-1;;;;;38616:22:0;38589:7;38616:22;;;:12;:22;;;;;;;38528:118;38033:98;38104:19;;38033:98;;13385:142;;;;;;:::i;:::-;;:::i;:::-;;50504:40;;50538:6;50504:40;;57188:246;;;;;;:::i;:::-;;:::i;57577:180::-;;;;;;:::i;:::-;;:::i;37844:84::-;;;37918:2;13072:36:1;;13060:2;13045:18;37844:84:0;13027:87:1;58477:209:0;;;:::i;36799:35::-;;;;;69878:839;;;;;;:::i;:::-;;:::i;12686:33::-;;;;;-1:-1:-1;;;;;12686:33:0;;;;;;-1:-1:-1;;;;;3546:32:1;;;3528:51;;3516:2;3501:18;12686:33:0;3483:102:1;50713:37:0;;50745:5;50713:37;;58986:208;;;;;;:::i;:::-;;:::i;51186:47::-;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;12767:15:1;;;12749:34;;12819:15;;;;12814:2;12799:18;;12792:43;-1:-1:-1;;;;;12871:47:1;12851:18;;;12844:75;12700:2;12685:18;51186:47:0;12667:258:1;38820:148:0;;;;;;:::i;:::-;;:::i;61472:104::-;61556:12;61472:104;;38272:119;;;;;;:::i;:::-;-1:-1:-1;;;;;38357:26:0;38330:7;38357:26;;;:16;:26;;;;;;;38272:119;36196:36;;;;;50883:25;;;;;;61673:146;;;:::i;50608:41::-;;50641:8;50608:41;;52103:315;;;;;;:::i;:::-;;:::i;64556:394::-;;;;;;:::i;:::-;;:::i;:::-;;;;12187:25:1;;;12243:2;12228:18;;12221:34;;;;12271:18;;;12264:34;12175:2;12160:18;64556:394:0;12142:162:1;37741:95:0;;;:::i;8631:29::-;;;;;55854:186;;;;;;:::i;:::-;;:::i;56266:214::-;;;;;;:::i;:::-;;:::i;36239:45::-;;;;;57909:355;;;:::i;51104:44::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;51104:44:0;;;;-1:-1:-1;;;51104:44:0;;;;-1:-1:-1;;;;;51104:44:0;;;;-1:-1:-1;;;51104:44:0;;;;;;;;;-1:-1:-1;;;;;11304:15:1;;;11286:34;;11356:15;;;;11351:2;11336:18;;11329:43;-1:-1:-1;;;;;11445:15:1;;;11425:18;;;11418:43;;;;11497:15;11492:2;11477:18;;11470:43;11220:3;11205:19;51104:44:0;11187:332:1;50954:29:0;;;;;;62045:164;;;:::i;59274:180::-;;;;;;:::i;:::-;;:::i;50459:36::-;;;;;51062:35;;;;;;56712:245;;;:::i;50803:27::-;;;;;;36741:35;;;;;63782:372;-1:-1:-1;;;;;63931:18:0;;63846:7;63931:18;;;:8;:18;;;;;:37;63846:7;;63886:124;;63908:8;;-1:-1:-1;;;;;63931:37:0;63983:16;:14;:16::i;:::-;63886:7;:124::i;:::-;63866:144;-1:-1:-1;64021:27:0;64051:29;63866:144;50745:5;64051:21;:29::i;:::-;-1:-1:-1;;;;;64120:18:0;;;;;;:8;:18;;;;;:26;64021:59;;-1:-1:-1;64098:48:0;;-1:-1:-1;;;64120:26:0;;-1:-1:-1;;;;;64120:26:0;64021:59;64098:48;:::i;:::-;64091:55;;;;63782:372;;;;:::o;37642:91::-;37687:13;37720:5;37713:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37642:91;:::o;13385:142::-;9065:15;:13;:15::i;:::-;13479:18:::1;:40:::0;;-1:-1:-1;;;;;;13479:40:0::1;-1:-1:-1::0;;;;;13479:40:0;;;::::1;::::0;;;::::1;::::0;;13385:142::o;57188:246::-;57291:10;52895:23;52909:8;52895:13;:23::i;:::-;57324:10:::1;38589:7:::0;38616:22;;;:12;:22;;;;;;57352:35:::2;::::0;57362:24:::2;57352:9;:35::i;:::-;57398:28;57412:6;57420:5;57398:13;:28::i;:::-;55555:19:::1;55565:8;55555:9;:19::i;:::-;52929:1;57188:246:::0;;;:::o;57577:180::-;57670:10;52895:23;52909:8;52895:13;:23::i;:::-;57703:10:::1;57731:18:::2;57741:7;57731:9;:18::i;:::-;55555:19:::1;55565:8;55555:9;:19::i;:::-;52929:1;57577:180:::0;;:::o;58477:209::-;58532:10;52895:23;52909:8;52895:13;:23::i;:::-;58556:10:::1;58580:13:::2;58595:12:::0;58611:28:::2;58628:10;58611:16;:28::i;:::-;58579:60;;;;58652:26;58666:5;58673:4;58652:13;:26::i;:::-;55543:1;;55555:19:::1;55565:8;55555:9;:19::i;:::-;52929:1;58477:209:::0;:::o;69878:839::-;13139:18;;-1:-1:-1;;;;;13139:18:0;13125:10;:32;13117:77;;;;-1:-1:-1;;;13117:77:0;;6624:2:1;13117:77:0;;;6606:21:1;;;6643:18;;;6636:30;6702:34;6682:18;;;6675:62;6754:18;;13117:77:0;;;;;;;;;70021:1:::1;52895:23;52909:8;52895:13;:23::i;:::-;70059:4:::2;70049:7;:14;70041:71;;;::::0;-1:-1:-1;;;70041:71:0;;5868:2:1;70041:71:0::2;::::0;::::2;5850:21:1::0;5907:2;5887:18;;;5880:30;5946:34;5926:18;;;5919:62;-1:-1:-1;;;5997:18:1;;;5990:42;6049:19;;70041:71:0::2;5840:234:1::0;70041:71:0::2;70246:12;::::0;70147:15:::2;::::0;70231:27;::::2;70227:356;;70288:18;50538:6;70288:7:::0;:18:::2;:::i;:::-;70275:10;:31:::0;70227:356:::2;;;70410:17;70445:11;70430:12;;:26;;;;:::i;:::-;70410:46;;70471:16;70502:10;;70490:9;:22;;;;:::i;:::-;70471:41:::0;-1:-1:-1;50538:6:0::2;70541:18;70471:41:::0;70541:7;:18:::2;:::i;:::-;70540:31;;;;:::i;:::-;70527:10;:44:::0;-1:-1:-1;;70227:356:0::2;70595:14;:28:::0;;;70649:22:::2;50538:6;70612:11:::0;70649:22:::2;:::i;:::-;70634:12;:37:::0;70689:20:::2;::::0;11670:25:1;;;70689:20:0::2;::::0;11658:2:1;11643:18;70689:20:0::2;;;;;;;52929:1;13205::::1;69878:839:::0;:::o;58986:208::-;59097:10;52895:23;52909:8;52895:13;:23::i;:::-;59130:10:::1;59158:28:::2;59172:6;59180:5;59158:13;:28::i;51186:47::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;51186:47:0;;;;-1:-1:-1;;;;51186:47:0;;;;-1:-1:-1;;;;51186:47:0;;-1:-1:-1;;;;;51186:47:0;;:::o;38820:148::-;-1:-1:-1;;;;;38616:22:0;;38877:7;38616:22;;;:12;:22;;;;;;;;;38357:16;:26;;;;;;38904:56;;:32;:56::i;:::-;38897:63;38820:148;-1:-1:-1;;38820:148:0:o;61673:146::-;61739:7;61766:45;61781:15;61798:12;;61766:14;:45::i;:::-;61759:52;;61673:146;:::o;52103:315::-;42263:12;;;;;;;;:31;;-1:-1:-1;43176:4:0;43243:17;43288:7;42279:15;42263:47;;;-1:-1:-1;42299:11:0;;;;42298:12;42263:47;42241:143;;;;-1:-1:-1;;;42241:143:0;;9322:2:1;42241:143:0;;;9304:21:1;9361:2;9341:18;;;9334:30;9400:34;9380:18;;;9373:62;-1:-1:-1;;;9451:18:1;;;9444:44;9505:19;;42241:143:0;9294:236:1;42241:143:0;42397:19;42420:12;;;;;;42419:13;42443:99;;;;42478:12;:19;;-1:-1:-1;;;;42478:19:0;;;;;42512:18;42493:4;42512:18;;;42443:99;52272:74:::1;52326:19;52272:53;:74::i;:::-;52357:53;52389:8;;52357:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;52357:53:0::1;::::0;;::::1;;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;-1:-1:-1;52399:10:0;;-1:-1:-1;52399:10:0;;;;52357:53;::::1;52399:10:::0;;;;52357:53;::::1;;::::0;::::1;::::0;;;;-1:-1:-1;52357:31:0::1;::::0;-1:-1:-1;;;52357:53:0:i:1;:::-;42572:14:::0;42568:67;;;42618:5;42603:20;;-1:-1:-1;;42603:20:0;;;42568:67;52103:315;;;;;;:::o;64556:394::-;64682:14;64711:13;64739:12;64795:26;64812:8;64795:16;:26::i;:::-;64779:42;;-1:-1:-1;64779:42:0;-1:-1:-1;64833:16:0;64855:40;64873:8;64779:42;;64855:17;:40::i;:::-;64832:63;;;64926:16;64933:8;64926:6;:16::i;:::-;64915:27;;:8;:27;:::i;:::-;64906:36;;64556:394;;;;;;:::o;37741:95::-;37788:13;37821:7;37814:14;;;;;:::i;55854:186::-;55944:10;52895:23;52909:8;52895:13;:23::i;:::-;55977:10:::1;56005:27:::2;56012:10;56024:7;56005:6;:27::i;56266:214::-:0;56378:12;52895:23;52909:8;52895:13;:23::i;:::-;56413:12:::1;56443:29:::2;56450:12;56464:7;56443:6;:29::i;57909:355::-:0;57963:10;52895:23;52909:8;52895:13;:23::i;:::-;57987:10:::1;58010:16:::2;58029:20:::0;;;:8:::2;:20;::::0;;;;:28;;-1:-1:-1;;;;;58068:32:0;;::::2;::::0;;;-1:-1:-1;;;58029:28:0;::::2;;58117:12:::0;;58113:144:::2;;58146:47;-1:-1:-1::0;;;;;58146:12:0::2;:25;58172:10;58184:8:::0;58146:25:::2;:47::i;:::-;58213:32;::::0;11670:25:1;;;58224:10:0::2;::::0;58213:32:::2;::::0;11658:2:1;11643:18;58213:32:0::2;;;;;;;58113:144;55543:1;55555:19:::1;55565:8;55555:9;:19::i;62045:164::-:0;62101:7;62122:23;62151:17;:15;:17::i;:::-;-1:-1:-1;62121:47:0;-1:-1:-1;;62045:164:0;:::o;59274:180::-;59369:8;52895:23;52909:8;52895:13;:23::i;:::-;59431:15:::2;::::0;59400:8;;-1:-1:-1;;;;;59431:15:0;::::2;::::0;::::2;::::0;;;::::2;55555:19:::1;55565:8;55555:9;:19::i;56712:245::-:0;56759:10;52895:23;52909:8;52895:13;:23::i;:::-;56783:10:::1;38589:7:::0;38616:22;;;:12;:22;;;;;;56806:35:::2;::::0;56816:24:::2;38528:118:::0;56806:35:::2;56853:13;56868:12:::0;56884:28:::2;56901:10;56884:16;:28::i;65021:697::-:0;65178:7;;65291:48;65316:23;65291:22;:48;:::i;:::-;65265:74;-1:-1:-1;65431:20:0;65427:61;;65475:1;65468:8;;;;;65427:61;65558:21;65582:48;65614:15;65582:19;65592:8;-1:-1:-1;;;;;38357:26:0;38330:7;38357:26;;;:16;:26;;;;;;;38272:119;65582:19;:31;;:48::i;:::-;65558:72;-1:-1:-1;;;65021:697:0;;;;;;:::o;28935:135::-;29001:7;29028:34;29045:1;29048;27309:4;29028:16;:34::i;9108:121::-;9180:11;:9;:11::i;:::-;-1:-1:-1;;;;;9166:25:0;:10;-1:-1:-1;;;;;9166:25:0;;9158:63;;;;-1:-1:-1;;;9158:63:0;;8215:2:1;9158:63:0;;;8197:21:1;8254:2;8234:18;;;8227:30;8293:27;8273:18;;;8266:55;8338:18;;9158:63:0;8187:175:1;9158:63:0;9108:121::o;52950:2435::-;53033:15;53011:19;53082:30;53033:15;53082:17;:30::i;:::-;53059:53;;53161:25;53188:26;53218:17;:15;:17::i;:::-;53160:75;;-1:-1:-1;53160:75:0;-1:-1:-1;53320:21:0;;53316:2062;;53358:20;:40;;;53413:14;:35;;;-1:-1:-1;;;;;53531:22:0;;;53527:1648;;-1:-1:-1;;;;;53597:18:0;;53574:20;53597:18;;;:8;:18;;;;;;;;53574:41;;;;;;;;;-1:-1:-1;;;;;53574:41:0;;;;;;-1:-1:-1;;;53574:41:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;53574:41:0;;;;;;;;;;-1:-1:-1;;;53574:41:0;;;;;;;;;;:20;53652:61;;53606:8;;53695:17;53652:7;:61::i;:::-;53634:79;-1:-1:-1;53911:11:0;;53907:1253;;53947:16;53966:27;:7;50745:5;53966:19;:27::i;:::-;53947:46;-1:-1:-1;54016:14:0;54033:18;53947:46;54033:7;:18;:::i;:::-;54016:35;;54076:11;:21;54088:8;-1:-1:-1;;;;;54076:21:0;-1:-1:-1;;;;;54076:21:0;;;;;;;;;;;;54129:291;;;;;;;;54174:43;54201:4;:15;;;-1:-1:-1;;;;;54192:24:0;50641:8;54192:24;;;;:::i;:::-;54174:17;:43::i;:::-;-1:-1:-1;;;;;54129:291:0;;;;;54256:39;54274:20;54283:11;50641:8;54274:20;:::i;54256:39::-;-1:-1:-1;;;;;54129:291:0;;;;;54332:60;54375:4;:15;;;-1:-1:-1;;;;;54361:29:0;:11;:29;;;;:::i;:::-;54351:40;;:6;:40;:::i;:::-;54332:18;:60::i;:::-;-1:-1:-1;;;;;54129:291:0;;;;;;54076:367;;;;;;;-1:-1:-1;54076:367:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;54076:367:0;-1:-1:-1;;;;;54076:367:0;;;-1:-1:-1;;;54076:367:0;-1:-1:-1;;;;54076:367:0;;;;-1:-1:-1;;54076:367:0;;;;;;;;;;;;;;;;;;;;;;54489:308;;;;;;;;;54545:37;54564:17;54545:18;:37::i;:::-;-1:-1:-1;;;;;54489:308:0;;;;;54618:43;54648:4;:12;;;-1:-1:-1;;;;;54637:23:0;:8;:23;;;;:::i;54618:43::-;-1:-1:-1;;;;;54489:308:0;;;;;54700:13;-1:-1:-1;;;;;54489:308:0;;;;;54753:4;:16;;;54772:1;54753:20;;;;:::i;:::-;-1:-1:-1;;;;;54489:308:0;;;;;;-1:-1:-1;;;;;54468:18:0;;;;;;:8;:18;;;;;;;;;:329;;;;;;;;-1:-1:-1;;;;;54468:329:0;;;-1:-1:-1;;;54468:329:0;;;;-1:-1:-1;;;;;;54468:329:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;54468:329:0;-1:-1:-1;;;;54468:329:0;;;;-1:-1:-1;;54468:329:0;;;;;;;;;;;-1:-1:-1;53907:1253:0;;-1:-1:-1;53907:1253:0;;54867:273;;;;;;;;54923:37;54942:17;54923:18;:37::i;:::-;-1:-1:-1;;;;;54867:273:0;;;;;;54996:12;;;;54867:273;;;;;;-1:-1:-1;;;;;54867:273:0;;;;;;;;;;;;55100:16;;;;54867:273;;;;;;;;;-1:-1:-1;;;;;54846:18:0;;-1:-1:-1;54846:18:0;;;:8;:18;;;;;:294;;;;;;;;;;-1:-1:-1;;;54846:294:0;;;;-1:-1:-1;;;;;;54846:294:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;54846:294:0;-1:-1:-1;;;;54846:294:0;;;;-1:-1:-1;;54846:294:0;;;;;;;;;;;;;;53907:1253;53527:1648;;;53316:2062;;;-1:-1:-1;;;;;55196:22:0;;;55192:186;;-1:-1:-1;;;;;55321:18:0;;;;;;:8;:18;;;;;:29;;:45;;-1:-1:-1;;55321:45:0;-1:-1:-1;;;;;55321:45:0;;;;;55192:186;52950:2435;;;;;:::o;61104:183::-;61178:1;61168:7;:11;61160:41;;;;-1:-1:-1;;;61160:41:0;;8569:2:1;61160:41:0;;;8551:21:1;8608:2;8588:18;;;8581:30;-1:-1:-1;;;8627:18:1;;;8620:47;8684:18;;61160:41:0;8541:167:1;61160:41:0;61212:21;61225:7;61212:12;:21::i;:::-;61249:30;;11670:25:1;;;61259:10:0;;61249:30;;11658:2:1;11643:18;61249:30:0;;;;;;;61104:183;:::o;59885:528::-;59960:17;59979:21;60004:44;60022:10;60034:6;60042:5;60004:17;:44::i;:::-;60069:10;60059:21;;;;:9;:21;;;;;;;;:45;;-1:-1:-1;;60059:45:0;-1:-1:-1;;;;;60059:45:0;;;;;60136:8;:20;;;;;:28;;-1:-1:-1;;;;;60175:32:0;;;;;;59959:89;;-1:-1:-1;60059:45:0;;-1:-1:-1;;;;60136:28:0;;;;;60236:20;60136:28;59959:89;60236:20;:::i;:::-;60220:36;-1:-1:-1;60273:9:0;;60269:137;;60299:44;-1:-1:-1;;;;;60299:12:0;:25;60325:10;60337:5;60299:25;:44::i;:::-;60365:29;;11670:25:1;;;60376:10:0;;60365:29;;11658:2:1;11643:18;60365:29:0;;;;;;;59885:528;;;;;;:::o;39890:1132::-;-1:-1:-1;;;;;39968:22:0;;39947:18;39968:22;;;:12;:22;;;;;;;;;40026:16;:26;;;;;;39968:22;;36685:4;;;40227:23;40240:10;39968:22;40227:23;:::i;:::-;40226:32;;;;:::i;:::-;40202:56;;36537:4;40273:13;:28;40269:183;;40341:34;;-1:-1:-1;;;40341:34:0;;-1:-1:-1;;;;;3546:32:1;;;40341:34:0;;;3528:51:1;40318:20:0;;40341:13;:24;;;;;;3501:18:1;;40341:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40318:57;;40398:42;40412:13;40427:12;40398:13;:42::i;:::-;40390:50;;40269:183;;40464:25;40492:29;:10;40515:5;40492:22;:29::i;:::-;40464:57;;40559:14;40538:17;:35;40534:481;;40651:17;40634:14;40612:19;;:36;;;;:::i;:::-;:56;;;;:::i;:::-;40590:19;:78;-1:-1:-1;;;;;40683:26:0;;;;;;:16;:26;;;;;:46;;;40750:34;;;40746:258;;;-1:-1:-1;;;;;40810:66:0;;40827:1;40810:66;40841:34;40861:14;40841:17;:34;:::i;:::-;40810:66;;11670:25:1;;;11658:2;11643:18;40810:66:0;;;;;;;40746:258;;;40949:1;-1:-1:-1;;;;;40922:66:0;;;40953:34;40970:17;40953:14;:34;:::i;:::-;40922:66;;11670:25:1;;;11658:2;11643:18;40922:66:0;;;;;;;39890:1132;;;;;;:::o;65836:377::-;-1:-1:-1;;;;;65994:19:0;;65930:13;65994:19;;;:9;:19;;;;;;65930:13;;-1:-1:-1;;;;;65994:19:0;65930:13;66051:40;65994:19;66004:8;66051:19;:40::i;:::-;66026:65;;66102:21;66126:28;66145:8;66126:18;:28::i;:::-;66175:14;;-1:-1:-1;66102:52:0;;-1:-1:-1;;;65836:377:0;;;:::o;31065:195::-;31132:7;31251:1;31233:14;27309:4;31233:1;:14;:::i;:::-;31232:20;;;;:::i;33687:106::-;33745:7;33776:1;33772;:5;:13;;33784:1;33772:13;;;-1:-1:-1;33780:1:0;33687:106;-1:-1:-1;33687:106:0:o;37449:185::-;37540:28;26248:11;:18;;-1:-1:-1;;;;26248:18:0;-1:-1:-1;;;26248:18:0;;;25772:502;37540:28;37579:16;;;;:5;;:16;;;;;:::i;:::-;-1:-1:-1;37606:20:0;;;;:7;;:20;;;;;:::i;66299:1661::-;-1:-1:-1;;;;;66551:19:0;;66432:14;66551:19;;;:9;:19;;;;;;;;;66644:11;:21;;;;;:28;66432:14;;66506:15;;-1:-1:-1;;;;;66551:19:0;;;;66687:11;;:25;;;;-1:-1:-1;66702:10:0;;66687:25;66683:183;;;66733:13;;;:62;;-1:-1:-1;;;;;;66765:21:0;;;;;;:11;:21;;;;;:24;;:21;;;:24;;-1:-1:-1;;;66765:24:0;;;;;;;;;;;;;;;;;;:30;-1:-1:-1;;;;;66765:30:0;66750:45;;;66733:62;66729:126;;;66824:1;66827:11;66816:23;;;;;;;;;66729:126;66974:10;;66970:204;;-1:-1:-1;;;;;67040:21:0;;;;;;:11;:21;;;;;67062:10;67071:1;67062:6;:10;:::i;:::-;67040:33;;;;;;-1:-1:-1;;;67040:33:0;;;;;;;;;;;;;;;;;;:40;-1:-1:-1;;;;;;;;67040:40:0;;;;;67027:53;;;;;67001:161;;;;-1:-1:-1;;;67001:161:0;;6985:2:1;67001:161:0;;;6967:21:1;7024:2;7004:18;;;6997:30;7063:34;7043:18;;;7036:62;-1:-1:-1;;;7114:18:1;;;7107:44;7168:19;;67001:161:0;6957:236:1;67001:161:0;67186:13;67202:14;67210:6;67202:5;:14;:::i;:::-;:18;;67219:1;67202:18;:::i;:::-;67186:34;;67236:9;67231:488;67255:5;67251:1;:9;67231:488;;;67282:10;67295;67304:1;67295:6;:10;:::i;:::-;-1:-1:-1;;;;;67340:21:0;;67320:17;67340:21;;;:11;:21;;;;;:25;;67282:23;;-1:-1:-1;67320:17:0;;67282:23;;67340:25;;;;-1:-1:-1;;;67340:25:0;;;;;;;;;;;;;;;;;;67320:45;;;;;;;;67340:25;;;;67320:45;-1:-1:-1;;;;;67320:45:0;;;;;;-1:-1:-1;;;67320:45:0;;;;;;;;;;;;-1:-1:-1;;;67320:45:0;;-1:-1:-1;;;;;67320:45:0;;;;;;-1:-1:-1;67390:24:0;;;;;:51;;;67431:3;:10;;;-1:-1:-1;;;;;67418:23:0;:9;-1:-1:-1;;;;;67418:23:0;;;67390:51;67382:77;;;;-1:-1:-1;;;67382:77:0;;10095:2:1;67382:77:0;;;10077:21:1;10134:2;10114:18;;;10107:30;-1:-1:-1;;;10153:18:1;;;10146:43;10206:18;;67382:77:0;10067:163:1;67382:77:0;67476:15;67494:39;67509:3;:10;;;-1:-1:-1;;;;;67494:39:0;67521:11;67494:14;:39::i;:::-;67476:57;;67548:17;67568:36;67583:3;:9;;;-1:-1:-1;;;;;67568:36:0;67594:9;-1:-1:-1;;;;;67568:36:0;:14;:36::i;:::-;67548:56;;67619:17;67663:3;:8;;;-1:-1:-1;;;;;67639:32:0;67650:9;67640:7;:19;;;;:::i;:::-;67639:32;;;;:::i;:::-;67619:52;-1:-1:-1;67688:19:0;67619:52;67688:19;;:::i;:::-;;;67231:488;;;;;67262:3;;;;;:::i;:::-;;;;67231:488;;;-1:-1:-1;;;;;;67916:21:0;;;;;;:11;:21;;;;;:28;;67888:64;;67903:11;;67938:5;;67916:28;;;;-1:-1:-1;;;67916:28:0;;;;;;;;;;;;;;;;;;:35;-1:-1:-1;;;67916:35:0;;-1:-1:-1;;;;;67916:35:0;67888:14;:64::i;:::-;67870:82;;66299:1661;;;;;;;;;;;:::o;60679:300::-;60772:1;60762:7;:11;60754:38;;;;-1:-1:-1;;;60754:38:0;;6281:2:1;60754:38:0;;;6263:21:1;6320:2;6300:18;;;6293:30;-1:-1:-1;;;6339:18:1;;;6332:44;6393:18;;60754:38:0;6253:164:1;60754:38:0;-1:-1:-1;;;;;60811:26:0;;60803:66;;;;-1:-1:-1;;;60803:66:0;;5512:2:1;60803:66:0;;;5494:21:1;5551:2;5531:18;;;5524:30;5590:29;5570:18;;;5563:57;5637:18;;60803:66:0;5484:177:1;60803:66:0;60882:32;60892:12;60906:7;60882:9;:32::i;:::-;60930:41;;;11880:25:1;;;60960:10:0;11936:2:1;11921:18;;11914:60;-1:-1:-1;;;;;60930:41:0;;;;;11853:18:1;60930:41:0;;;;;;;60679:300;;:::o;22126:211::-;22270:58;;-1:-1:-1;;;;;4162:32:1;;22270:58:0;;;4144:51:1;4211:18;;;4204:34;;;22243:86:0;;22263:5;;-1:-1:-1;;;22293:23:0;4117:18:1;;22270:58:0;;;;-1:-1:-1;;22270:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;22270:58:0;-1:-1:-1;;;;;;22270:58:0;;;;;;;;;;22243:19;:86::i;62217:1285::-;62294:23;62319:33;62370:26;62399;:24;:26::i;:::-;62370:55;;62449:17;62490:14;;62469:18;:35;;;;:::i;:::-;62449:55;-1:-1:-1;62620:14:0;62616:96;;-1:-1:-1;62659:20:0;;;-1:-1:-1;62681:18:0;-1:-1:-1;62651:49:0;;62616:96;62800:31;62847:9;62834:10;;:22;;;;:::i;:::-;62800:56;;62880:14;62897:13;38104:19;;38033:98;;62897:13;62880:30;-1:-1:-1;63063:11:0;;;:43;;-1:-1:-1;63078:28:0;;63063:43;63059:125;;;63131:20;;63153:18;63123:49;;;;;;;;;;63059:125;63282:33;63318:44;:23;63355:6;63318:36;:44::i;:::-;63282:80;;63435:25;63412:20;;:48;;;;:::i;:::-;63404:77;-1:-1:-1;63462:18:0;;-1:-1:-1;;;;;62217:1285:0;;;:::o;29543:286::-;29663:7;29816:5;29807;29811:1;29807;:5;:::i;:::-;29806:15;;;;:::i;:::-;29799:22;29543:286;-1:-1:-1;;;;29543:286:0:o;10147:95::-;10191:7;10218:5;-1:-1:-1;;;;;10218:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;44223:178::-;44279:6;-1:-1:-1;;;44306:5:0;:13;44298:64;;;;-1:-1:-1;;;44298:64:0;;8915:2:1;44298:64:0;;;8897:21:1;8954:2;8934:18;;;8927:30;8993:34;8973:18;;;8966:62;-1:-1:-1;;;9044:18:1;;;9037:36;9090:19;;44298:64:0;8887:228:1;44298:64:0;-1:-1:-1;44387:5:0;44223:178::o;43741:183::-;43798:7;-1:-1:-1;;;43826:5:0;:14;43818:66;;;;-1:-1:-1;;;43818:66:0;;7400:2:1;43818:66:0;;;7382:21:1;7439:2;7419:18;;;7412:30;7478:34;7458:18;;;7451:62;-1:-1:-1;;;7529:18:1;;;7522:37;7576:19;;43818:66:0;7372:229:1;39436:172:0;26773:11;;-1:-1:-1;;;26773:11:0;;;;26765:55;;;;-1:-1:-1;;;26765:55:0;;10848:2:1;26765:55:0;;;10830:21:1;10887:2;10867:18;;;10860:30;10926:33;10906:18;;;10899:61;10977:18;;26765:55:0;10820:181:1;26765:55:0;26898:11;:19;;-1:-1:-1;;;;26898:19:0;;;39521:10:::1;26912:5:::0;39508:24;;;:12:::1;:24;::::0;;;;:35;;39536:7;;26912:5;39508:35:::1;::::0;39536:7;;39508:35:::1;:::i;:::-;::::0;;;-1:-1:-1;39554:46:0::1;::::0;-1:-1:-1;;;;;;39554:12:0::1;:25;39580:10;39592:7:::0;39554:25:::1;:46::i;:::-;-1:-1:-1::0;27078:11:0;:18;;-1:-1:-1;;;;27078:18:0;-1:-1:-1;;;27078:18:0;;;39436:172::o;41226:607::-;41345:13;41380:18;41376:40;;-1:-1:-1;36685:4:0;41400:16;;41376:40;41474:13;41490:31;41500:20;:14;41517:3;41500:20;:::i;:::-;41490:9;:31::i;:::-;41474:47;;41532:13;41548:16;41558:5;41548:9;:16::i;:::-;41532:32;-1:-1:-1;41575:19:0;41597:13;41532:32;41597:5;:13;:::i;:::-;41575:35;;41728:11;41701:2;41687:10;41645:39;41660:13;36584:9;41645:14;:39::i;:::-;:52;;;;:::i;:::-;41644:59;;;;:::i;:::-;41643:68;;41707:4;41643:68;:::i;:::-;41642:97;;;;:::i;:::-;41621:118;-1:-1:-1;41758:67:0;36637:4;41784:40;36685:4;41810:13;41621:118;36729:5;41810:13;:::i;:::-;41784:14;:40::i;:::-;41758:14;:67::i;:::-;41750:75;41226:607;-1:-1:-1;;;;;;41226:607:0:o;68067:692::-;-1:-1:-1;;;;;68228:21:0;;68183:13;68228:21;;;:11;:21;;;;;:28;68271:8;68267:22;;68288:1;68281:8;;;;;68267:22;68326:11;;68366:7;68372:1;68366:3;:7;:::i;:::-;68352:21;;68443:9;68438:293;68462:3;68458:1;:7;68438:293;;;68498:3;68491;:10;68487:21;;68503:5;;68487:21;68523:11;68555:1;68538:9;68544:3;68538;:9;:::i;:::-;:13;;68550:1;68538:13;:::i;:::-;68537:19;;;;:::i;:::-;-1:-1:-1;;;;;68588:21:0;;;;;;:11;:21;;;;;:26;;68523:33;;-1:-1:-1;68588:21:0;68523:33;;68588:26;;;;-1:-1:-1;;;68588:26:0;;;;;;;;;;;;;;;;;;:32;-1:-1:-1;;;;;68588:32:0;;;68575:45;;;;68571:149;;;68647:3;68641:9;;68571:149;;;68697:7;68703:1;68697:3;:7;:::i;:::-;68691:13;;68571:149;-1:-1:-1;68467:3:0;;;;:::i;:::-;;;;68438:293;;;-1:-1:-1;68748:3:0;;68067:692;-1:-1:-1;;;;;68067:692:0:o;68866:645::-;-1:-1:-1;;;;;68975:21:0;;68935:13;68975:21;;;:11;:21;;;;;:28;69018:8;69014:22;;69035:1;69028:8;;;;;69014:22;69073:11;;69113:7;69119:1;69113:3;:7;:::i;:::-;69099:21;;69190:9;69185:298;69209:3;69205:1;:7;69185:298;;;69245:3;69238;:10;69234:21;;69250:5;;69234:21;69270:11;69302:1;69285:9;69291:3;69285;:9;:::i;:::-;:13;;69297:1;69285:13;:::i;:::-;69284:19;;;;:::i;:::-;-1:-1:-1;;;;;69340:21:0;;;;;;:11;:21;;;;;:26;;69270:33;;-1:-1:-1;69340:21:0;69270:33;;69340:26;;;;-1:-1:-1;;;69340:26:0;;;;;;;;;;;;;;;;;;:32;-1:-1:-1;;;;;69340:32:0;69322:15;:50;69318:154;;;69399:3;69393:9;;69318:154;;;69449:7;69455:1;69449:3;:7;:::i;:::-;69443:13;;69318:154;-1:-1:-1;69214:3:0;;;;:::i;:::-;;;;69185:298;;;-1:-1:-1;69500:3:0;;68866:645;-1:-1:-1;;;;68866:645:0:o;33988:106::-;34046:7;34077:1;34073;:5;:13;;34085:1;34073:13;;;-1:-1:-1;34081:1:0;;33988:106;-1:-1:-1;33988:106:0:o;39104:212::-;26773:11;;-1:-1:-1;;;26773:11:0;;;;26765:55;;;;-1:-1:-1;;;26765:55:0;;10848:2:1;26765:55:0;;;10830:21:1;10887:2;10867:18;;;10860:30;10926:33;10906:18;;;10899:61;10977:18;;26765:55:0;10820:181:1;26765:55:0;26898:11;:19;;-1:-1:-1;;;;26898:19:0;;;-1:-1:-1;;;;;39195:26:0;::::1;26912:5:::0;39195:26;;;:12:::1;:26;::::0;;;;:37;;39225:7;;26912:5;39195:37:::1;::::0;39225:7;;39195:37:::1;:::i;:::-;::::0;;;-1:-1:-1;39243:65:0::1;::::0;-1:-1:-1;;;;;;39243:12:0::1;:29;39273:10;39293:4;39300:7:::0;39243:29:::1;:65::i;:::-;-1:-1:-1::0;;27078:11:0;:18;;-1:-1:-1;;;;27078:18:0;-1:-1:-1;;;27078:18:0;;;39104:212::o;24876:811::-;25300:23;25326:106;25368:4;25326:106;;;;;;;;;;;;;;;;;25334:5;-1:-1:-1;;;;;25326:27:0;;;:106;;;;;:::i;:::-;25447:17;;25300:132;;-1:-1:-1;25447:21:0;25443:237;;25602:10;25591:30;;;;;;;;;;;;:::i;:::-;25583:85;;;;-1:-1:-1;;;25583:85:0;;10437:2:1;25583:85:0;;;10419:21:1;10476:2;10456:18;;;10449:30;10515:34;10495:18;;;10488:62;-1:-1:-1;;;10566:18:1;;;10559:40;10616:19;;25583:85:0;10409:232:1;34640:1273:0;34688:9;34714:6;34710:1196;;-1:-1:-1;34729:1:0;34722:8;;34710:1196;34774:1;34802;-1:-1:-1;;;34822:41:0;;34818:119;;34891:3;34884:10;;;;;34919:2;34913:8;34818:119;-1:-1:-1;;;34955:2:0;:25;34951:102;;35008:2;35001:9;;;;;35035:2;35029:8;34951:102;35077:11;35071:2;:17;35067:94;;35116:2;35109:9;;;;;35143:2;35137:8;35067:94;35185:7;35179:2;:13;35175:89;;35220:2;35213:9;;;;;35247:1;35241:7;35175:89;35288:5;35282:2;:11;35278:86;;35321:1;35314:8;;;;;35347:1;35341:7;35278:86;35388:4;35382:2;:10;35378:85;;35420:1;35413:8;;;;;35446:1;35440:7;35378:85;35487:3;35481:2;:9;35477:57;;35517:1;35511:7;35477:57;35567:1;35557:5;35561:1;35557;:5;:::i;:::-;35553:9;;:1;:9;:::i;:::-;35552:16;;;-1:-1:-1;35602:1:0;35592:5;35552:16;35592:1;:5;:::i;:::-;35588:9;;:1;:9;:::i;:::-;35587:16;;;-1:-1:-1;35637:1:0;35627:5;35587:16;35627:1;:5;:::i;:::-;35623:9;;:1;:9;:::i;:::-;35622:16;;;-1:-1:-1;35672:1:0;35662:5;35622:16;35662:1;:5;:::i;:::-;35658:9;;:1;:9;:::i;:::-;35657:16;;;-1:-1:-1;35707:1:0;35697:5;35657:16;35697:1;:5;:::i;:::-;35693:9;;:1;:9;:::i;:::-;35692:16;;;-1:-1:-1;35742:1:0;35732:5;35692:16;35732:1;:5;:::i;:::-;35728:9;;:1;:9;:::i;:::-;35727:16;;;-1:-1:-1;35777:1:0;35767:5;35727:16;35767:1;:5;:::i;:::-;35763:9;;:1;:9;:::i;:::-;35762:16;;;-1:-1:-1;35830:10:0;35843:5;35762:16;35843:1;:5;:::i;:::-;35830:18;;35882:2;35878:1;:6;:15;;35891:2;35878:15;;;35887:1;35878:15;35863:31;;;;;;;22345:285;22543:68;;-1:-1:-1;;;;;3848:15:1;;;22543:68:0;;;3830:34:1;3900:15;;3880:18;;;3873:43;3932:18;;;3925:34;;;22489:133:0;;22523:5;;-1:-1:-1;;;22566:27:0;3765:18:1;;22543:68:0;3747:218:1;17444:229:0;17581:12;17613:52;17635:6;17643:4;17649:1;17652:12;17581;14882:20;;18864:60;;;;-1:-1:-1;;;18864:60:0;;9737:2:1;18864:60:0;;;9719:21:1;9776:2;9756:18;;;9749:30;9815:31;9795:18;;;9788:59;9864:18;;18864:60:0;9709:179:1;18864:60:0;18998:12;19012:23;19039:6;-1:-1:-1;;;;;19039:11:0;19059:5;19067:4;19039:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18997:75;;;;19090:52;19108:7;19117:10;19129:12;19090:17;:52::i;:::-;19083:59;18577:573;-1:-1:-1;;;;;;;18577:573:0:o;21283:777::-;21433:12;21462:7;21458:595;;;-1:-1:-1;21493:10:0;21486:17;;21458:595;21607:17;;:21;21603:439;;21870:10;21864:17;21931:15;21918:10;21914:2;21910:19;21903:44;21818:148;22013:12;22006:20;;-1:-1:-1;;;22006:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;:::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;4922:383::-;;5071:2;5060:9;5053:21;5103:6;5097:13;5146:6;5141:2;5130:9;5126:18;5119:34;5162:66;5221:6;5216:2;5205:9;5201:18;5196:2;5188:6;5184:15;5162:66;:::i;:::-;5289:2;5268:15;-1:-1:-1;;5264:29:1;5249:45;;;;5296:2;5245:54;;5043:262;-1:-1:-1;;5043:262:1:o;13119:128::-;;13190:1;13186:6;13183:1;13180:13;13177:2;;;13196:18;;:::i;:::-;-1:-1:-1;13232:9:1;;13167:80::o;13252:236::-;;-1:-1:-1;;;;;13364:2:1;13361:1;13357:10;13394:2;13391:1;13387:10;13425:3;13421:2;13417:12;13412:3;13409:21;13406:2;;;13433:18;;:::i;:::-;13469:13;;13299:189;-1:-1:-1;;;;13299:189:1:o;13493:217::-;;13559:1;13549:2;;-1:-1:-1;;;13584:31:1;;13638:4;13635:1;13628:15;13666:4;13591:1;13656:15;13549:2;-1:-1:-1;13695:9:1;;13539:171::o;13715:168::-;;13821:1;13817;13813:6;13809:14;13806:1;13803:21;13798:1;13791:9;13784:17;13780:45;13777:2;;;13828:18;;:::i;:::-;-1:-1:-1;13868:9:1;;13767:116::o;13888:125::-;;13956:1;13953;13950:8;13947:2;;;13961:18;;:::i;:::-;-1:-1:-1;13998:9:1;;13937:76::o;14018:258::-;14090:1;14100:113;14114:6;14111:1;14108:13;14100:113;;;14190:11;;;14184:18;14171:11;;;14164:39;14136:2;14129:10;14100:113;;;14231:6;14228:1;14225:13;14222:2;;;-1:-1:-1;;14266:1:1;14248:16;;14241:27;14071:205::o;14281:380::-;14366:1;14356:12;;14413:1;14403:12;;;14424:2;;14478:4;14470:6;14466:17;14456:27;;14424:2;14531;14523:6;14520:14;14500:18;14497:38;14494:2;;;14577:10;14572:3;14568:20;14565:1;14558:31;14612:4;14609:1;14602:15;14640:4;14637:1;14630:15;14666:135;;-1:-1:-1;;14726:17:1;;14723:2;;;14746:18;;:::i;:::-;-1:-1:-1;14793:1:1;14782:13;;14713:88::o;14806:127::-;14867:10;14862:3;14858:20;14855:1;14848:31;14898:4;14895:1;14888:15;14922:4;14919:1;14912:15;14938:131;-1:-1:-1;;;;;15013:31:1;;15003:42;;14993:2;;15059:1;15056;15049:12;14993:2;14983:86;:::o
Swarm Source
ipfs://990c0b652b36ef5f6cad2b869241b1ed7f2e26644ceda9c0764f38cede57a095
Loading...
Loading
Loading...
Loading
OVERVIEW
Logic contract for mStable Binance USD (BUSD) Feeder Pool Savings Vault (v-fPmUSD/BUSD).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.