Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
StakedAaveV3
Compiler Version
v0.8.21+commit.d9974bed
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; import {DistributionTypes} from '../lib/DistributionTypes.sol'; import {StakedTokenV3} from './StakedTokenV3.sol'; import {IGhoVariableDebtTokenTransferHook} from '../interfaces/IGhoVariableDebtTokenTransferHook.sol'; import {SafeCast} from '../lib/SafeCast.sol'; import {IStakedAaveV3} from '../interfaces/IStakedAaveV3.sol'; /** * @title StakedAaveV3 * @notice StakedTokenV3 with AAVE token as staked token * @author BGD Labs */ contract StakedAaveV3 is StakedTokenV3, IStakedAaveV3 { using SafeCast for uint256; uint256[1] private ______DEPRECATED_FROM_STK_AAVE_V3; /// @notice GHO debt token to be used in the _beforeTokenTransfer hook IGhoVariableDebtTokenTransferHook public ghoDebtToken; function REVISION() public pure virtual override returns (uint256) { return 6; } constructor( IERC20 stakedToken, IERC20 rewardToken, uint256 unstakeWindow, address rewardsVault, address emissionManager, uint128 distributionDuration ) StakedTokenV3( stakedToken, rewardToken, unstakeWindow, rewardsVault, emissionManager, distributionDuration ) { // brick initialize lastInitializedRevision = REVISION(); } /** * @dev Called by the proxy contract */ function initialize() external override initializer {} /// @inheritdoc IStakedAaveV3 function claimRewardsAndStake( address to, uint256 amount ) external override returns (uint256) { return _claimRewardsAndStakeOnBehalf(msg.sender, to, amount); } /// @inheritdoc IStakedAaveV3 function claimRewardsAndStakeOnBehalf( address from, address to, uint256 amount ) external override onlyClaimHelper returns (uint256) { return _claimRewardsAndStakeOnBehalf(from, to, amount); } /** * - On _transfer, it updates discount, rewards & delegation for both "from" and "to" * - On _mint, only for _to * - On _burn, only for _from * @param from token sender * @param to token recipient * @param fromBalanceBefore balance of the sender before transfer * @param toBalanceBefore balance of the recipient before transfer * @param amount amount of tokens sent */ function _afterTokenTransfer( address from, address to, uint256 fromBalanceBefore, uint256 toBalanceBefore, uint256 amount ) internal override { super._afterTokenTransfer( from, to, fromBalanceBefore, toBalanceBefore, amount ); address cachedGhoDebtToken = address(ghoDebtToken); if (cachedGhoDebtToken != address(0)) { _updateDiscountDistribution( cachedGhoDebtToken, from, to, fromBalanceBefore, toBalanceBefore, amount ); } } /// @notice Assembly implementation of the gas limited call to avoid return gas bomb, /// moreover call would also revert even inside try-catch block in Solidity 0.8.17 function _updateDiscountDistribution( address cachedGhoDebtToken, address from, address to, uint256 fromBalanceBefore, uint256 toBalanceBefore, uint256 amount ) internal { bytes4 selector = IGhoVariableDebtTokenTransferHook .updateDiscountDistribution .selector; uint256 gasLimit = 220_000; /// @solidity memory-safe-assembly assembly { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) mstore(ptr, selector) mstore(add(ptr, 0x04), from) mstore(add(ptr, 0x24), to) mstore(add(ptr, 0x44), fromBalanceBefore) mstore(add(ptr, 0x64), toBalanceBefore) mstore(add(ptr, 0x84), amount) let gasLeft := gas() if iszero(call(gasLimit, cachedGhoDebtToken, 0, ptr, 0xA4, 0, 0)) { if lt(div(mul(gasLeft, 63), 64), gasLimit) { returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.19; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; pragma experimental ABIEncoderV2; library DistributionTypes { struct AssetConfigInput { uint128 emissionPerSecond; uint256 totalStaked; address underlyingAsset; } struct UserStakeInput { address underlyingAsset; uint256 stakedByUser; uint256 totalStaked; } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; import {IERC20Metadata} from 'openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol'; import {BaseDelegation} from 'aave-token-v3/BaseDelegation.sol'; import {DistributionTypes} from '../lib/DistributionTypes.sol'; import {SafeERC20} from '../lib/SafeERC20.sol'; import {IAaveDistributionManager} from '../interfaces/IAaveDistributionManager.sol'; import {IStakedTokenV2} from '../interfaces/IStakedTokenV2.sol'; import {StakedTokenV2} from './StakedTokenV2.sol'; import {IStakedTokenV3} from '../interfaces/IStakedTokenV3.sol'; import {PercentageMath} from '../lib/PercentageMath.sol'; import {RoleManager} from '../utils/RoleManager.sol'; import {SafeCast} from '../lib/SafeCast.sol'; import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol'; /** * @title StakedTokenV3 * @notice Contract to stake Aave token, tokenize the position and get rewards, inheriting from a distribution manager contract * @author BGD Labs */ contract StakedTokenV3 is StakedTokenV2, IStakedTokenV3, RoleManager, IAaveDistributionManager, BaseDelegation { using SafeERC20 for IERC20; using PercentageMath for uint256; using SafeCast for uint256; using SafeCast for uint104; uint256 public constant SLASH_ADMIN_ROLE = 0; uint256 public constant COOLDOWN_ADMIN_ROLE = 1; uint256 public constant CLAIM_HELPER_ROLE = 2; uint216 public constant INITIAL_EXCHANGE_RATE = 1e18; uint256 public constant EXCHANGE_RATE_UNIT = 1e18; /// @notice lower bound to prevent spam & avoid exchangeRate issues // as returnFunds can be called permissionless an attacker could spam returnFunds(1) to produce exchangeRate snapshots making voting expensive uint256 public immutable LOWER_BOUND; // Reserved storage space to allow for layout changes in the future. uint256[6] private ______gap; /// @notice Seconds between starting cooldown and being able to withdraw uint256 internal _cooldownSeconds; /// @notice The maximum amount of funds that can be slashed at any given time uint256 internal _maxSlashablePercentage; /// @notice Mirror of latest snapshot value for cheaper access uint216 internal _currentExchangeRate; /// @notice Flag determining if there's an ongoing slashing event that needs to be settled bool public inPostSlashingPeriod; modifier onlySlashingAdmin() { require( msg.sender == getAdmin(SLASH_ADMIN_ROLE), 'CALLER_NOT_SLASHING_ADMIN' ); _; } modifier onlyCooldownAdmin() { require( msg.sender == getAdmin(COOLDOWN_ADMIN_ROLE), 'CALLER_NOT_COOLDOWN_ADMIN' ); _; } modifier onlyClaimHelper() { require( msg.sender == getAdmin(CLAIM_HELPER_ROLE), 'CALLER_NOT_CLAIM_HELPER' ); _; } constructor( IERC20 stakedToken, IERC20 rewardToken, uint256 unstakeWindow, address rewardsVault, address emissionManager, uint128 distributionDuration ) StakedTokenV2( stakedToken, rewardToken, unstakeWindow, rewardsVault, emissionManager, distributionDuration ) { // brick initialize lastInitializedRevision = REVISION(); uint256 decimals = IERC20Metadata(address(stakedToken)).decimals(); LOWER_BOUND = 10 ** decimals; } /** * @dev returns the revision of the implementation contract * @return The revision */ function REVISION() public pure virtual returns (uint256) { return 4; } /** * @dev returns the revision of the implementation contract * @return The revision */ function getRevision() internal pure virtual override returns (uint256) { return REVISION(); } /** * @dev Called by the proxy contract */ function initialize() external virtual initializer {} function _initialize( address slashingAdmin, address cooldownPauseAdmin, address claimHelper, uint256 maxSlashablePercentage, uint256 cooldownSeconds ) internal { InitAdmin[] memory initAdmins = new InitAdmin[](3); initAdmins[0] = InitAdmin(SLASH_ADMIN_ROLE, slashingAdmin); initAdmins[1] = InitAdmin(COOLDOWN_ADMIN_ROLE, cooldownPauseAdmin); initAdmins[2] = InitAdmin(CLAIM_HELPER_ROLE, claimHelper); _initAdmins(initAdmins); _setMaxSlashablePercentage(maxSlashablePercentage); _setCooldownSeconds(cooldownSeconds); _updateExchangeRate(INITIAL_EXCHANGE_RATE); } /// @inheritdoc IAaveDistributionManager function configureAssets( DistributionTypes.AssetConfigInput[] memory assetsConfigInput ) external override { require(msg.sender == EMISSION_MANAGER, 'ONLY_EMISSION_MANAGER'); for (uint256 i = 0; i < assetsConfigInput.length; i++) { assetsConfigInput[i].totalStaked = totalSupply(); } _configureAssets(assetsConfigInput); } /// @inheritdoc IStakedTokenV3 function previewStake(uint256 assets) public view returns (uint256) { return (assets * _currentExchangeRate) / EXCHANGE_RATE_UNIT; } /// @inheritdoc IStakedTokenV2 function stake( address to, uint256 amount ) external override(IStakedTokenV2, StakedTokenV2) { _stake(msg.sender, to, amount); } /// @inheritdoc IStakedTokenV3 function stakeWithPermit( uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external override { try IERC20WithPermit(address(STAKED_TOKEN)).permit( msg.sender, address(this), amount, deadline, v, r, s ) { // do nothing } catch (bytes memory) { // do nothing } _stake(msg.sender, msg.sender, amount); } /// @inheritdoc IStakedTokenV2 function cooldown() external override(IStakedTokenV2, StakedTokenV2) { _cooldown(msg.sender); } /// @inheritdoc IStakedTokenV3 function cooldownOnBehalfOf(address from) external override onlyClaimHelper { _cooldown(from); } function _cooldown(address from) internal { uint256 amount = balanceOf(from); require(amount != 0, 'INVALID_BALANCE_ON_COOLDOWN'); stakersCooldowns[from] = CooldownSnapshot({ timestamp: uint40(block.timestamp), amount: uint216(amount) }); emit Cooldown(from, amount); } /// @inheritdoc IStakedTokenV2 function redeem( address to, uint256 amount ) external override(IStakedTokenV2, StakedTokenV2) { _redeem(msg.sender, to, amount.toUint104()); } /// @inheritdoc IStakedTokenV3 function redeemOnBehalf( address from, address to, uint256 amount ) external override onlyClaimHelper { _redeem(from, to, amount.toUint104()); } /// @inheritdoc IStakedTokenV2 function claimRewards( address to, uint256 amount ) external override(IStakedTokenV2, StakedTokenV2) { _claimRewards(msg.sender, to, amount); } /// @inheritdoc IStakedTokenV3 function claimRewardsOnBehalf( address from, address to, uint256 amount ) external override onlyClaimHelper returns (uint256) { return _claimRewards(from, to, amount); } /// @inheritdoc IStakedTokenV3 function claimRewardsAndRedeem( address to, uint256 claimAmount, uint256 redeemAmount ) external override { _claimRewards(msg.sender, to, claimAmount); _redeem(msg.sender, to, redeemAmount.toUint104()); } /// @inheritdoc IStakedTokenV3 function claimRewardsAndRedeemOnBehalf( address from, address to, uint256 claimAmount, uint256 redeemAmount ) external override onlyClaimHelper { _claimRewards(from, to, claimAmount); _redeem(from, to, redeemAmount.toUint104()); } /// @inheritdoc IStakedTokenV3 function getExchangeRate() public view override returns (uint216) { return _currentExchangeRate; } /// @inheritdoc IStakedTokenV3 function previewRedeem( uint256 shares ) public view override returns (uint256) { return (EXCHANGE_RATE_UNIT * shares) / _currentExchangeRate; } /// @inheritdoc IStakedTokenV3 function slash( address destination, uint256 amount ) external override onlySlashingAdmin returns (uint256) { require(!inPostSlashingPeriod, 'PREVIOUS_SLASHING_NOT_SETTLED'); require(amount > 0, 'ZERO_AMOUNT'); uint256 currentShares = totalSupply(); uint256 balance = previewRedeem(currentShares); uint256 maxSlashable = balance.percentMul(_maxSlashablePercentage); if (amount > maxSlashable) { amount = maxSlashable; } require(balance - amount >= LOWER_BOUND, 'REMAINING_LT_MINIMUM'); inPostSlashingPeriod = true; _updateExchangeRate(_getExchangeRate(balance - amount, currentShares)); STAKED_TOKEN.safeTransfer(destination, amount); emit Slashed(destination, amount); return amount; } /// @inheritdoc IStakedTokenV3 function returnFunds(uint256 amount) external override { require(amount >= LOWER_BOUND, 'AMOUNT_LT_MINIMUM'); uint256 currentShares = totalSupply(); require(currentShares >= LOWER_BOUND, 'SHARES_LT_MINIMUM'); uint256 assets = previewRedeem(currentShares); _updateExchangeRate(_getExchangeRate(assets + amount, currentShares)); STAKED_TOKEN.safeTransferFrom(msg.sender, address(this), amount); emit FundsReturned(amount); } /// @inheritdoc IStakedTokenV3 function settleSlashing() external override onlySlashingAdmin { inPostSlashingPeriod = false; emit SlashingSettled(); } /// @inheritdoc IStakedTokenV3 function setMaxSlashablePercentage( uint256 percentage ) external override onlySlashingAdmin { _setMaxSlashablePercentage(percentage); } /// @inheritdoc IStakedTokenV3 function getMaxSlashablePercentage() external view override returns (uint256) { return _maxSlashablePercentage; } /// @inheritdoc IStakedTokenV3 function setCooldownSeconds( uint256 cooldownSeconds ) external onlyCooldownAdmin { _setCooldownSeconds(cooldownSeconds); } /// @inheritdoc IStakedTokenV3 function getCooldownSeconds() external view returns (uint256) { return _cooldownSeconds; } /// @inheritdoc IStakedTokenV3 function COOLDOWN_SECONDS() external view returns (uint256) { return _cooldownSeconds; } /** * @dev sets the max slashable percentage * @param percentage must be strictly lower 100% as otherwise the exchange rate calculation would result in 0 division */ function _setMaxSlashablePercentage(uint256 percentage) internal { require( percentage < PercentageMath.PERCENTAGE_FACTOR, 'INVALID_SLASHING_PERCENTAGE' ); _maxSlashablePercentage = percentage; emit MaxSlashablePercentageChanged(percentage); } /** * @dev sets the cooldown seconds * @param cooldownSeconds the new amount of cooldown seconds */ function _setCooldownSeconds(uint256 cooldownSeconds) internal { _cooldownSeconds = cooldownSeconds; emit CooldownSecondsChanged(cooldownSeconds); } /** * @dev claims the rewards for a specified address to a specified address * @param from The address of the from from which to claim * @param to Address to receive the rewards * @param amount Amount to claim * @return amount claimed */ function _claimRewards( address from, address to, uint256 amount ) internal returns (uint256) { require(amount != 0, 'INVALID_ZERO_AMOUNT'); uint256 newTotalRewards = _updateCurrentUnclaimedRewards( from, balanceOf(from), false ); uint256 amountToClaim = (amount > newTotalRewards) ? newTotalRewards : amount; require(amountToClaim != 0, 'INVALID_ZERO_AMOUNT'); stakerRewardsToClaim[from] = newTotalRewards - amountToClaim; REWARD_TOKEN.safeTransferFrom(REWARDS_VAULT, to, amountToClaim); emit RewardsClaimed(from, to, amountToClaim); return amountToClaim; } /** * @dev Claims an `amount` of `REWARD_TOKEN` and stakes. * @param from The address of the from from which to claim * @param to Address to stake to * @param amount Amount to claim * @return amount claimed */ function _claimRewardsAndStakeOnBehalf( address from, address to, uint256 amount ) internal returns (uint256) { require(REWARD_TOKEN == STAKED_TOKEN, 'REWARD_TOKEN_IS_NOT_STAKED_TOKEN'); uint256 userUpdatedRewards = _updateCurrentUnclaimedRewards( from, balanceOf(from), true ); uint256 amountToClaim = (amount > userUpdatedRewards) ? userUpdatedRewards : amount; if (amountToClaim != 0) { _claimRewards(from, address(this), amountToClaim); _stake(address(this), to, amountToClaim); } return amountToClaim; } /** * @dev Allows staking a specified amount of STAKED_TOKEN * @param to The address to receiving the shares * @param amount The amount of assets to be staked */ function _stake(address from, address to, uint256 amount) internal { require(!inPostSlashingPeriod, 'SLASHING_ONGOING'); require(amount != 0, 'INVALID_ZERO_AMOUNT'); uint256 balanceOfTo = balanceOf(to); uint256 accruedRewards = _updateUserAssetInternal( to, address(this), balanceOfTo, totalSupply() ); if (accruedRewards != 0) { stakerRewardsToClaim[to] = stakerRewardsToClaim[to] + accruedRewards; emit RewardsAccrued(to, accruedRewards); } uint256 sharesToMint = previewStake(amount); STAKED_TOKEN.safeTransferFrom(from, address(this), amount); _mint(to, sharesToMint.toUint104()); emit Staked(from, to, amount, sharesToMint); } /** * @dev Redeems staked tokens, and stop earning rewards * @param from Address to redeem from * @param to Address to redeem to * @param amount Amount to redeem */ function _redeem(address from, address to, uint104 amount) internal { require(amount != 0, 'INVALID_ZERO_AMOUNT'); CooldownSnapshot memory cooldownSnapshot = stakersCooldowns[from]; if (!inPostSlashingPeriod) { require( (block.timestamp >= cooldownSnapshot.timestamp + _cooldownSeconds), 'INSUFFICIENT_COOLDOWN' ); require( (block.timestamp - (cooldownSnapshot.timestamp + _cooldownSeconds) <= UNSTAKE_WINDOW), 'UNSTAKE_WINDOW_FINISHED' ); } uint256 balanceOfFrom = balanceOf(from); uint256 maxRedeemable = inPostSlashingPeriod ? balanceOfFrom : cooldownSnapshot.amount; require(maxRedeemable != 0, 'INVALID_ZERO_MAX_REDEEMABLE'); uint256 amountToRedeem = (amount > maxRedeemable) ? maxRedeemable : amount; _updateCurrentUnclaimedRewards(from, balanceOfFrom, true); uint256 underlyingToRedeem = previewRedeem(amountToRedeem); _burn(from, amountToRedeem.toUint104()); if (cooldownSnapshot.timestamp != 0) { if (cooldownSnapshot.amount - amountToRedeem == 0) { delete stakersCooldowns[from]; } else { stakersCooldowns[from].amount = stakersCooldowns[from].amount - amountToRedeem.toUint184(); } } IERC20(STAKED_TOKEN).safeTransfer(to, underlyingToRedeem); emit Redeem(from, to, underlyingToRedeem, amountToRedeem); } /** * @dev Updates the exchangeRate and emits events accordingly * @param newExchangeRate the new exchange rate */ function _updateExchangeRate(uint216 newExchangeRate) internal virtual { require(newExchangeRate != 0, 'ZERO_EXCHANGE_RATE'); _currentExchangeRate = newExchangeRate; emit ExchangeRateChanged(newExchangeRate); } /** * @dev calculates the exchange rate based on totalAssets and totalShares * @dev always rounds up to ensure 100% backing of shares by rounding in favor of the contract * @param totalAssets The total amount of assets staked * @param totalShares The total amount of shares * @return exchangeRate as 18 decimal precision uint216 */ function _getExchangeRate( uint256 totalAssets, uint256 totalShares ) internal pure returns (uint216) { return (((totalShares * EXCHANGE_RATE_UNIT) + totalAssets - 1) / totalAssets) .toUint216(); } function _transfer( address from, address to, uint256 amount ) internal override { uint256 balanceOfFrom = balanceOf(from); // Sender _updateCurrentUnclaimedRewards(from, balanceOfFrom, true); // Recipient if (from != to) { uint256 balanceOfTo = balanceOf(to); _updateCurrentUnclaimedRewards(to, balanceOfTo, true); CooldownSnapshot memory previousSenderCooldown = stakersCooldowns[from]; if (previousSenderCooldown.timestamp != 0) { // if cooldown was set and whole balance of sender was transferred - clear cooldown if (balanceOfFrom == amount) { delete stakersCooldowns[from]; } else if (balanceOfFrom - amount < previousSenderCooldown.amount) { stakersCooldowns[from].amount = uint216(balanceOfFrom - amount); } } } super._transfer(from, to, amount); } function _afterTokenTransfer( address from, address to, uint256 fromBalanceBefore, uint256 toBalanceBefore, uint256 amount ) internal virtual override { _delegationChangeOnTransfer( from, to, fromBalanceBefore, toBalanceBefore, amount ); } function _getDelegationState( address user ) internal view override returns (DelegationState memory) { DelegationAwareBalance memory userState = _balances[user]; return DelegationState({ delegatedPropositionBalance: userState.delegatedPropositionBalance, delegatedVotingBalance: userState.delegatedVotingBalance, delegationMode: userState.delegationMode }); } function _getBalance(address user) internal view override returns (uint256) { return balanceOf(user); } function getPowerCurrent( address user, GovernancePowerType delegationType ) public view override returns (uint256) { return (super.getPowerCurrent(user, delegationType) * EXCHANGE_RATE_UNIT) / getExchangeRate(); } function _setDelegationState( address user, DelegationState memory delegationState ) internal override { DelegationAwareBalance storage userState = _balances[user]; userState.delegatedPropositionBalance = delegationState .delegatedPropositionBalance; userState.delegatedVotingBalance = delegationState.delegatedVotingBalance; userState.delegationMode = delegationState.delegationMode; } function _incrementNonces(address user) internal override returns (uint256) { unchecked { // Does not make sense to check because it's not realistic to reach uint256.max in nonce return _nonces[user]++; } } function _getDomainSeparator() internal view override returns (bytes32) { return DOMAIN_SEPARATOR(); } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; interface IGhoVariableDebtTokenTransferHook { /** * @dev updates the discount when discount token is transferred * @dev Only callable by discount token * @param sender address of sender * @param recipient address of recipient * @param senderDiscountTokenBalance sender discount token balance * @param recipientDiscountTokenBalance recipient discount token balance * @param amount amount of discount token being transferred **/ function updateDiscountDistribution( address sender, address recipient, uint256 senderDiscountTokenBalance, uint256 recipientDiscountTokenBalance, uint256 amount ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @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 * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(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 * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(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 * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(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 * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "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 * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "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. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @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 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @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 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @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 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @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 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @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 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; import {IStakedTokenV3} from './IStakedTokenV3.sol'; import {IGhoVariableDebtTokenTransferHook} from './IGhoVariableDebtTokenTransferHook.sol'; interface IStakedAaveV3 is IStakedTokenV3 { /** * @dev Claims an `amount` of `REWARD_TOKEN` and stakes. * @param to Address to stake to * @param amount Amount to claim */ function claimRewardsAndStake( address to, uint256 amount ) external returns (uint256); /** * @dev Claims an `amount` of `REWARD_TOKEN` and stakes. Only the claim helper contract is allowed to call this function * @param from The address of the from from which to claim * @param to Address to stake to * @param amount Amount to claim */ function claimRewardsAndStakeOnBehalf( address from, address to, uint256 amount ) external returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.19; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ECDSA} from 'openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol'; import {SafeCast72} from './utils/SafeCast72.sol'; import {IGovernancePowerDelegationToken} from './interfaces/IGovernancePowerDelegationToken.sol'; import {DelegationMode} from './DelegationAwareBalance.sol'; /** * @notice The contract implements generic delegation functionality for the upcoming governance v3 * @author BGD Labs * @dev to make it's pluggable to any exising token it has a set of virtual functions * for simple access to balances and permit functionality * @dev ************ IMPORTANT SECURITY CONSIDERATION ************ * current version of the token can be used only with asset which has 18 decimals * and possible totalSupply lower then 4722366482869645213696, * otherwise at least POWER_SCALE_FACTOR should be adjusted !!! * ************************************************************* */ abstract contract BaseDelegation is IGovernancePowerDelegationToken { struct DelegationState { uint72 delegatedPropositionBalance; uint72 delegatedVotingBalance; DelegationMode delegationMode; } mapping(address => address) internal _votingDelegatee; mapping(address => address) internal _propositionDelegatee; /** @dev we assume that for the governance system delegation with 18 decimals of precision is not needed, * by this constant we reduce it by 10, to 8 decimals. * In case of Aave token this will allow to work with up to 47'223'664'828'696,45213696 total supply * If your token already have less then 10 decimals, please change it to appropriate. */ uint256 public constant POWER_SCALE_FACTOR = 1e10; bytes32 public constant DELEGATE_BY_TYPE_TYPEHASH = keccak256( 'DelegateByType(address delegator,address delegatee,uint8 delegationType,uint256 nonce,uint256 deadline)' ); bytes32 public constant DELEGATE_TYPEHASH = keccak256('Delegate(address delegator,address delegatee,uint256 nonce,uint256 deadline)'); /** * @notice returns eip-2612 compatible domain separator * @dev we expect that existing tokens, ie Aave, already have, so we want to reuse * @return domain separator */ function _getDomainSeparator() internal view virtual returns (bytes32); /** * @notice gets the delegation state of a user * @param user address * @return state of a user's delegation */ function _getDelegationState(address user) internal view virtual returns (DelegationState memory); /** * @notice returns the token balance of a user * @param user address * @return current nonce before increase */ function _getBalance(address user) internal view virtual returns (uint256); /** * @notice increases and return the current nonce of a user * @dev should use `return nonce++;` pattern * @param user address * @return current nonce before increase */ function _incrementNonces(address user) internal virtual returns (uint256); /** * @notice sets the delegation state of a user * @param user address * @param delegationState state of a user's delegation */ function _setDelegationState(address user, DelegationState memory delegationState) internal virtual; /// @inheritdoc IGovernancePowerDelegationToken function delegateByType(address delegatee, GovernancePowerType delegationType) external virtual override { _delegateByType(msg.sender, delegatee, delegationType); } /// @inheritdoc IGovernancePowerDelegationToken function delegate(address delegatee) external override { _delegateByType(msg.sender, delegatee, GovernancePowerType.VOTING); _delegateByType(msg.sender, delegatee, GovernancePowerType.PROPOSITION); } /// @inheritdoc IGovernancePowerDelegationToken function getDelegateeByType(address delegator, GovernancePowerType delegationType) external view override returns (address) { return _getDelegateeByType(delegator, _getDelegationState(delegator), delegationType); } /// @inheritdoc IGovernancePowerDelegationToken function getDelegates(address delegator) external view override returns (address, address) { DelegationState memory delegatorBalance = _getDelegationState(delegator); return ( _getDelegateeByType(delegator, delegatorBalance, GovernancePowerType.VOTING), _getDelegateeByType(delegator, delegatorBalance, GovernancePowerType.PROPOSITION) ); } /// @inheritdoc IGovernancePowerDelegationToken function getPowerCurrent(address user, GovernancePowerType delegationType) public view virtual override returns (uint256) { DelegationState memory userState = _getDelegationState(user); uint256 userOwnPower = uint8(userState.delegationMode) & (uint8(delegationType) + 1) == 0 ? _getBalance(user) : 0; uint256 userDelegatedPower = _getDelegatedPowerByType(userState, delegationType); return userOwnPower + userDelegatedPower; } /// @inheritdoc IGovernancePowerDelegationToken function getPowersCurrent(address user) external view override returns (uint256, uint256) { return ( getPowerCurrent(user, GovernancePowerType.VOTING), getPowerCurrent(user, GovernancePowerType.PROPOSITION) ); } /// @inheritdoc IGovernancePowerDelegationToken function metaDelegateByType( address delegator, address delegatee, GovernancePowerType delegationType, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external override { require(delegator != address(0), 'INVALID_OWNER'); //solium-disable-next-line require(block.timestamp <= deadline, 'INVALID_EXPIRATION'); bytes32 digest = ECDSA.toTypedDataHash( _getDomainSeparator(), keccak256( abi.encode( DELEGATE_BY_TYPE_TYPEHASH, delegator, delegatee, delegationType, _incrementNonces(delegator), deadline ) ) ); require(delegator == ECDSA.recover(digest, v, r, s), 'INVALID_SIGNATURE'); _delegateByType(delegator, delegatee, delegationType); } /// @inheritdoc IGovernancePowerDelegationToken function metaDelegate( address delegator, address delegatee, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external override { require(delegator != address(0), 'INVALID_OWNER'); //solium-disable-next-line require(block.timestamp <= deadline, 'INVALID_EXPIRATION'); bytes32 digest = ECDSA.toTypedDataHash( _getDomainSeparator(), keccak256( abi.encode(DELEGATE_TYPEHASH, delegator, delegatee, _incrementNonces(delegator), deadline) ) ); require(delegator == ECDSA.recover(digest, v, r, s), 'INVALID_SIGNATURE'); _delegateByType(delegator, delegatee, GovernancePowerType.VOTING); _delegateByType(delegator, delegatee, GovernancePowerType.PROPOSITION); } /** * @dev Modifies the delegated power of a `delegatee` account by type (VOTING, PROPOSITION). * Passing the impact on the delegation of `delegatee` account before and after to reduce conditionals and not lose * any precision. * @param impactOnDelegationBefore how much impact a balance of another account had over the delegation of a `delegatee` * before an action. * For example, if the action is a delegation from one account to another, the impact before the action will be 0. * @param impactOnDelegationAfter how much impact a balance of another account will have over the delegation of a `delegatee` * after an action. * For example, if the action is a delegation from one account to another, the impact after the action will be the whole balance * of the account changing the delegatee. * @param delegatee the user whom delegated governance power will be changed * @param delegationType the type of governance power delegation (VOTING, PROPOSITION) **/ function _governancePowerTransferByType( uint256 impactOnDelegationBefore, uint256 impactOnDelegationAfter, address delegatee, GovernancePowerType delegationType ) internal { if (delegatee == address(0)) return; if (impactOnDelegationBefore == impactOnDelegationAfter) return; // we use uint72, because this is the most optimal for AaveTokenV3 // To make delegated balance fit into uint72 we're decreasing precision of delegated balance by POWER_SCALE_FACTOR uint72 impactOnDelegationBefore72 = SafeCast72.toUint72( impactOnDelegationBefore / POWER_SCALE_FACTOR ); uint72 impactOnDelegationAfter72 = SafeCast72.toUint72( impactOnDelegationAfter / POWER_SCALE_FACTOR ); DelegationState memory delegateeState = _getDelegationState(delegatee); if (delegationType == GovernancePowerType.VOTING) { delegateeState.delegatedVotingBalance = delegateeState.delegatedVotingBalance - impactOnDelegationBefore72 + impactOnDelegationAfter72; } else { delegateeState.delegatedPropositionBalance = delegateeState.delegatedPropositionBalance - impactOnDelegationBefore72 + impactOnDelegationAfter72; } _setDelegationState(delegatee, delegateeState); } /** * @dev performs all state changes related delegation changes on transfer * @param from token sender * @param to token recipient * @param fromBalanceBefore balance of the sender before transfer * @param toBalanceBefore balance of the recipient before transfer * @param amount amount of tokens sent **/ function _delegationChangeOnTransfer( address from, address to, uint256 fromBalanceBefore, uint256 toBalanceBefore, uint256 amount ) internal { if (from == to) { return; } if (from != address(0)) { DelegationState memory fromUserState = _getDelegationState(from); uint256 fromBalanceAfter = fromBalanceBefore - amount; if (fromUserState.delegationMode != DelegationMode.NO_DELEGATION) { _governancePowerTransferByType( fromBalanceBefore, fromBalanceAfter, _getDelegateeByType(from, fromUserState, GovernancePowerType.VOTING), GovernancePowerType.VOTING ); _governancePowerTransferByType( fromBalanceBefore, fromBalanceAfter, _getDelegateeByType(from, fromUserState, GovernancePowerType.PROPOSITION), GovernancePowerType.PROPOSITION ); } } if (to != address(0)) { DelegationState memory toUserState = _getDelegationState(to); uint256 toBalanceAfter = toBalanceBefore + amount; if (toUserState.delegationMode != DelegationMode.NO_DELEGATION) { _governancePowerTransferByType( toBalanceBefore, toBalanceAfter, _getDelegateeByType(to, toUserState, GovernancePowerType.VOTING), GovernancePowerType.VOTING ); _governancePowerTransferByType( toBalanceBefore, toBalanceAfter, _getDelegateeByType(to, toUserState, GovernancePowerType.PROPOSITION), GovernancePowerType.PROPOSITION ); } } } /** * @dev Extracts from state and returns delegated governance power (Voting, Proposition) * @param userState the current state of a user * @param delegationType the type of governance power delegation (VOTING, PROPOSITION) **/ function _getDelegatedPowerByType( DelegationState memory userState, GovernancePowerType delegationType ) internal pure returns (uint256) { return POWER_SCALE_FACTOR * ( delegationType == GovernancePowerType.VOTING ? userState.delegatedVotingBalance : userState.delegatedPropositionBalance ); } /** * @dev Extracts from state and returns the delegatee of a delegator by type of governance power (Voting, Proposition) * - If the delegator doesn't have any delegatee, returns address(0) * @param delegator delegator * @param userState the current state of a user * @param delegationType the type of governance power delegation (VOTING, PROPOSITION) **/ function _getDelegateeByType( address delegator, DelegationState memory userState, GovernancePowerType delegationType ) internal view returns (address) { if (delegationType == GovernancePowerType.VOTING) { return /// With the & operation, we cover both VOTING_DELEGATED delegation and FULL_POWER_DELEGATED /// as VOTING_DELEGATED is equivalent to 01 in binary and FULL_POWER_DELEGATED is equivalent to 11 (uint8(userState.delegationMode) & uint8(DelegationMode.VOTING_DELEGATED)) != 0 ? _votingDelegatee[delegator] : address(0); } return userState.delegationMode >= DelegationMode.PROPOSITION_DELEGATED ? _propositionDelegatee[delegator] : address(0); } /** * @dev Changes user's delegatee address by type of governance power (Voting, Proposition) * @param delegator delegator * @param delegationType the type of governance power delegation (VOTING, PROPOSITION) * @param _newDelegatee the new delegatee **/ function _updateDelegateeByType( address delegator, GovernancePowerType delegationType, address _newDelegatee ) internal { address newDelegatee = _newDelegatee == delegator ? address(0) : _newDelegatee; if (delegationType == GovernancePowerType.VOTING) { _votingDelegatee[delegator] = newDelegatee; } else { _propositionDelegatee[delegator] = newDelegatee; } } /** * @dev Updates the specific flag which signaling about existence of delegation of governance power (Voting, Proposition) * @param userState a user state to change * @param delegationType the type of governance power delegation (VOTING, PROPOSITION) * @param willDelegate next state of delegation **/ function _updateDelegationModeByType( DelegationState memory userState, GovernancePowerType delegationType, bool willDelegate ) internal pure returns (DelegationState memory) { if (willDelegate) { // Because GovernancePowerType starts from 0, we should add 1 first, then we apply bitwise OR userState.delegationMode = DelegationMode( uint8(userState.delegationMode) | (uint8(delegationType) + 1) ); } else { // First bitwise NEGATION, ie was 01, after XOR with 11 will be 10, // then bitwise AND, which means it will keep only another delegation type if it exists userState.delegationMode = DelegationMode( uint8(userState.delegationMode) & ((uint8(delegationType) + 1) ^ uint8(DelegationMode.FULL_POWER_DELEGATED)) ); } return userState; } /** * @dev This is the equivalent of an ERC20 transfer(), but for a power type: an atomic transfer of a balance (power). * When needed, it decreases the power of the `delegator` and when needed, it increases the power of the `delegatee` * @param delegator delegator * @param _delegatee the user which delegated power will change * @param delegationType the type of delegation (VOTING, PROPOSITION) **/ function _delegateByType( address delegator, address _delegatee, GovernancePowerType delegationType ) internal { // Here we unify the property that delegating power to address(0) == delegating power to yourself == no delegation // So from now on, not being delegating is (exclusively) that delegatee == address(0) address delegatee = _delegatee == delegator ? address(0) : _delegatee; // We read the whole struct before validating delegatee, because in the optimistic case // (_delegatee != currentDelegatee) we will reuse userState in the rest of the function DelegationState memory delegatorState = _getDelegationState(delegator); address currentDelegatee = _getDelegateeByType(delegator, delegatorState, delegationType); if (delegatee == currentDelegatee) return; bool delegatingNow = currentDelegatee != address(0); bool willDelegateAfter = delegatee != address(0); uint256 delegatorBalance = _getBalance(delegator); if (delegatingNow) { _governancePowerTransferByType(delegatorBalance, 0, currentDelegatee, delegationType); } if (willDelegateAfter) { _governancePowerTransferByType(0, delegatorBalance, delegatee, delegationType); } _updateDelegateeByType(delegator, delegationType, delegatee); if (willDelegateAfter != delegatingNow) { _setDelegationState( delegator, _updateDelegationModeByType(delegatorState, delegationType, willDelegateAfter) ); } emit DelegateChanged(delegator, delegatee, delegationType); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; import "./Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ 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' 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 require( abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed" ); } } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; import {DistributionTypes} from '../lib/DistributionTypes.sol'; interface IAaveDistributionManager { function configureAssets( DistributionTypes.AssetConfigInput[] memory assetsConfigInput ) external; }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; interface IStakedTokenV2 { struct CooldownSnapshot { uint40 timestamp; uint216 amount; } event RewardsAccrued(address user, uint256 amount); event RewardsClaimed( address indexed from, address indexed to, uint256 amount ); event Cooldown(address indexed user, uint256 amount); /** * @dev Allows staking a specified amount of STAKED_TOKEN * @param to The address to receiving the shares * @param amount The amount of assets to be staked */ function stake(address to, uint256 amount) external; /** * @dev Redeems shares, and stop earning rewards * @param to Address to redeem to * @param amount Amount of shares to redeem */ function redeem(address to, uint256 amount) external; /** * @dev Activates the cooldown period to unstake * - It can't be called if the user is not staking */ function cooldown() external; /** * @dev Claims an `amount` of `REWARD_TOKEN` to the address `to` * @param to Address to send the claimed rewards * @param amount Amount to stake */ function claimRewards(address to, uint256 amount) external; /** * @dev Return the total rewards pending to claim by an staker * @param staker The staker address * @return The rewards */ function getTotalRewardsBalance( address staker ) external view returns (uint256); /** * @dev implements the permit function as for https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md * @param owner the owner of the funds * @param spender the spender * @param value the amount * @param deadline the deadline timestamp, type(uint256).max for no deadline * @param v signature param * @param s signature param * @param r signature param */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; import {EIP712, ECDSA} from 'aave-token-v3/utils/EIP712.sol'; import {IStakedTokenV2} from '../interfaces/IStakedTokenV2.sol'; import {DistributionTypes} from '../lib/DistributionTypes.sol'; import {SafeERC20} from '../lib/SafeERC20.sol'; import {VersionedInitializable} from '../utils/VersionedInitializable.sol'; import {AaveDistributionManager} from './AaveDistributionManager.sol'; import {GovernancePowerWithSnapshot} from '../lib/GovernancePowerWithSnapshot.sol'; import {BaseMintableAaveToken} from './BaseMintableAaveToken.sol'; /** * @title StakedTokenV2 * @notice Contract to stake Aave token, tokenize the position and get rewards, inheriting from a distribution manager contract * @author BGD Labs */ abstract contract StakedTokenV2 is IStakedTokenV2, BaseMintableAaveToken, GovernancePowerWithSnapshot, VersionedInitializable, AaveDistributionManager, EIP712 { using SafeERC20 for IERC20; IERC20 public immutable STAKED_TOKEN; IERC20 public immutable REWARD_TOKEN; /// @notice Seconds available to redeem once the cooldown period is fulfilled uint256 public immutable UNSTAKE_WINDOW; /// @notice Address to pull from the rewards, needs to have approved this contract address public immutable REWARDS_VAULT; mapping(address => uint256) public stakerRewardsToClaim; mapping(address => CooldownSnapshot) public stakersCooldowns; /// @dev End of Storage layout from StakedToken v1 uint256[5] private ______DEPRECATED_FROM_STK_AAVE_V2; bytes32 public constant PERMIT_TYPEHASH = keccak256( 'Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)' ); /// @dev owner => next valid nonce to submit with permit() mapping(address => uint256) public _nonces; constructor( IERC20 stakedToken, IERC20 rewardToken, uint256 unstakeWindow, address rewardsVault, address emissionManager, uint128 distributionDuration ) AaveDistributionManager(emissionManager, distributionDuration) EIP712('Staked Aave', '2') { STAKED_TOKEN = stakedToken; REWARD_TOKEN = rewardToken; UNSTAKE_WINDOW = unstakeWindow; REWARDS_VAULT = rewardsVault; } /** * @notice Get the domain separator for the token * @dev Return cached value if chainId matches cache, otherwise recomputes separator * @return The domain separator of the token at current chain */ function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return _domainSeparatorV4(); } /// @dev maintained for backwards compatibility. See EIP712 _EIP712Version function EIP712_REVISION() external view returns (bytes memory) { return bytes(_EIP712Version()); } /// @inheritdoc IStakedTokenV2 function stake(address onBehalfOf, uint256 amount) external virtual override; /// @inheritdoc IStakedTokenV2 function redeem(address to, uint256 amount) external virtual override; /// @inheritdoc IStakedTokenV2 function cooldown() external virtual override; /// @inheritdoc IStakedTokenV2 function claimRewards(address to, uint256 amount) external virtual override; /// @inheritdoc IStakedTokenV2 function getTotalRewardsBalance( address staker ) external view returns (uint256) { DistributionTypes.UserStakeInput[] memory userStakeInputs = new DistributionTypes.UserStakeInput[](1); userStakeInputs[0] = DistributionTypes.UserStakeInput({ underlyingAsset: address(this), stakedByUser: balanceOf(staker), totalStaked: totalSupply() }); return stakerRewardsToClaim[staker] + _getUnclaimedRewards(staker, userStakeInputs); } /// @inheritdoc IStakedTokenV2 function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external { require(owner != address(0), 'INVALID_OWNER'); //solium-disable-next-line require(block.timestamp <= deadline, 'INVALID_EXPIRATION'); uint256 currentValidNonce = _nonces[owner]; bytes32 digest = _hashTypedDataV4( keccak256( abi.encode( PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline ) ) ); require(owner == ECDSA.recover(digest, v, r, s), 'INVALID_SIGNATURE'); unchecked { _nonces[owner] = currentValidNonce + 1; } _approve(owner, spender, value); } /** * @dev Updates the user state related with his accrued rewards * @param user Address of the user * @param userBalance The current balance of the user * @param updateStorage Boolean flag used to update or not the stakerRewardsToClaim of the user * @return The unclaimed rewards that were added to the total accrued */ function _updateCurrentUnclaimedRewards( address user, uint256 userBalance, bool updateStorage ) internal returns (uint256) { uint256 accruedRewards = _updateUserAssetInternal( user, address(this), userBalance, totalSupply() ); uint256 unclaimedRewards = stakerRewardsToClaim[user] + accruedRewards; if (accruedRewards != 0) { if (updateStorage) { stakerRewardsToClaim[user] = unclaimedRewards; } emit RewardsAccrued(user, accruedRewards); } return unclaimedRewards; } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; import {IStakedTokenV2} from './IStakedTokenV2.sol'; interface IStakedTokenV3 is IStakedTokenV2 { event Staked( address indexed from, address indexed to, uint256 assets, uint256 shares ); event Redeem( address indexed from, address indexed to, uint256 assets, uint256 shares ); event MaxSlashablePercentageChanged(uint256 newPercentage); event Slashed(address indexed destination, uint256 amount); event SlashingExitWindowDurationChanged(uint256 windowSeconds); event CooldownSecondsChanged(uint256 cooldownSeconds); event ExchangeRateChanged(uint216 exchangeRate); event FundsReturned(uint256 amount); event SlashingSettled(); /** * @dev Allows staking a certain amount of STAKED_TOKEN with gasless approvals (permit) * @param amount The amount to be staked * @param deadline The permit execution deadline * @param v The v component of the signed message * @param r The r component of the signed message * @param s The s component of the signed message */ function stakeWithPermit( uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current exchange rate * @return exchangeRate as 18 decimal precision uint216 */ function getExchangeRate() external view returns (uint216); /** * @dev Executes a slashing of the underlying of a certain amount, transferring the seized funds * to destination. Decreasing the amount of underlying will automatically adjust the exchange rate. * A call to `slash` will start a slashing event which has to be settled via `settleSlashing`. * As long as the slashing event is ongoing, stake and slash are deactivated. * - MUST NOT be called when a previous slashing is still ongoing * @param destination the address where seized funds will be transferred * @param amount the amount to be slashed * - if the amount bigger than maximum allowed, the maximum will be slashed instead. * @return amount the amount slashed */ function slash( address destination, uint256 amount ) external returns (uint256); /** * @dev Settles an ongoing slashing event */ function settleSlashing() external; /** * @dev Pulls STAKE_TOKEN and distributes them amongst current stakers by altering the exchange rate. * This method is permissionless and intended to be used after a slashing event to return potential excess funds. * @param amount amount of STAKE_TOKEN to pull. */ function returnFunds(uint256 amount) external; /** * @dev Getter of the cooldown seconds * @return cooldownSeconds the amount of seconds between starting the cooldown and being able to redeem */ function getCooldownSeconds() external view returns (uint256); /** * @dev Getter of the cooldown seconds * @return cooldownSeconds the amount of seconds between starting the cooldown and being able to redeem */ function COOLDOWN_SECONDS() external view returns (uint256); // @deprecated /** * @dev Setter of cooldown seconds * Can only be called by the cooldown admin * @param cooldownSeconds the new amount of seconds you have to wait between starting the cooldown and being able to redeem */ function setCooldownSeconds(uint256 cooldownSeconds) external; /** * @dev Getter of the max slashable percentage of the total staked amount. * @return percentage the maximum slashable percentage */ function getMaxSlashablePercentage() external view returns (uint256); /** * @dev Setter of max slashable percentage of the total staked amount. * Can only be called by the slashing admin * @param percentage the new maximum slashable percentage */ function setMaxSlashablePercentage(uint256 percentage) external; /** * @dev returns the exact amount of shares that would be received for the provided number of assets * @param assets the number of assets to stake * @return uint256 shares the number of shares that would be received */ function previewStake(uint256 assets) external view returns (uint256); /** * @dev Activates the cooldown period to unstake * - It can't be called if the user is not staking */ function cooldownOnBehalfOf(address from) external; /** * @dev Claims an `amount` of `REWARD_TOKEN` to the address `to` on behalf of the user. Only the claim helper contract is allowed to call this function * @param from The address of the user from to claim * @param to Address to send the claimed rewards * @param amount Amount to claim */ function claimRewardsOnBehalf( address from, address to, uint256 amount ) external returns (uint256); /** * @dev returns the exact amount of assets that would be redeemed for the provided number of shares * @param shares the number of shares to redeem * @return uint256 assets the number of assets that would be redeemed */ function previewRedeem(uint256 shares) external view returns (uint256); /** * @dev Redeems shares for a user. Only the claim helper contract is allowed to call this function * @param from Address to redeem from * @param to Address to redeem to * @param amount Amount of shares to redeem */ function redeemOnBehalf(address from, address to, uint256 amount) external; /** * @dev Claims an `amount` of `REWARD_TOKEN` and redeems to the provided address * @param to Address to claim and redeem to * @param claimAmount Amount to claim * @param redeemAmount Amount to redeem */ function claimRewardsAndRedeem( address to, uint256 claimAmount, uint256 redeemAmount ) external; /** * @dev Claims an `amount` of `REWARD_TOKEN` and redeems the `redeemAmount` to an address. Only the claim helper contract is allowed to call this function * @param from The address of the from * @param to Address to claim and redeem to * @param claimAmount Amount to claim * @param redeemAmount Amount to redeem */ function claimRewardsAndRedeemOnBehalf( address from, address to, uint256 claimAmount, uint256 redeemAmount ) external; }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; /** * @title PercentageMath library * @author Aave * @notice Provides functions to perform percentage calculations * @dev Percentages are defined by default with 2 decimals of precision (100.00). The precision is indicated by PERCENTAGE_FACTOR * @dev Operations are rounded half up **/ library PercentageMath { uint256 constant PERCENTAGE_FACTOR = 1e4; //percentage plus two decimals uint256 constant HALF_PERCENT = PERCENTAGE_FACTOR / 2; /** * @dev Executes a percentage multiplication * @param value The value of which the percentage needs to be calculated * @param percentage The percentage of the value to be calculated * @return The percentage of value **/ function percentMul(uint256 value, uint256 percentage) internal pure returns (uint256) { if (value == 0 || percentage == 0) { return 0; } require( value <= (type(uint256).max) / percentage, "MATH_MULTIPLICATION_OVERFLOW" ); return (value * percentage) / PERCENTAGE_FACTOR; } /** * @dev Executes a percentage division * @param value The value of which the percentage needs to be calculated * @param percentage The percentage of the value to be calculated * @return The value divided the percentage **/ function percentDiv(uint256 value, uint256 percentage) internal pure returns (uint256) { require(percentage != 0, "MATH_DIVISION_BY_ZERO"); require( value <= type(uint256).max / PERCENTAGE_FACTOR, "MATH_MULTIPLICATION_OVERFLOW" ); return (value * PERCENTAGE_FACTOR) / percentage; } }
pragma solidity ^0.8.0; /** * @title RoleManager * @notice Generic role manager to manage slashing and cooldown admin in StakedAaveV3. * It implements a claim admin role pattern to safely migrate between different admin addresses * @author Aave **/ contract RoleManager { struct InitAdmin { uint256 role; address admin; } mapping(uint256 => address) private _admins; mapping(uint256 => address) private _pendingAdmins; event PendingAdminChanged(address indexed newPendingAdmin, uint256 role); event RoleClaimed(address indexed newAdmin, uint256 role); modifier onlyRoleAdmin(uint256 role) { require(_admins[role] == msg.sender, 'CALLER_NOT_ROLE_ADMIN'); _; } modifier onlyPendingRoleAdmin(uint256 role) { require( _pendingAdmins[role] == msg.sender, 'CALLER_NOT_PENDING_ROLE_ADMIN' ); _; } /** * @dev returns the admin associated with the specific role * @param role the role associated with the admin being returned **/ function getAdmin(uint256 role) public view returns (address) { return _admins[role]; } /** * @dev returns the pending admin associated with the specific role * @param role the role associated with the pending admin being returned **/ function getPendingAdmin(uint256 role) public view returns (address) { return _pendingAdmins[role]; } /** * @dev sets the pending admin for a specific role * @param role the role associated with the new pending admin being set * @param newPendingAdmin the address of the new pending admin **/ function setPendingAdmin( uint256 role, address newPendingAdmin ) public onlyRoleAdmin(role) { _pendingAdmins[role] = newPendingAdmin; emit PendingAdminChanged(newPendingAdmin, role); } /** * @dev allows the caller to become a specific role admin * @param role the role associated with the admin claiming the new role **/ function claimRoleAdmin(uint256 role) external onlyPendingRoleAdmin(role) { _admins[role] = msg.sender; _pendingAdmins[role] = address(0); emit RoleClaimed(msg.sender, role); } function _initAdmins(InitAdmin[] memory initAdmins) internal { for (uint256 i = 0; i < initAdmins.length; i++) { require( _admins[initAdmins[i].role] == address(0) && initAdmins[i].admin != address(0), 'ADMIN_CANNOT_BE_INITIALIZED' ); _admins[initAdmins[i].role] = initAdmins[i].admin; emit RoleClaimed(initAdmins[i].admin, initAdmins[i].role); } } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; interface IERC20WithPermit is IERC20 { function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.19; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** @notice influenced by OpenZeppelin SafeCast lib, which is missing to uint72 cast * @author BGD Labs */ library SafeCast72 { /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IGovernancePowerDelegationToken { enum GovernancePowerType { VOTING, PROPOSITION } /** * @dev emitted when a user delegates to another * @param delegator the user which delegated governance power * @param delegatee the delegatee * @param delegationType the type of delegation (VOTING, PROPOSITION) **/ event DelegateChanged( address indexed delegator, address indexed delegatee, GovernancePowerType delegationType ); // @dev we removed DelegatedPowerChanged event because to reconstruct the full state of the system, // is enough to have Transfer and DelegateChanged TODO: document it /** * @dev delegates the specific power to a delegatee * @param delegatee the user which delegated power will change * @param delegationType the type of delegation (VOTING, PROPOSITION) **/ function delegateByType(address delegatee, GovernancePowerType delegationType) external; /** * @dev delegates all the governance powers to a specific user * @param delegatee the user to which the powers will be delegated **/ function delegate(address delegatee) external; /** * @dev returns the delegatee of an user * @param delegator the address of the delegator * @param delegationType the type of delegation (VOTING, PROPOSITION) * @return address of the specified delegatee **/ function getDelegateeByType(address delegator, GovernancePowerType delegationType) external view returns (address); /** * @dev returns delegates of an user * @param delegator the address of the delegator * @return a tuple of addresses the VOTING and PROPOSITION delegatee **/ function getDelegates(address delegator) external view returns (address, address); /** * @dev returns the current voting or proposition power of a user. * @param user the user * @param delegationType the type of delegation (VOTING, PROPOSITION) * @return the current voting or proposition power of a user **/ function getPowerCurrent(address user, GovernancePowerType delegationType) external view returns (uint256); /** * @dev returns the current voting or proposition power of a user. * @param user the user * @return the current voting and proposition power of a user **/ function getPowersCurrent(address user) external view returns (uint256, uint256); /** * @dev implements the permit function as for https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md * @param delegator the owner of the funds * @param delegatee the user to who owner delegates his governance power * @param delegationType the type of governance power delegation (VOTING, PROPOSITION) * @param deadline the deadline timestamp, type(uint256).max for no deadline * @param v signature param * @param s signature param * @param r signature param */ function metaDelegateByType( address delegator, address delegatee, GovernancePowerType delegationType, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev implements the permit function as for https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md * @param delegator the owner of the funds * @param delegatee the user to who delegator delegates his voting and proposition governance power * @param deadline the deadline timestamp, type(uint256).max for no deadline * @param v signature param * @param s signature param * @param r signature param */ function metaDelegate( address delegator, address delegatee, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; enum DelegationMode { NO_DELEGATION, VOTING_DELEGATED, PROPOSITION_DELEGATED, FULL_POWER_DELEGATED }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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://consensys.net/diligence/blog/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"); (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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // Contract modified from OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) to remove local // fallback storage variables, so contract does not affect on existing storage layout. This works as its used on contracts // that have name and revision < 32 bytes pragma solidity ^0.8.10; import {ECDSA} from 'openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol'; import {ShortStrings, ShortString} from 'openzeppelin-contracts/contracts/utils/ShortStrings.sol'; import {IERC5267} from 'openzeppelin-contracts/contracts/interfaces/IERC5267.sol'; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * _Available since v3.4._ * * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant _TYPE_HASH = keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ /// @dev BGD: removed usage of fallback variables to not modify previous storage layout. As we know that the length of /// name and version will not be bigger than 32 bytes we use toShortString as there is no need to use the fallback system. constructor(string memory name, string memory version) { _name = name.toShortString(); _version = version.toShortString(); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {EIP-5267}. * * _Available since v4.9._ */ function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex'0f', // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: By default this function reads _name which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). * * _Available since v5.0._ */ /// @dev BGD: we use toString instead of toStringWithFallback as we dont have fallback, to not modify previous storage layout // solhint-disable-next-line func-name-mixedcase function _EIP712Name() internal view returns (string memory) { return _name.toString(); // _name.toStringWithFallback(_nameFallback); } /** * @dev The version parameter for the EIP712 domain. * * NOTE: By default this function reads _version which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). * * _Available since v5.0._ */ /// @dev BGD: we use toString instead of toStringWithFallback as we dont have fallback, to not modify previous storage layout // solhint-disable-next-line func-name-mixedcase function _EIP712Version() internal view returns (string memory) { return _version.toString(); } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; /** * @title VersionedInitializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. * * @author Aave, inspired by the OpenZeppelin Initializable contract */ abstract contract VersionedInitializable { /** * @dev Indicates that the contract has been initialized. */ uint256 internal lastInitializedRevision = 0; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { uint256 revision = getRevision(); require( revision > lastInitializedRevision, 'Contract instance has already been initialized' ); lastInitializedRevision = revision; _; } /// @dev returns the revision number of the contract. /// Needs to be defined in the inherited class as a constant. function getRevision() internal pure virtual returns (uint256); // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; import {DistributionTypes} from '../lib/DistributionTypes.sol'; /** * @title AaveDistributionManager * @notice Accounting contract to manage multiple staking distributions * @author Aave */ contract AaveDistributionManager { struct AssetData { uint128 emissionPerSecond; uint128 lastUpdateTimestamp; uint256 index; mapping(address => uint256) users; } uint256 public immutable DISTRIBUTION_END; address public immutable EMISSION_MANAGER; uint8 public constant PRECISION = 18; mapping(address => AssetData) public assets; event AssetConfigUpdated(address indexed asset, uint256 emission); event AssetIndexUpdated(address indexed asset, uint256 index); event UserIndexUpdated( address indexed user, address indexed asset, uint256 index ); constructor(address emissionManager, uint256 distributionDuration) { DISTRIBUTION_END = block.timestamp + distributionDuration; EMISSION_MANAGER = emissionManager; } /** * @dev Configures the distribution of rewards for a list of assets * @param assetsConfigInput The list of configurations to apply */ function _configureAssets( DistributionTypes.AssetConfigInput[] memory assetsConfigInput ) internal { for (uint256 i = 0; i < assetsConfigInput.length; i++) { AssetData storage assetConfig = assets[ assetsConfigInput[i].underlyingAsset ]; _updateAssetStateInternal( assetsConfigInput[i].underlyingAsset, assetConfig, assetsConfigInput[i].totalStaked ); assetConfig.emissionPerSecond = assetsConfigInput[i].emissionPerSecond; emit AssetConfigUpdated( assetsConfigInput[i].underlyingAsset, assetsConfigInput[i].emissionPerSecond ); } } /** * @dev Updates the state of one distribution, mainly rewards index and timestamp * @param underlyingAsset The address used as key in the distribution, for example sAAVE or the aTokens addresses on Aave * @param assetConfig Storage pointer to the distribution's config * @param totalStaked Current total of staked assets for this distribution * @return The new distribution index */ function _updateAssetStateInternal( address underlyingAsset, AssetData storage assetConfig, uint256 totalStaked ) internal returns (uint256) { uint256 oldIndex = assetConfig.index; uint128 lastUpdateTimestamp = assetConfig.lastUpdateTimestamp; if (block.timestamp == lastUpdateTimestamp) { return oldIndex; } uint256 newIndex = _getAssetIndex( oldIndex, assetConfig.emissionPerSecond, lastUpdateTimestamp, totalStaked ); if (newIndex != oldIndex) { assetConfig.index = newIndex; emit AssetIndexUpdated(underlyingAsset, newIndex); } assetConfig.lastUpdateTimestamp = uint128(block.timestamp); return newIndex; } /** * @dev Updates the state of an user in a distribution * @param user The user's address * @param asset The address of the reference asset of the distribution * @param stakedByUser Amount of tokens staked by the user in the distribution at the moment * @param totalStaked Total tokens staked in the distribution * @return The accrued rewards for the user until the moment */ function _updateUserAssetInternal( address user, address asset, uint256 stakedByUser, uint256 totalStaked ) internal returns (uint256) { AssetData storage assetData = assets[asset]; uint256 userIndex = assetData.users[user]; uint256 accruedRewards = 0; uint256 newIndex = _updateAssetStateInternal(asset, assetData, totalStaked); if (userIndex != newIndex) { if (stakedByUser != 0) { accruedRewards = _getRewards(stakedByUser, newIndex, userIndex); } assetData.users[user] = newIndex; emit UserIndexUpdated(user, asset, newIndex); } return accruedRewards; } /** * @dev Used by "frontend" stake contracts to update the data of an user when claiming rewards from there * @param user The address of the user * @param stakes List of structs of the user data related with his stake * @return The accrued rewards for the user until the moment */ function _claimRewards( address user, DistributionTypes.UserStakeInput[] memory stakes ) internal returns (uint256) { uint256 accruedRewards = 0; for (uint256 i = 0; i < stakes.length; i++) { accruedRewards = accruedRewards + _updateUserAssetInternal( user, stakes[i].underlyingAsset, stakes[i].stakedByUser, stakes[i].totalStaked ); } return accruedRewards; } /** * @dev Return the accrued rewards for an user over a list of distribution * @param user The address of the user * @param stakes List of structs of the user data related with his stake * @return The accrued rewards for the user until the moment */ function _getUnclaimedRewards( address user, DistributionTypes.UserStakeInput[] memory stakes ) internal view returns (uint256) { uint256 accruedRewards = 0; for (uint256 i = 0; i < stakes.length; i++) { AssetData storage assetConfig = assets[stakes[i].underlyingAsset]; uint256 assetIndex = _getAssetIndex( assetConfig.index, assetConfig.emissionPerSecond, assetConfig.lastUpdateTimestamp, stakes[i].totalStaked ); accruedRewards = accruedRewards + _getRewards( stakes[i].stakedByUser, assetIndex, assetConfig.users[user] ); } return accruedRewards; } /** * @dev Internal function for the calculation of user's rewards on a distribution * @param principalUserBalance Amount staked by the user on a distribution * @param reserveIndex Current index of the distribution * @param userIndex Index stored for the user, representation his staking moment * @return The rewards */ function _getRewards( uint256 principalUserBalance, uint256 reserveIndex, uint256 userIndex ) internal pure returns (uint256) { return (principalUserBalance * (reserveIndex - userIndex)) / (10 ** uint256(PRECISION)); } /** * @dev Calculates the next value of an specific distribution index, with validations * @param currentIndex Current index of the distribution * @param emissionPerSecond Representing the total rewards distributed per second per asset unit, on the distribution * @param lastUpdateTimestamp Last moment this distribution was updated * @param totalBalance of tokens considered for the distribution * @return The new index. */ function _getAssetIndex( uint256 currentIndex, uint256 emissionPerSecond, uint128 lastUpdateTimestamp, uint256 totalBalance ) internal view returns (uint256) { if ( emissionPerSecond == 0 || totalBalance == 0 || lastUpdateTimestamp == block.timestamp || lastUpdateTimestamp >= DISTRIBUTION_END ) { return currentIndex; } uint256 currentTimestamp = block.timestamp > DISTRIBUTION_END ? DISTRIBUTION_END : block.timestamp; uint256 timeDelta = currentTimestamp - lastUpdateTimestamp; return ((emissionPerSecond * timeDelta * (10 ** uint256(PRECISION))) / totalBalance) + currentIndex; } /** * @dev Returns the data of an user on a distribution * @param user Address of the user * @param asset The address of the reference asset of the distribution * @return The new index */ function getUserAssetData( address user, address asset ) public view returns (uint256) { return assets[asset].users[user]; } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; /** * @title MOCK CONTRACT TO KEEP VALID STORAGE LAYOUT * @dev WAS including snapshots of balances on transfer-related actions * @author BGD Labs **/ abstract contract GovernancePowerWithSnapshot { uint256[3] private __________DEPRECATED_GOV_V2_PART; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {BaseAaveToken} from 'aave-token-v3/BaseAaveToken.sol'; /** * @title BaseMintableAaveToken * @author BGD labs * @notice extension for BaseAaveToken adding mint/burn and transfer hooks */ contract BaseMintableAaveToken is BaseAaveToken { /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint104 amount) internal virtual { require(account != address(0), 'ERC20: mint to the zero address'); uint104 balanceBefore = _balances[account].balance; _totalSupply += amount; _balances[account].balance += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, 0, balanceBefore, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint104 amount) internal virtual { require(account != address(0), 'ERC20: burn from the zero address'); uint104 accountBalance = _balances[account].balance; require(accountBalance >= amount, 'ERC20: burn amount exceeds balance'); unchecked { _balances[account].balance = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), accountBalance, 0, amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.19; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol) pragma solidity ^0.8.19; import "./StorageSlot.sol"; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(_FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.19; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Context} from 'openzeppelin-contracts/contracts/utils/Context.sol'; import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; import {IERC20Metadata} from 'openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol'; import {DelegationMode} from './DelegationAwareBalance.sol'; // Inspired by OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol) abstract contract BaseAaveToken is Context, IERC20Metadata { struct DelegationAwareBalance { uint104 balance; uint72 delegatedPropositionBalance; uint72 delegatedVotingBalance; DelegationMode delegationMode; } mapping(address => DelegationAwareBalance) internal _balances; mapping(address => mapping(address => uint256)) internal _allowances; uint256 internal _totalSupply; string internal _name; string internal _symbol; // @dev DEPRECATED // kept for backwards compatibility with old storage layout uint8 private ______DEPRECATED_OLD_ERC20_DECIMALS; /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } function decimals() public view virtual override returns (uint8) { return 18; } function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account].balance; } function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, _allowances[owner][spender] + addedValue); return true; } function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = _allowances[owner][spender]; require(currentAllowance >= subtractedValue, 'ERC20: decreased allowance below zero'); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), 'ERC20: transfer from the zero address'); require(to != address(0), 'ERC20: transfer to the zero address'); if (from != to) { uint104 fromBalanceBefore = _balances[from].balance; uint104 toBalanceBefore = _balances[to].balance; require(fromBalanceBefore >= amount, 'ERC20: transfer amount exceeds balance'); unchecked { _balances[from].balance = fromBalanceBefore - uint104(amount); } _balances[to].balance = toBalanceBefore + uint104(amount); _afterTokenTransfer(from, to, fromBalanceBefore, toBalanceBefore, amount); } emit Transfer(from, to, amount); } function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), 'ERC20: approve from the zero address'); require(spender != address(0), 'ERC20: approve to the zero address'); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, 'ERC20: insufficient allowance'); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev after token transfer hook, added for delegation system * @param from token sender * @param to token recipient * @param fromBalanceBefore balance of the sender before transfer * @param toBalanceBefore balance of the recipient before transfer * @param amount amount of tokens sent **/ function _afterTokenTransfer( address from, address to, uint256 fromBalanceBefore, uint256 toBalanceBefore, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.19; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v5.0._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v5.0._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v5.0._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v5.0._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v5.0._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.19; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.19; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.19; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "remappings": [ "@aave/core-v3/=lib/aave-address-book/lib/aave-v3-core/", "@aave/periphery-v3/=lib/aave-address-book/lib/aave-v3-periphery/", "aave-address-book/=lib/aave-address-book/src/", "aave-helpers/=lib/aave-helpers/src/", "aave-v3-core/=lib/aave-address-book/lib/aave-v3-core/", "aave-v3-periphery/=lib/aave-address-book/lib/aave-v3-periphery/", "aave-token-v3/=lib/aave-token-v3/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solidity-utils/=lib/aave-helpers/lib/solidity-utils/src/", "aave-token-v2/=lib/aave-token-v3/lib/aave-token-v2/contracts/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "governance-crosschain-bridges/=lib/aave-helpers/lib/governance-crosschain-bridges/", "openzeppelin/=lib/openzeppelin-contracts/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IERC20","name":"stakedToken","type":"address"},{"internalType":"contract IERC20","name":"rewardToken","type":"address"},{"internalType":"uint256","name":"unstakeWindow","type":"uint256"},{"internalType":"address","name":"rewardsVault","type":"address"},{"internalType":"address","name":"emissionManager","type":"address"},{"internalType":"uint128","name":"distributionDuration","type":"uint128"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"emission","type":"uint256"}],"name":"AssetConfigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"AssetIndexUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Cooldown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"cooldownSeconds","type":"uint256"}],"name":"CooldownSecondsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"delegatee","type":"address"},{"indexed":false,"internalType":"enum IGovernancePowerDelegationToken.GovernancePowerType","name":"delegationType","type":"uint8"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint216","name":"exchangeRate","type":"uint216"}],"name":"ExchangeRateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FundsReturned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newPercentage","type":"uint256"}],"name":"MaxSlashablePercentageChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newPendingAdmin","type":"address"},{"indexed":false,"internalType":"uint256","name":"role","type":"uint256"}],"name":"PendingAdminChanged","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":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsAccrued","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":"amount","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"},{"indexed":false,"internalType":"uint256","name":"role","type":"uint256"}],"name":"RoleClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Slashed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"windowSeconds","type":"uint256"}],"name":"SlashingExitWindowDurationChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"SlashingSettled","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":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"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":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"UserIndexUpdated","type":"event"},{"inputs":[],"name":"CLAIM_HELPER_ROLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COOLDOWN_ADMIN_ROLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COOLDOWN_SECONDS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGATE_BY_TYPE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGATE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISTRIBUTION_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EIP712_REVISION","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_MANAGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXCHANGE_RATE_UNIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_EXCHANGE_RATE","outputs":[{"internalType":"uint216","name":"","type":"uint216"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOWER_BOUND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POWER_SCALE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REVISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"REWARDS_VAULT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_TOKEN","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLASH_ADMIN_ROLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKED_TOKEN","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNSTAKE_WINDOW","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assets","outputs":[{"internalType":"uint128","name":"emissionPerSecond","type":"uint128"},{"internalType":"uint128","name":"lastUpdateTimestamp","type":"uint128"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"claimAmount","type":"uint256"},{"internalType":"uint256","name":"redeemAmount","type":"uint256"}],"name":"claimRewardsAndRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"claimAmount","type":"uint256"},{"internalType":"uint256","name":"redeemAmount","type":"uint256"}],"name":"claimRewardsAndRedeemOnBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimRewardsAndStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimRewardsAndStakeOnBehalf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimRewardsOnBehalf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"role","type":"uint256"}],"name":"claimRoleAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"emissionPerSecond","type":"uint128"},{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"address","name":"underlyingAsset","type":"address"}],"internalType":"struct DistributionTypes.AssetConfigInput[]","name":"assetsConfigInput","type":"tuple[]"}],"name":"configureAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"cooldownOnBehalfOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"enum IGovernancePowerDelegationToken.GovernancePowerType","name":"delegationType","type":"uint8"}],"name":"delegateByType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"role","type":"uint256"}],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCooldownSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"enum IGovernancePowerDelegationToken.GovernancePowerType","name":"delegationType","type":"uint8"}],"name":"getDelegateeByType","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"getDelegates","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExchangeRate","outputs":[{"internalType":"uint216","name":"","type":"uint216"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxSlashablePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"role","type":"uint256"}],"name":"getPendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"enum IGovernancePowerDelegationToken.GovernancePowerType","name":"delegationType","type":"uint8"}],"name":"getPowerCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getPowersCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"getTotalRewardsBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"asset","type":"address"}],"name":"getUserAssetData","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ghoDebtToken","outputs":[{"internalType":"contract IGhoVariableDebtTokenTransferHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inPostSlashingPeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"metaDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"enum IGovernancePowerDelegationToken.GovernancePowerType","name":"delegationType","type":"uint8"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"metaDelegateByType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"redeemOnBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"returnFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"cooldownSeconds","type":"uint256"}],"name":"setCooldownSeconds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percentage","type":"uint256"}],"name":"setMaxSlashablePercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"role","type":"uint256"},{"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleSlashing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"slash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"stakeWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakerRewardsToClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakersCooldowns","outputs":[{"internalType":"uint40","name":"timestamp","type":"uint40"},{"internalType":"uint216","name":"amount","type":"uint216"}],"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":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61024060405260006009553480156200001757600080fd5b50604051620057c8380380620057c88339810160408190526200003a9162000294565b8585858585858585858585856040518060400160405280600b81526020016a5374616b6564204161766560a81b815250604051806040016040528060018152602001601960f91b81525083836001600160801b031680426200009d91906200033d565b608052506001600160a01b031660a052620000b8826200022a565b61016052620000c7816200022a565b61018052815160208084019190912061012052815190820120610140524660e052620001576101205161014051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60c0525050306101005250506001600160a01b039384166101a0529183166101c0526101e052166102005260066009819055506000866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001cb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001f1919062000359565b60ff1690506200020381600a62000482565b61022052506200021a955050620002769350505050565b6009555062000508945050505050565b600080829050601f8151111562000261578260405163305a27a960e01b815260040162000258919062000490565b60405180910390fd5b80516200026e82620004e0565b179392505050565b600690565b6001600160a01b03811681146200029157600080fd5b50565b60008060008060008060c08789031215620002ae57600080fd5b8651620002bb816200027b565b6020880151909650620002ce816200027b565b604088015160608901519196509450620002e8816200027b565b6080880151909350620002fb816200027b565b60a08801519092506001600160801b03811681146200031957600080fd5b809150509295509295509295565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000353576200035362000327565b92915050565b6000602082840312156200036c57600080fd5b815160ff811681146200037e57600080fd5b9392505050565b600181815b80851115620003c6578160001904821115620003aa57620003aa62000327565b80851615620003b857918102915b93841c93908002906200038a565b509250929050565b600082620003df5750600162000353565b81620003ee5750600062000353565b8160018114620004075760028114620004125762000432565b600191505062000353565b60ff84111562000426576200042662000327565b50506001821b62000353565b5060208310610133831016604e8410600b841016171562000457575081810a62000353565b62000463838362000385565b80600019048211156200047a576200047a62000327565b029392505050565b60006200037e8383620003ce565b600060208083528351808285015260005b81811015620004bf57858101830151858201604001528201620004a1565b506000604082860101526040601f19601f8301168501019250505092915050565b8051602080830151919081101562000502576000198160200360031b1b821691505b50919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516151a162000627600039600081816107d901528181610d12015281816110ba015261112b01526000818161091601526127b70152600081816106d30152612288015260008181610958015281816127950152612fe501526000818161065901528181610dbb015281816111bd01528181611cd9015281816124c401528181612fbb01526131d801526000612e2501526000612e8501526000612bad01526000612b8501526000612ae001526000612b0a01526000612b34015260008181610a9c01526119f20152600081816108ef01528181613fbc01528181613ff8015261402501526151a16000f3fe608060405234801561001057600080fd5b506004361061046a5760003560e01c80637e90d7ef1161024c578063ab406fe611610146578063dc937e1c116100c3578063ecd9ba8211610087578063ecd9ba8214610b50578063f036bc6814610b63578063f11b818814610b77578063f34d96da14610bd9578063fde9eb6914610be157600080fd5b8063dc937e1c14610ad9578063dd62ed3e14610aec578063dde43cba14610b25578063e6aa216c14610b2c578063eab5231814610b3d57600080fd5b8063b9844d8d1161010a578063b9844d8d14610a64578063c18f539a14610a84578063cbcbb50714610a97578063d505accf14610abe578063dbc0ed8a14610ad157600080fd5b8063ab406fe614610a10578063adc9772e14610a23578063aff05aa914610a36578063b2a5dbfa14610a3e578063b2f4201d14610a5157600080fd5b806395d89b41116101d4578063a095ac1911610198578063a095ac19146109a8578063a457c2d7146109bb578063a9059cbb146109ce578063aa9fbe02146109e1578063aaf5eb6814610a0857600080fd5b806395d89b411461094b57806399248ea7146109535780639a99b4f01461097a5780639c9b51541461098d5780639e3ffce0146109a057600080fd5b80638dbefee21161021b5780638dbefee2146108c85780638e9b2ca4146108db578063919cd40f146108ea578063946776cd14610911578063955e18af1461093857600080fd5b80637e90d7ef1461087d5780638129fc1c1461089d57806384b0196e146108a55780638c9a281d146108c057600080fd5b80633644e515116103685780636198e135116102e557806372b49d63116102a957806372b49d63146107cc57806374011f5614610847578063781603761461085a578063787a08a6146108625780637b5b11571461086a57600080fd5b80636198e135146107d4578063657f0cde146107fb5780636f50458d1461080e57806370a0823114610821578063727a5d571461083457600080fd5b80634cdad5061161032c5780634cdad50614610773578063570a97141461078657806358146d17146107925780635c19a95c146107b9578063616e0bf9146107cc57600080fd5b80633644e515146106f557806339509351146106fd57806341cbf54a1461071057806345755dd6146107375780634575e69b1461074a57600080fd5b80631e9a6950116103f657806330adf81f116103ba57806330adf81f1461062d578063312f6b8314610654578063313ce5671461067b5780633373ee4c14610690578063359c4a96146106ce57600080fd5b80631e9a6950146105b957806320fb80b5146105cc57806323b872dd146105df578063250201db146105f25780632a8b36681461060557600080fd5b8063111fd88b1161043d578063111fd88b1461052b578063112d037c14610556578063169db77d1461056b578063174ed5421461059e57806318160ddd146105b157600080fd5b806302fb4d851461046f57806306fdde0314610495578063091030c3146104aa578063095ea7b314610508575b600080fd5b61048261047d3660046147bf565b610bf4565b6040519081526020015b60405180910390f35b61049d610e32565b60405161048c9190614839565b6104e36104b836600461484c565b603e6020526000908152604090205464ffffffffff811690600160281b90046001600160d81b031682565b6040805164ffffffffff90931683526001600160d81b0390911660208301520161048c565b61051b6105163660046147bf565b610ec4565b604051901515815260200161048c565b61053e610539366004614867565b610edc565b6040516001600160a01b03909116815260200161048c565b610569610564366004614880565b610ef7565b005b61057e61057936600461484c565b610f49565b604080516001600160a01b0393841681529290911660208301520161048c565b60535461053e906001600160a01b031681565b600254610482565b6105696105c73660046147bf565b610f7b565b6104826105da366004614880565b610f8d565b61051b6105ed366004614880565b610fde565b61056961060036600461484c565b611002565b61061861061336600461484c565b611048565b6040805192835260208301919091520161048c565b6104827f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61053e7f000000000000000000000000000000000000000000000000000000000000000081565b60125b60405160ff909116815260200161048c565b61048261069e3660046148bc565b6001600160a01b038082166000908152603c60209081526040808320938616835260029093019052205492915050565b6104827f000000000000000000000000000000000000000000000000000000000000000081565b61048261106a565b61051b61070b3660046147bf565b611079565b6104827fd46e8b93b5190df6403875402a5c13897b72d2a576da5d1bfea20a63638d216e81565b610569610745366004614867565b6110b8565b61053e610758366004614867565b6000908152604660205260409020546001600160a01b031690565b610482610781366004614867565b61121d565b6104826402540be40081565b6107a1670de0b6b3a764000081565b6040516001600160d81b03909116815260200161048c565b6105696107c736600461484c565b611248565b604f54610482565b6104827f000000000000000000000000000000000000000000000000000000000000000081565b61056961080936600461490f565b611260565b61053e61081c366004614980565b61139c565b61048261082f36600461484c565b6113b1565b610482610842366004614867565b6113d5565b610569610855366004614867565b6113f8565b61049d61143b565b610569611445565b610569610878366004614867565b611450565b61048261088b36600461484c565b603d6020526000908152604090205481565b6105696114c3565b6108ad611533565b60405161048c97969594939291906149aa565b610482600081565b6104826108d636600461484c565b611579565b610482670de0b6b3a764000081565b6104827f000000000000000000000000000000000000000000000000000000000000000081565b61053e7f000000000000000000000000000000000000000000000000000000000000000081565b6104826109463660046147bf565b611654565b61049d611661565b61053e7f000000000000000000000000000000000000000000000000000000000000000081565b6105696109883660046147bf565b611670565b61056961099b366004614a40565b61167b565b610482600181565b6105696109b6366004614a82565b6116d5565b61051b6109c93660046147bf565b611807565b61051b6109dc3660046147bf565b611899565b6104827f6e77642f8f60cdece0498bfeeb2f06ccfef0e8f86d28a1b6255c5e48f1d72a0381565b61067e601281565b610569610a1e366004614ae1565b6118a7565b610569610a313660046147bf565b61196a565b610569611975565b610569610a4c366004614b74565b6119e7565b610482610a5f366004614980565b611aa2565b610482610a7236600461484c565b60446020526000908152604090205481565b610482610a92366004614880565b611ae6565b61053e7f000000000000000000000000000000000000000000000000000000000000000081565b610569610acc366004614c59565b611b2d565b610482600281565b610569610ae7366004614980565b611c74565b610482610afa3660046148bc565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6006610482565b6051546001600160d81b03166107a1565b610569610b4b366004614ca7565b611c7f565b610569610b5e366004614cda565b611c99565b60515461051b90600160d81b900460ff1681565b610bb3610b8536600461484c565b603c60205260009081526040902080546001909101546001600160801b0380831692600160801b9004169083565b604080516001600160801b0394851681529390921660208401529082015260600161048c565b605054610482565b610569610bef366004614867565b611d7e565b6000610c006000610edc565b6001600160a01b0316336001600160a01b031614610c395760405162461bcd60e51b8152600401610c3090614d21565b60405180910390fd5b605154600160d81b900460ff1615610c935760405162461bcd60e51b815260206004820152601d60248201527f50524556494f55535f534c415348494e475f4e4f545f534554544c45440000006044820152606401610c30565b60008211610cd15760405162461bcd60e51b815260206004820152600b60248201526a16915493d7d05353d5539560aa1b6044820152606401610c30565b6000610cdc60025490565b90506000610ce98261121d565b90506000610d0260505483611e4f90919063ffffffff16565b905080851115610d10578094505b7f0000000000000000000000000000000000000000000000000000000000000000610d3b8684614d6e565b1015610d805760405162461bcd60e51b815260206004820152601460248201527352454d41494e494e475f4c545f4d494e494d554d60601b6044820152606401610c30565b6051805460ff60d81b1916600160d81b179055610dae610da9610da38785614d6e565b85611ed1565b611f0f565b610de26001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168787611fb2565b856001600160a01b03167f4ed05e9673c26d2ed44f7ef6a7f2942df0ee3b5e1e17db4b99f9dcd261a339cd86604051610e1d91815260200190565b60405180910390a28493505050505b92915050565b606060038054610e4190614d81565b80601f0160208091040260200160405190810160405280929190818152602001828054610e6d90614d81565b8015610eba5780601f10610e8f57610100808354040283529160200191610eba565b820191906000526020600020905b815481529060010190602001808311610e9d57829003601f168201915b5050505050905090565b600033610ed2818585612015565b5060019392505050565b6000908152604560205260409020546001600160a01b031690565b610f016002610edc565b6001600160a01b0316336001600160a01b031614610f315760405162461bcd60e51b8152600401610c3090614dbb565b610f448383610f3f8461213a565b6121a7565b505050565b6000806000610f578461254b565b9050610f658482600061264e565b610f718583600161264e565b9250925050915091565b610f893383610f3f8461213a565b5050565b6000610f996002610edc565b6001600160a01b0316336001600160a01b031614610fc95760405162461bcd60e51b8152600401610c3090614dbb565b610fd48484846126fb565b90505b9392505050565b600033610fec858285612833565b610ff78585856128bf565b506001949350505050565b61100c6002610edc565b6001600160a01b0316336001600160a01b03161461103c5760405162461bcd60e51b8152600401610c3090614dbb565b611045816129f0565b50565b600080611056836000611aa2565b611061846001611aa2565b91509150915091565b6000611074612ad3565b905090565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190610ed290829086906110b3908790614df2565b612015565b7f000000000000000000000000000000000000000000000000000000000000000081101561111c5760405162461bcd60e51b8152602060048201526011602482015270414d4f554e545f4c545f4d494e494d554d60781b6044820152606401610c30565b600061112760025490565b90507f000000000000000000000000000000000000000000000000000000000000000081101561118d5760405162461bcd60e51b81526020600482015260116024820152705348415245535f4c545f4d494e494d554d60781b6044820152606401610c30565b60006111988261121d565b90506111b0610da96111aa8584614df2565b84611ed1565b6111e56001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086612bfe565b6040518381527f278e51d3323fbf18b9fb8df3f8b97e31b145bc1146c52e764cf4aa1bfc4ba17d9060200160405180910390a1505050565b6051546000906001600160d81b031661123e83670de0b6b3a7640000614e05565b610e2c9190614e1c565b61125433826000612c36565b61104533826001612c36565b6001600160a01b0387166112865760405162461bcd60e51b8152600401610c3090614e3e565b834211156112a65760405162461bcd60e51b8152600401610c3090614e65565b60006113496112b3612d5e565b7f6e77642f8f60cdece0498bfeeb2f06ccfef0e8f86d28a1b6255c5e48f1d72a038a8a8a6112fe8e6001600160a01b0316600090815260446020526040902080546001810190915590565b8b60405160200161131496959493929190614ec9565b6040516020818303038152906040528051906020012060405161190160f01b8152600281019290925260228201526042902090565b905061135781858585612d68565b6001600160a01b0316886001600160a01b0316146113875760405162461bcd60e51b8152600401610c3090614f08565b611392888888612c36565b5050505050505050565b6000610fd7836113ab8561254b565b8461264e565b6001600160a01b03166000908152602081905260409020546001600160681b031690565b605154600090670de0b6b3a76400009061123e906001600160d81b031684614e05565b6114026000610edc565b6001600160a01b0316336001600160a01b0316146114325760405162461bcd60e51b8152600401610c3090614d21565b61104581612d98565b6060611074612e1e565b61144e336129f0565b565b61145a6001610edc565b6001600160a01b0316336001600160a01b0316146114ba5760405162461bcd60e51b815260206004820152601960248201527f43414c4c45525f4e4f545f434f4f4c444f574e5f41444d494e000000000000006044820152606401610c30565b61104581612e49565b600954600690811161152e5760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b6064820152608401610c30565b600955565b600060608060008060006060611547612e7e565b61154f612e1e565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b604080516001808252818301909252600091829190816020015b6115c0604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b8152602001906001900390816115935790505090506040518060600160405280306001600160a01b031681526020016115f8856113b1565b815260200161160660025490565b8152508160008151811061161c5761161c614f33565b60200260200101819052506116318382612ea9565b6001600160a01b0384166000908152603d6020526040902054610fd79190614df2565b6000610fd7338484612fb7565b606060048054610e4190614d81565b610f443383836126fb565b6116856002610edc565b6001600160a01b0316336001600160a01b0316146116b55760405162461bcd60e51b8152600401610c3090614dbb565b6116c08484846126fb565b506116cf8484610f3f8461213a565b50505050565b6001600160a01b0386166116fb5760405162461bcd60e51b8152600401610c3090614e3e565b8342111561171b5760405162461bcd60e51b8152600401610c3090614e65565b60006117a8611728612d5e565b7fd46e8b93b5190df6403875402a5c13897b72d2a576da5d1bfea20a63638d216e89896117728c6001600160a01b0316600090815260446020526040902080546001810190915590565b6040805160208101959095526001600160a01b039384169085015291166060830152608082015260a0810188905260c001611314565b90506117b681858585612d68565b6001600160a01b0316876001600160a01b0316146117e65760405162461bcd60e51b8152600401610c3090614f08565b6117f287876000612c36565b6117fe87876001612c36565b50505050505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091908381101561188c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610c30565b610ff78286868403612015565b600033610ed28185856128bf565b60008281526045602052604090205482906001600160a01b031633146119075760405162461bcd60e51b815260206004820152601560248201527421a0a62622a92fa727aa2fa927a622afa0a226a4a760591b6044820152606401610c30565b60008381526046602090815260409182902080546001600160a01b0319166001600160a01b03861690811790915591518581527fc3d1bf52795a20771ee6de3e59948fd83e10db956122d4709a3b86c512963855910160405180910390a2505050565b610f893383836130ab565b61197f6000610edc565b6001600160a01b0316336001600160a01b0316146119af5760405162461bcd60e51b8152600401610c3090614d21565b6051805460ff60d81b191690556040517fcdee157e87ba915be681d4fa3f3d511afe7348eca06448a3accd6ac227fa40af90600090a1565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611a575760405162461bcd60e51b815260206004820152601560248201527427a7262cafa2a6a4a9a9a4a7a72fa6a0a720a3a2a960591b6044820152606401610c30565b60005b8151811015611a9857600254828281518110611a7857611a78614f33565b602090810291909101810151015280611a9081614f49565b915050611a5a565b5061104581613270565b6000611ab66051546001600160d81b031690565b6001600160d81b0316670de0b6b3a7640000611ad285856133de565b611adc9190614e05565b610fd79190614e1c565b6000611af26002610edc565b6001600160a01b0316336001600160a01b031614611b225760405162461bcd60e51b8152600401610c3090614dbb565b610fd4848484612fb7565b6001600160a01b038716611b535760405162461bcd60e51b8152600401610c3090614e3e565b83421115611b735760405162461bcd60e51b8152600401610c3090614e65565b6001600160a01b0387811660008181526044602090815260408083205481517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9938101939093529082019390935292891660608401526080830188905260a0830182905260c083018790529091611c029060e00160405160208183030381529060405280519060200120613460565b9050611c1081868686612d68565b6001600160a01b0316896001600160a01b031614611c405760405162461bcd60e51b8152600401610c3090614f08565b6001600160a01b0389166000908152604460205260409020600183019055611c69898989612015565b505050505050505050565b610f89338383612c36565b611c8a3384846126fb565b50610f443384610f3f8461213a565b60405163d505accf60e01b8152336004820152306024820152604481018690526064810185905260ff8416608482015260a4810183905260c481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d505accf9060e401600060405180830381600087803b158015611d2557600080fd5b505af1925050508015611d36575060015b611d6c573d808015611d64576040519150601f19603f3d011682016040523d82523d6000602084013e611d69565b606091505b50505b611d773333876130ab565b5050505050565b60008181526046602052604090205481906001600160a01b03163314611de65760405162461bcd60e51b815260206004820152601d60248201527f43414c4c45525f4e4f545f50454e44494e475f524f4c455f41444d494e0000006044820152606401610c30565b60008281526045602090815260408083208054336001600160a01b0319918216811790925560468452938290208054909416909355518481527f83a9ddad961dcb7c6894c9585a16ff7792c2ec8281256a3cc7303ae830152dcf91015b60405180910390a25050565b6000821580611e5c575081155b15611e6957506000610e2c565b611e7582600019614e1c565b831115611ec45760405162461bcd60e51b815260206004820152601c60248201527f4d4154485f4d554c5449504c49434154494f4e5f4f564552464c4f57000000006044820152606401610c30565b612710611adc8385614e05565b6000610fd783600181611eec670de0b6b3a764000087614e05565b611ef69190614df2565b611f009190614d6e565b611f0a9190614e1c565b61348d565b806001600160d81b0316600003611f5d5760405162461bcd60e51b81526020600482015260126024820152715a45524f5f45584348414e47455f5241544560701b6044820152606401610c30565b605180546001600160d81b0319166001600160d81b0383169081179091556040519081527fa9c433f9734baa3cf48b209454bb0ace054e191f677ba50e74b696c0d35ef262906020015b60405180910390a150565b6040516001600160a01b038316602482015260448101829052610f4490849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526134f6565b6001600160a01b0383166120775760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610c30565b6001600160a01b0382166120d85760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610c30565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006001600160681b038211156121a35760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663034206269747360c81b6064820152608401610c30565b5090565b806001600160681b03166000036121d05760405162461bcd60e51b8152600401610c3090614f62565b6001600160a01b0383166000908152603e602090815260409182902082518084019093525464ffffffffff81168352600160281b90046001600160d81b031690820152605154600160d81b900460ff1661231057604f54815161223a919064ffffffffff16614df2565b4210156122815760405162461bcd60e51b815260206004820152601560248201527424a729aaa32324a1a4a2a72a2fa1a7a7a62227aba760591b6044820152606401610c30565b604f5481517f0000000000000000000000000000000000000000000000000000000000000000916122b89164ffffffffff16614df2565b6122c29042614d6e565b11156123105760405162461bcd60e51b815260206004820152601760248201527f554e5354414b455f57494e444f575f46494e49534845440000000000000000006044820152606401610c30565b600061231b856113b1565b605154909150600090600160d81b900460ff166123455782602001516001600160d81b0316612347565b815b9050806000036123995760405162461bcd60e51b815260206004820152601b60248201527f494e56414c49445f5a45524f5f4d41585f52454445454d41424c4500000000006044820152606401610c30565b600081856001600160681b0316116123ba57846001600160681b03166123bc565b815b90506123ca878460016135c8565b5060006123d68261121d565b90506123ea886123e58461213a565b613677565b845164ffffffffff16156124b7578185602001516001600160d81b03166124119190614d6e565b600003612436576001600160a01b0388166000908152603e60205260408120556124b7565b61243f826137f3565b6001600160a01b0389166000908152603e602052604090205461247b916001600160b81b031690600160281b90046001600160d81b0316614f8f565b6001600160a01b0389166000908152603e6020526040902080546001600160d81b0392909216600160281b0264ffffffffff9092169190911790555b6124eb6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168883611fb2565b866001600160a01b0316886001600160a01b03167f3f693fff038bb8a046aa76d9516190ac7444f7d69cf952c4cbdc086fdef2d6fc8385604051612539929190918252602082015260400190565b60405180910390a35050505050505050565b61256c60408051606081018252600080825260208201819052909182015290565b6001600160a01b038216600090815260208181526040808320815160808101835281546001600160681b03811682526001600160481b03600160681b8204811695830195909552600160b01b8104909416928101929092529091606083019060ff600160f81b9091041660038111156125e7576125e7614e91565b60038111156125f8576125f8614e91565b815250509050604051806060016040528082602001516001600160481b0316815260200182604001516001600160481b031681526020018260600151600381111561264557612645614e91565b90529392505050565b60008082600181111561266357612663614e91565b036126b55760018360400151600381111561268057612680614e91565b1660ff166000036126925760006126ae565b6001600160a01b03808516600090815260476020526040902054165b9050610fd7565b6002836040015160038111156126cd576126cd614e91565b10156126da576000610fd4565b5050506001600160a01b039081166000908152604860205260409020541690565b60008160000361271d5760405162461bcd60e51b8152600401610c3090614f62565b60006127338561272c876113b1565b60006135c8565b905060008184116127445783612746565b815b9050806000036127685760405162461bcd60e51b8152600401610c3090614f62565b6127728183614d6e565b6001600160a01b038088166000908152603d60205260409020919091556127dd907f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000008784612bfe565b846001600160a01b0316866001600160a01b03167f9310ccfcb8de723f578a9e4282ea9f521f05ae40dc08f3068dfad528a65ee3c78360405161282291815260200190565b60405180910390a395945050505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981146116cf57818110156128b25760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610c30565b6116cf8484848403612015565b60006128ca846113b1565b90506128d8848260016135c8565b50826001600160a01b0316846001600160a01b0316146129e55760006128fd846113b1565b905061290b848260016135c8565b506001600160a01b0385166000908152603e602090815260409182902082518084019093525464ffffffffff8116808452600160281b9091046001600160d81b031691830191909152156129e25783830361297e576001600160a01b0386166000908152603e60205260408120556129e2565b60208101516001600160d81b03166129968585614d6e565b10156129e2576129a68484614d6e565b6001600160a01b0387166000908152603e6020526040902080546001600160d81b0392909216600160281b0264ffffffffff9092169190911790555b50505b6116cf84848461385c565b60006129fb826113b1565b905080600003612a4d5760405162461bcd60e51b815260206004820152601b60248201527f494e56414c49445f42414c414e43455f4f4e5f434f4f4c444f574e00000000006044820152606401610c30565b60408051808201825264ffffffffff42811682526001600160d81b0380851660208085019182526001600160a01b0388166000818152603e9092529086902094519151909216600160281b0292169190911790915590517f8a05f911d8ab7fc50fec37ef4ba7f9bfcb1a3c191c81dcd824ad0946c4e20d6590611e439084815260200190565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015612b2c57507f000000000000000000000000000000000000000000000000000000000000000046145b15612b5657507f000000000000000000000000000000000000000000000000000000000000000090565b611074604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b6040516001600160a01b03808516602483015283166044820152606481018290526116cf9085906323b872dd60e01b90608401611fde565b6000836001600160a01b0316836001600160a01b031614612c575782612c5a565b60005b90506000612c678561254b565b90506000612c7686838661264e565b9050806001600160a01b0316836001600160a01b031603612c9957505050505050565b6001600160a01b03818116151590841615156000612cb689613a95565b90508215612ccb57612ccb816000868a613aa0565b8115612cde57612cde600082888a613aa0565b612ce9898888613b6a565b82151582151514612d0857612d0889612d03878a86613c0d565b613d2d565b856001600160a01b0316896001600160a01b03167fe8d51c8e11bd570db1734c8ec775785330e77007feed45c43b608ef33ff914bd89604051612d4b9190614fb6565b60405180910390a3505050505050505050565b600061107461106a565b600080600080612d7a88888888613dcd565b925092509250612d8a8282613e9c565b50909150505b949350505050565b6127108110612de95760405162461bcd60e51b815260206004820152601b60248201527f494e56414c49445f534c415348494e475f50455243454e5441474500000000006044820152606401610c30565b60508190556040518181527fb79c2d6c7f5c95eec9dc05affc0ed002620a4ec6d72b7b0744cc8638168c600a90602001611fa7565b60606110747f0000000000000000000000000000000000000000000000000000000000000000613f55565b604f8190556040518181527fbbf67247b5c97564e30ffc0a355e71c006836de7b9149e09e3d5d6054cb0335590602001611fa7565b60606110747f0000000000000000000000000000000000000000000000000000000000000000613f55565b600080805b8351811015612faf576000603c6000868481518110612ecf57612ecf614f33565b602090810291909101810151516001600160a01b031682528101919091526040016000908120600181015481548851929450612f3d926001600160801b0380831692600160801b900416908a9088908110612f2c57612f2c614f33565b602002602001015160400151613f94565b9050612f8e868481518110612f5457612f54614f33565b602002602001015160200151828460020160008b6001600160a01b03166001600160a01b031681526020019081526020016000205461409f565b612f989085614df2565b935050508080612fa790614f49565b915050612eae565b509392505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461305a5760405162461bcd60e51b815260206004820181905260248201527f5245574152445f544f4b454e5f49535f4e4f545f5354414b45445f544f4b454e6044820152606401610c30565b600061307085613069876113b1565b60016135c8565b905060008184116130815783613083565b815b905080156130a2576130968630836126fb565b506130a23086836130ab565b95945050505050565b605154600160d81b900460ff16156130f85760405162461bcd60e51b815260206004820152601060248201526f534c415348494e475f4f4e474f494e4760801b6044820152606401610c30565b806000036131185760405162461bcd60e51b8152600401610c3090614f62565b6000613123836113b1565b9050600061313b84308461313660025490565b6140cb565b905080156131be576001600160a01b0384166000908152603d6020526040902054613167908290614df2565b6001600160a01b0385166000818152603d60209081526040918290209390935580519182529181018390527f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a76910160405180910390a15b60006131c9846113d5565b90506132006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016873087612bfe565b6132128561320d8361213a565b61418c565b846001600160a01b0316866001600160a01b03167f6c86f3fd5118b3aa8bb4f389a617046de0a3d3d477de1a1673d227f802f616dc8684604051613260929190918252602082015260400190565b60405180910390a3505050505050565b60005b8151811015610f89576000603c600084848151811061329457613294614f33565b6020026020010151604001516001600160a01b03166001600160a01b0316815260200190815260200160002090506133078383815181106132d7576132d7614f33565b602002602001015160400151828585815181106132f6576132f6614f33565b6020026020010151602001516142f1565b5082828151811061331a5761331a614f33565b60209081029190910101515181546fffffffffffffffffffffffffffffffff19166001600160801b03909116178155825183908390811061335d5761335d614f33565b6020026020010151604001516001600160a01b03167f87fa03892a0556cb6b8f97e6d533a150d4d55fcbf275fff5fa003fa636bcc7fa8484815181106133a5576133a5614f33565b602090810291909101810151516040516001600160801b0390911681520160405180910390a250806133d681614f49565b915050613273565b6000806133ea8461254b565b9050600083600181111561340057613400614e91565b61340b906001614fc4565b8260400151600381111561342157613421614e91565b1660ff1660001461343357600061343c565b61343c85613a95565b9050600061344a83866143a9565b90506134568183614df2565b9695505050505050565b6000610e2c61346d612ad3565b8360405161190160f01b8152600281019290925260228201526042902090565b60006001600160d81b038211156121a35760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663136206269747360c81b6064820152608401610c30565b600061354b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143e89092919063ffffffff16565b805190915015610f4457808060200190518101906135699190614fdd565b610f445760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c30565b6000806135da85308661313660025490565b6001600160a01b0386166000908152603d602052604081205491925090613602908390614df2565b905081156130a257831561362c576001600160a01b0386166000908152603d602052604090208190555b604080516001600160a01b0388168152602081018490527f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a76910160405180910390a195945050505050565b6001600160a01b0382166136d75760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610c30565b6001600160a01b0382166000908152602081905260409020546001600160681b039081169082168110156137585760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610c30565b6001600160a01b03831660008181526020818152604080832080546001600160681b0319168787036001600160681b03908116919091179091556002805491881691829003905590519081529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610f44836000836001600160681b03166000866001600160681b03166143f7565b60006001600160b81b038211156121a35760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663834206269747360c81b6064820152608401610c30565b6001600160a01b0383166138c05760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610c30565b6001600160a01b0382166139225760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610c30565b816001600160a01b0316836001600160a01b031614613a50576001600160a01b038084166000908152602081905260408082205492851682529020546001600160681b039182169116828210156139ca5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610c30565b6001600160a01b038516600090815260208190526040902080546001600160681b0319168484036001600160681b0316179055613a078382614fff565b6001600160a01b038516600090815260208190526040902080546001600160681b0319166001600160681b03928316179055613a4d9086908690858116908516876143f7565b50505b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161212d91815260200190565b6000610e2c826113b1565b6001600160a01b038216156116cf578383146116cf576000613acf613aca6402540be40087614e1c565b61442c565b90506000613ae5613aca6402540be40087614e1c565b90506000613af28561254b565b90506000846001811115613b0857613b08614e91565b03613b3b5781838260200151613b1e919061501f565b613b28919061503f565b6001600160481b03166020820152613b60565b80518290613b4a90859061501f565b613b54919061503f565b6001600160481b031681525b6117fe8582613d2d565b6000836001600160a01b0316826001600160a01b031614613b8b5781613b8e565b60005b90506000836001811115613ba457613ba4614e91565b03613bdc576001600160a01b03848116600090815260476020526040902080546001600160a01b0319169183169190911790556116cf565b6001600160a01b03938416600090815260486020526040902080546001600160a01b03191691909416179092555050565b613c2e60408051606081018252600080825260208201819052909182015290565b8115613cad57826001811115613c4657613c46614e91565b613c51906001614fc4565b84604001516003811115613c6757613c67614e91565b1760ff166003811115613c7c57613c7c614e91565b84604001906003811115613c9257613c92614e91565b90816003811115613ca557613ca5614e91565b905250613d25565b6003836001811115613cc157613cc1614e91565b613ccc906001614fc4565b1884604001516003811115613ce357613ce3614e91565b1660ff166003811115613cf857613cf8614e91565b84604001906003811115613d0e57613d0e614e91565b90816003811115613d2157613d21614e91565b9052505b509192915050565b6001600160a01b03821660009081526020818152604091829020835181549285015171ffffffffffffffffffffffffffffffffffff60681b19909316600160681b6001600160481b039283160268ffffffffffffffffff60b01b191617600160b01b91909316029190911780825591830151909182906001600160f81b0316600160f81b836003811115613dc357613dc3614e91565b0217905550505050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115613e085750600091506003905082613e92565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015613e5c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613e8857506000925060019150829050613e92565b9250600091508190505b9450945094915050565b6000826003811115613eb057613eb0614e91565b03613eb9575050565b6001826003811115613ecd57613ecd614e91565b03613eeb5760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115613eff57613eff614e91565b03613f205760405163fce698f760e01b815260048101829052602401610c30565b6003826003811115613f3457613f34614e91565b03610f89576040516335e2f38360e21b815260048101829052602401610c30565b60606000613f6283614494565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000831580613fa1575081155b80613fb4575042836001600160801b0316145b80613fe857507f0000000000000000000000000000000000000000000000000000000000000000836001600160801b031610155b15613ff4575083612d90565b60007f000000000000000000000000000000000000000000000000000000000000000042116140235742614045565b7f00000000000000000000000000000000000000000000000000000000000000005b9050600061405c6001600160801b03861683614d6e565b9050868461406c6012600a615143565b614076848a614e05565b6140809190614e05565b61408a9190614e1c565b6140949190614df2565b979650505050505050565b60006140ad6012600a615143565b6140b78385614d6e565b6140c19086614e05565b610fd49190614e1c565b6001600160a01b038084166000908152603c6020908152604080832093881683526002840190915281205490919082806141068885886142f1565b90508083146141805786156141235761412087828561409f565b91505b6001600160a01b03808a1660008181526002870160205260409081902084905551918a16917fbb123b5c06d5408bbea3c4fef481578175cfb432e3b482c6186f02ed9086585b906141779085815260200190565b60405180910390a35b50979650505050505050565b6001600160a01b0382166141e25760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610c30565b6001600160a01b038216600090815260208190526040812054600280546001600160681b0392831693928516929061421b908490614df2565b90915550506001600160a01b038316600090815260208190526040812080548492906142519084906001600160681b0316614fff565b92506101000a8154816001600160681b0302191690836001600160681b03160217905550826001600160a01b031660006001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516142c891906001600160681b0391909116815260200190565b60405180910390a3610f446000846000846001600160681b0316866001600160681b03166143f7565b6001820154825460009190600160801b90046001600160801b03164281900361431c57509050610fd7565b84546000906143379084906001600160801b03168488613f94565b905082811461438657600186018190556040518181526001600160a01b038816907f5777ca300dfe5bead41006fbce4389794dbc0ed8d6cccebfaf94630aa04184bc9060200160405180910390a25b85546001600160801b03428116600160801b029116178655925050509392505050565b6000808260018111156143be576143be614e91565b146143ca5782516143d0565b82602001515b610fd7906001600160481b03166402540be400614e05565b6060610fd484846000856144bc565b614404858585858561458c565b6053546001600160a01b0316801561442457614424818787878787614599565b505050505050565b60006001600160481b038211156121a35760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203760448201526532206269747360d01b6064820152608401610c30565b600060ff8216601f811115610e2c57604051632cd44ac360e21b815260040160405180910390fd5b60608247101561451d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610c30565b600080866001600160a01b03168587604051614539919061514f565b60006040518083038185875af1925050503d8060008114614576576040519150601f19603f3d011682016040523d82523d6000602084013e61457b565b606091505b509150915061409487838387614603565b611d77858585858561467c565b604051635b9c4cf160e01b80825260048201879052602482018690526044820185905260648201849052608482018390529062035b60905a60008060a48460008e88f16145f757826040603f83020410156145f7573d6000833e3d82fd5b50505050505050505050565b6060831561467257825160000361466b576001600160a01b0385163b61466b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c30565b5081612d90565b612d908383614779565b836001600160a01b0316856001600160a01b03160315611d77576001600160a01b038516156147105760006146b08661254b565b905060006146be8386614d6e565b90506000826040015160038111156146d8576146d8614e91565b1461470d576146f585826146ee8a86600061264e565b6000613aa0565b61470d85826147068a86600161264e565b6001613aa0565b50505b6001600160a01b03841615611d7757600061472a8561254b565b905060006147388385614df2565b905060008260400151600381111561475257614752614e91565b146117fe5761476884826146ee8986600061264e565b6117fe84826147068986600161264e565b8151156147895781518083602001fd5b8060405162461bcd60e51b8152600401610c309190614839565b80356001600160a01b03811681146147ba57600080fd5b919050565b600080604083850312156147d257600080fd5b6147db836147a3565b946020939093013593505050565b60005b838110156148045781810151838201526020016147ec565b50506000910152565b600081518084526148258160208601602086016147e9565b601f01601f19169290920160200192915050565b602081526000610fd7602083018461480d565b60006020828403121561485e57600080fd5b610fd7826147a3565b60006020828403121561487957600080fd5b5035919050565b60008060006060848603121561489557600080fd5b61489e846147a3565b92506148ac602085016147a3565b9150604084013590509250925092565b600080604083850312156148cf57600080fd5b6148d8836147a3565b91506148e6602084016147a3565b90509250929050565b8035600281106147ba57600080fd5b803560ff811681146147ba57600080fd5b600080600080600080600060e0888a03121561492a57600080fd5b614933886147a3565b9650614941602089016147a3565b955061494f604089016148ef565b945060608801359350614964608089016148fe565b925060a0880135915060c0880135905092959891949750929550565b6000806040838503121561499357600080fd5b61499c836147a3565b91506148e6602084016148ef565b60ff60f81b881681526000602060e0818401526149ca60e084018a61480d565b83810360408501526149dc818a61480d565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015614a2e57835183529284019291840191600101614a12565b50909c9b505050505050505050505050565b60008060008060808587031215614a5657600080fd5b614a5f856147a3565b9350614a6d602086016147a3565b93969395505050506040820135916060013590565b60008060008060008060c08789031215614a9b57600080fd5b614aa4876147a3565b9550614ab2602088016147a3565b945060408701359350614ac7606088016148fe565b92506080870135915060a087013590509295509295509295565b60008060408385031215614af457600080fd5b823591506148e6602084016147a3565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715614b3d57614b3d614b04565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715614b6c57614b6c614b04565b604052919050565b60006020808385031215614b8757600080fd5b823567ffffffffffffffff80821115614b9f57600080fd5b818501915085601f830112614bb357600080fd5b813581811115614bc557614bc5614b04565b614bd3848260051b01614b43565b81815284810192506060918202840185019188831115614bf257600080fd5b938501935b828510156141805780858a031215614c0f5760008081fd5b614c17614b1a565b85356001600160801b0381168114614c2f5760008081fd5b815285870135878201526040614c468188016147a3565b9082015284529384019392850192614bf7565b600080600080600080600060e0888a031215614c7457600080fd5b614c7d886147a3565b9650614c8b602089016147a3565b95506040880135945060608801359350614964608089016148fe565b600080600060608486031215614cbc57600080fd5b614cc5846147a3565b95602085013595506040909401359392505050565b600080600080600060a08688031215614cf257600080fd5b8535945060208601359350614d09604087016148fe565b94979396509394606081013594506080013592915050565b60208082526019908201527f43414c4c45525f4e4f545f534c415348494e475f41444d494e00000000000000604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610e2c57610e2c614d58565b600181811c90821680614d9557607f821691505b602082108103614db557634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526017908201527f43414c4c45525f4e4f545f434c41494d5f48454c504552000000000000000000604082015260600190565b80820180821115610e2c57610e2c614d58565b8082028115828204841417610e2c57610e2c614d58565b600082614e3957634e487b7160e01b600052601260045260246000fd5b500490565b6020808252600d908201526c24a72b20a624a22fa7aba722a960991b604082015260600190565b60208082526012908201527124a72b20a624a22fa2ac2824a920aa24a7a760711b604082015260600190565b634e487b7160e01b600052602160045260246000fd5b60028110614ec557634e487b7160e01b600052602160045260246000fd5b9052565b8681526001600160a01b0386811660208301528516604082015260c08101614ef46060830186614ea7565b608082019390935260a00152949350505050565b602080825260119082015270494e56414c49445f5349474e415455524560781b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060018201614f5b57614f5b614d58565b5060010190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b6001600160d81b03828116828216039080821115614faf57614faf614d58565b5092915050565b60208101610e2c8284614ea7565b60ff8181168382160190811115610e2c57610e2c614d58565b600060208284031215614fef57600080fd5b81518015158114610fd757600080fd5b6001600160681b03818116838216019080821115614faf57614faf614d58565b6001600160481b03828116828216039080821115614faf57614faf614d58565b6001600160481b03818116838216019080821115614faf57614faf614d58565b600181815b8085111561509a57816000190482111561508057615080614d58565b8085161561508d57918102915b93841c9390800290615064565b509250929050565b6000826150b157506001610e2c565b816150be57506000610e2c565b81600181146150d457600281146150de576150fa565b6001915050610e2c565b60ff8411156150ef576150ef614d58565b50506001821b610e2c565b5060208310610133831016604e8410600b841016171561511d575081810a610e2c565b615127838361505f565b806000190482111561513b5761513b614d58565b029392505050565b6000610fd783836150a2565b600082516151618184602087016147e9565b919091019291505056fea2646970667358221220385b96f1c8f473a813ebd23eecf2eaf0bec52cdecaeeff8cb048e4b8d7ea13d264736f6c634300081500330000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae90000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9000000000000000000000000000000000000000000000000000000000002a30000000000000000000000000025f2226b597e8f9514b3f68f00f494cf4f2864910000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a00000000000000000000000000000000000000000000000000000000bc180c38
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061046a5760003560e01c80637e90d7ef1161024c578063ab406fe611610146578063dc937e1c116100c3578063ecd9ba8211610087578063ecd9ba8214610b50578063f036bc6814610b63578063f11b818814610b77578063f34d96da14610bd9578063fde9eb6914610be157600080fd5b8063dc937e1c14610ad9578063dd62ed3e14610aec578063dde43cba14610b25578063e6aa216c14610b2c578063eab5231814610b3d57600080fd5b8063b9844d8d1161010a578063b9844d8d14610a64578063c18f539a14610a84578063cbcbb50714610a97578063d505accf14610abe578063dbc0ed8a14610ad157600080fd5b8063ab406fe614610a10578063adc9772e14610a23578063aff05aa914610a36578063b2a5dbfa14610a3e578063b2f4201d14610a5157600080fd5b806395d89b41116101d4578063a095ac1911610198578063a095ac19146109a8578063a457c2d7146109bb578063a9059cbb146109ce578063aa9fbe02146109e1578063aaf5eb6814610a0857600080fd5b806395d89b411461094b57806399248ea7146109535780639a99b4f01461097a5780639c9b51541461098d5780639e3ffce0146109a057600080fd5b80638dbefee21161021b5780638dbefee2146108c85780638e9b2ca4146108db578063919cd40f146108ea578063946776cd14610911578063955e18af1461093857600080fd5b80637e90d7ef1461087d5780638129fc1c1461089d57806384b0196e146108a55780638c9a281d146108c057600080fd5b80633644e515116103685780636198e135116102e557806372b49d63116102a957806372b49d63146107cc57806374011f5614610847578063781603761461085a578063787a08a6146108625780637b5b11571461086a57600080fd5b80636198e135146107d4578063657f0cde146107fb5780636f50458d1461080e57806370a0823114610821578063727a5d571461083457600080fd5b80634cdad5061161032c5780634cdad50614610773578063570a97141461078657806358146d17146107925780635c19a95c146107b9578063616e0bf9146107cc57600080fd5b80633644e515146106f557806339509351146106fd57806341cbf54a1461071057806345755dd6146107375780634575e69b1461074a57600080fd5b80631e9a6950116103f657806330adf81f116103ba57806330adf81f1461062d578063312f6b8314610654578063313ce5671461067b5780633373ee4c14610690578063359c4a96146106ce57600080fd5b80631e9a6950146105b957806320fb80b5146105cc57806323b872dd146105df578063250201db146105f25780632a8b36681461060557600080fd5b8063111fd88b1161043d578063111fd88b1461052b578063112d037c14610556578063169db77d1461056b578063174ed5421461059e57806318160ddd146105b157600080fd5b806302fb4d851461046f57806306fdde0314610495578063091030c3146104aa578063095ea7b314610508575b600080fd5b61048261047d3660046147bf565b610bf4565b6040519081526020015b60405180910390f35b61049d610e32565b60405161048c9190614839565b6104e36104b836600461484c565b603e6020526000908152604090205464ffffffffff811690600160281b90046001600160d81b031682565b6040805164ffffffffff90931683526001600160d81b0390911660208301520161048c565b61051b6105163660046147bf565b610ec4565b604051901515815260200161048c565b61053e610539366004614867565b610edc565b6040516001600160a01b03909116815260200161048c565b610569610564366004614880565b610ef7565b005b61057e61057936600461484c565b610f49565b604080516001600160a01b0393841681529290911660208301520161048c565b60535461053e906001600160a01b031681565b600254610482565b6105696105c73660046147bf565b610f7b565b6104826105da366004614880565b610f8d565b61051b6105ed366004614880565b610fde565b61056961060036600461484c565b611002565b61061861061336600461484c565b611048565b6040805192835260208301919091520161048c565b6104827f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61053e7f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae981565b60125b60405160ff909116815260200161048c565b61048261069e3660046148bc565b6001600160a01b038082166000908152603c60209081526040808320938616835260029093019052205492915050565b6104827f000000000000000000000000000000000000000000000000000000000002a30081565b61048261106a565b61051b61070b3660046147bf565b611079565b6104827fd46e8b93b5190df6403875402a5c13897b72d2a576da5d1bfea20a63638d216e81565b610569610745366004614867565b6110b8565b61053e610758366004614867565b6000908152604660205260409020546001600160a01b031690565b610482610781366004614867565b61121d565b6104826402540be40081565b6107a1670de0b6b3a764000081565b6040516001600160d81b03909116815260200161048c565b6105696107c736600461484c565b611248565b604f54610482565b6104827f0000000000000000000000000000000000000000000000000de0b6b3a764000081565b61056961080936600461490f565b611260565b61053e61081c366004614980565b61139c565b61048261082f36600461484c565b6113b1565b610482610842366004614867565b6113d5565b610569610855366004614867565b6113f8565b61049d61143b565b610569611445565b610569610878366004614867565b611450565b61048261088b36600461484c565b603d6020526000908152604090205481565b6105696114c3565b6108ad611533565b60405161048c97969594939291906149aa565b610482600081565b6104826108d636600461484c565b611579565b610482670de0b6b3a764000081565b6104827f000000000000000000000000000000000000000000000000000000012180763b81565b61053e7f00000000000000000000000025f2226b597e8f9514b3f68f00f494cf4f28649181565b6104826109463660046147bf565b611654565b61049d611661565b61053e7f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae981565b6105696109883660046147bf565b611670565b61056961099b366004614a40565b61167b565b610482600181565b6105696109b6366004614a82565b6116d5565b61051b6109c93660046147bf565b611807565b61051b6109dc3660046147bf565b611899565b6104827f6e77642f8f60cdece0498bfeeb2f06ccfef0e8f86d28a1b6255c5e48f1d72a0381565b61067e601281565b610569610a1e366004614ae1565b6118a7565b610569610a313660046147bf565b61196a565b610569611975565b610569610a4c366004614b74565b6119e7565b610482610a5f366004614980565b611aa2565b610482610a7236600461484c565b60446020526000908152604090205481565b610482610a92366004614880565b611ae6565b61053e7f0000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a81565b610569610acc366004614c59565b611b2d565b610482600281565b610569610ae7366004614980565b611c74565b610482610afa3660046148bc565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6006610482565b6051546001600160d81b03166107a1565b610569610b4b366004614ca7565b611c7f565b610569610b5e366004614cda565b611c99565b60515461051b90600160d81b900460ff1681565b610bb3610b8536600461484c565b603c60205260009081526040902080546001909101546001600160801b0380831692600160801b9004169083565b604080516001600160801b0394851681529390921660208401529082015260600161048c565b605054610482565b610569610bef366004614867565b611d7e565b6000610c006000610edc565b6001600160a01b0316336001600160a01b031614610c395760405162461bcd60e51b8152600401610c3090614d21565b60405180910390fd5b605154600160d81b900460ff1615610c935760405162461bcd60e51b815260206004820152601d60248201527f50524556494f55535f534c415348494e475f4e4f545f534554544c45440000006044820152606401610c30565b60008211610cd15760405162461bcd60e51b815260206004820152600b60248201526a16915493d7d05353d5539560aa1b6044820152606401610c30565b6000610cdc60025490565b90506000610ce98261121d565b90506000610d0260505483611e4f90919063ffffffff16565b905080851115610d10578094505b7f0000000000000000000000000000000000000000000000000de0b6b3a7640000610d3b8684614d6e565b1015610d805760405162461bcd60e51b815260206004820152601460248201527352454d41494e494e475f4c545f4d494e494d554d60601b6044820152606401610c30565b6051805460ff60d81b1916600160d81b179055610dae610da9610da38785614d6e565b85611ed1565b611f0f565b610de26001600160a01b037f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9168787611fb2565b856001600160a01b03167f4ed05e9673c26d2ed44f7ef6a7f2942df0ee3b5e1e17db4b99f9dcd261a339cd86604051610e1d91815260200190565b60405180910390a28493505050505b92915050565b606060038054610e4190614d81565b80601f0160208091040260200160405190810160405280929190818152602001828054610e6d90614d81565b8015610eba5780601f10610e8f57610100808354040283529160200191610eba565b820191906000526020600020905b815481529060010190602001808311610e9d57829003601f168201915b5050505050905090565b600033610ed2818585612015565b5060019392505050565b6000908152604560205260409020546001600160a01b031690565b610f016002610edc565b6001600160a01b0316336001600160a01b031614610f315760405162461bcd60e51b8152600401610c3090614dbb565b610f448383610f3f8461213a565b6121a7565b505050565b6000806000610f578461254b565b9050610f658482600061264e565b610f718583600161264e565b9250925050915091565b610f893383610f3f8461213a565b5050565b6000610f996002610edc565b6001600160a01b0316336001600160a01b031614610fc95760405162461bcd60e51b8152600401610c3090614dbb565b610fd48484846126fb565b90505b9392505050565b600033610fec858285612833565b610ff78585856128bf565b506001949350505050565b61100c6002610edc565b6001600160a01b0316336001600160a01b03161461103c5760405162461bcd60e51b8152600401610c3090614dbb565b611045816129f0565b50565b600080611056836000611aa2565b611061846001611aa2565b91509150915091565b6000611074612ad3565b905090565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190610ed290829086906110b3908790614df2565b612015565b7f0000000000000000000000000000000000000000000000000de0b6b3a764000081101561111c5760405162461bcd60e51b8152602060048201526011602482015270414d4f554e545f4c545f4d494e494d554d60781b6044820152606401610c30565b600061112760025490565b90507f0000000000000000000000000000000000000000000000000de0b6b3a764000081101561118d5760405162461bcd60e51b81526020600482015260116024820152705348415245535f4c545f4d494e494d554d60781b6044820152606401610c30565b60006111988261121d565b90506111b0610da96111aa8584614df2565b84611ed1565b6111e56001600160a01b037f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae916333086612bfe565b6040518381527f278e51d3323fbf18b9fb8df3f8b97e31b145bc1146c52e764cf4aa1bfc4ba17d9060200160405180910390a1505050565b6051546000906001600160d81b031661123e83670de0b6b3a7640000614e05565b610e2c9190614e1c565b61125433826000612c36565b61104533826001612c36565b6001600160a01b0387166112865760405162461bcd60e51b8152600401610c3090614e3e565b834211156112a65760405162461bcd60e51b8152600401610c3090614e65565b60006113496112b3612d5e565b7f6e77642f8f60cdece0498bfeeb2f06ccfef0e8f86d28a1b6255c5e48f1d72a038a8a8a6112fe8e6001600160a01b0316600090815260446020526040902080546001810190915590565b8b60405160200161131496959493929190614ec9565b6040516020818303038152906040528051906020012060405161190160f01b8152600281019290925260228201526042902090565b905061135781858585612d68565b6001600160a01b0316886001600160a01b0316146113875760405162461bcd60e51b8152600401610c3090614f08565b611392888888612c36565b5050505050505050565b6000610fd7836113ab8561254b565b8461264e565b6001600160a01b03166000908152602081905260409020546001600160681b031690565b605154600090670de0b6b3a76400009061123e906001600160d81b031684614e05565b6114026000610edc565b6001600160a01b0316336001600160a01b0316146114325760405162461bcd60e51b8152600401610c3090614d21565b61104581612d98565b6060611074612e1e565b61144e336129f0565b565b61145a6001610edc565b6001600160a01b0316336001600160a01b0316146114ba5760405162461bcd60e51b815260206004820152601960248201527f43414c4c45525f4e4f545f434f4f4c444f574e5f41444d494e000000000000006044820152606401610c30565b61104581612e49565b600954600690811161152e5760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b6064820152608401610c30565b600955565b600060608060008060006060611547612e7e565b61154f612e1e565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b604080516001808252818301909252600091829190816020015b6115c0604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b8152602001906001900390816115935790505090506040518060600160405280306001600160a01b031681526020016115f8856113b1565b815260200161160660025490565b8152508160008151811061161c5761161c614f33565b60200260200101819052506116318382612ea9565b6001600160a01b0384166000908152603d6020526040902054610fd79190614df2565b6000610fd7338484612fb7565b606060048054610e4190614d81565b610f443383836126fb565b6116856002610edc565b6001600160a01b0316336001600160a01b0316146116b55760405162461bcd60e51b8152600401610c3090614dbb565b6116c08484846126fb565b506116cf8484610f3f8461213a565b50505050565b6001600160a01b0386166116fb5760405162461bcd60e51b8152600401610c3090614e3e565b8342111561171b5760405162461bcd60e51b8152600401610c3090614e65565b60006117a8611728612d5e565b7fd46e8b93b5190df6403875402a5c13897b72d2a576da5d1bfea20a63638d216e89896117728c6001600160a01b0316600090815260446020526040902080546001810190915590565b6040805160208101959095526001600160a01b039384169085015291166060830152608082015260a0810188905260c001611314565b90506117b681858585612d68565b6001600160a01b0316876001600160a01b0316146117e65760405162461bcd60e51b8152600401610c3090614f08565b6117f287876000612c36565b6117fe87876001612c36565b50505050505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091908381101561188c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610c30565b610ff78286868403612015565b600033610ed28185856128bf565b60008281526045602052604090205482906001600160a01b031633146119075760405162461bcd60e51b815260206004820152601560248201527421a0a62622a92fa727aa2fa927a622afa0a226a4a760591b6044820152606401610c30565b60008381526046602090815260409182902080546001600160a01b0319166001600160a01b03861690811790915591518581527fc3d1bf52795a20771ee6de3e59948fd83e10db956122d4709a3b86c512963855910160405180910390a2505050565b610f893383836130ab565b61197f6000610edc565b6001600160a01b0316336001600160a01b0316146119af5760405162461bcd60e51b8152600401610c3090614d21565b6051805460ff60d81b191690556040517fcdee157e87ba915be681d4fa3f3d511afe7348eca06448a3accd6ac227fa40af90600090a1565b336001600160a01b037f0000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a1614611a575760405162461bcd60e51b815260206004820152601560248201527427a7262cafa2a6a4a9a9a4a7a72fa6a0a720a3a2a960591b6044820152606401610c30565b60005b8151811015611a9857600254828281518110611a7857611a78614f33565b602090810291909101810151015280611a9081614f49565b915050611a5a565b5061104581613270565b6000611ab66051546001600160d81b031690565b6001600160d81b0316670de0b6b3a7640000611ad285856133de565b611adc9190614e05565b610fd79190614e1c565b6000611af26002610edc565b6001600160a01b0316336001600160a01b031614611b225760405162461bcd60e51b8152600401610c3090614dbb565b610fd4848484612fb7565b6001600160a01b038716611b535760405162461bcd60e51b8152600401610c3090614e3e565b83421115611b735760405162461bcd60e51b8152600401610c3090614e65565b6001600160a01b0387811660008181526044602090815260408083205481517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9938101939093529082019390935292891660608401526080830188905260a0830182905260c083018790529091611c029060e00160405160208183030381529060405280519060200120613460565b9050611c1081868686612d68565b6001600160a01b0316896001600160a01b031614611c405760405162461bcd60e51b8152600401610c3090614f08565b6001600160a01b0389166000908152604460205260409020600183019055611c69898989612015565b505050505050505050565b610f89338383612c36565b611c8a3384846126fb565b50610f443384610f3f8461213a565b60405163d505accf60e01b8152336004820152306024820152604481018690526064810185905260ff8416608482015260a4810183905260c481018290527f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae96001600160a01b03169063d505accf9060e401600060405180830381600087803b158015611d2557600080fd5b505af1925050508015611d36575060015b611d6c573d808015611d64576040519150601f19603f3d011682016040523d82523d6000602084013e611d69565b606091505b50505b611d773333876130ab565b5050505050565b60008181526046602052604090205481906001600160a01b03163314611de65760405162461bcd60e51b815260206004820152601d60248201527f43414c4c45525f4e4f545f50454e44494e475f524f4c455f41444d494e0000006044820152606401610c30565b60008281526045602090815260408083208054336001600160a01b0319918216811790925560468452938290208054909416909355518481527f83a9ddad961dcb7c6894c9585a16ff7792c2ec8281256a3cc7303ae830152dcf91015b60405180910390a25050565b6000821580611e5c575081155b15611e6957506000610e2c565b611e7582600019614e1c565b831115611ec45760405162461bcd60e51b815260206004820152601c60248201527f4d4154485f4d554c5449504c49434154494f4e5f4f564552464c4f57000000006044820152606401610c30565b612710611adc8385614e05565b6000610fd783600181611eec670de0b6b3a764000087614e05565b611ef69190614df2565b611f009190614d6e565b611f0a9190614e1c565b61348d565b806001600160d81b0316600003611f5d5760405162461bcd60e51b81526020600482015260126024820152715a45524f5f45584348414e47455f5241544560701b6044820152606401610c30565b605180546001600160d81b0319166001600160d81b0383169081179091556040519081527fa9c433f9734baa3cf48b209454bb0ace054e191f677ba50e74b696c0d35ef262906020015b60405180910390a150565b6040516001600160a01b038316602482015260448101829052610f4490849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526134f6565b6001600160a01b0383166120775760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610c30565b6001600160a01b0382166120d85760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610c30565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006001600160681b038211156121a35760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663034206269747360c81b6064820152608401610c30565b5090565b806001600160681b03166000036121d05760405162461bcd60e51b8152600401610c3090614f62565b6001600160a01b0383166000908152603e602090815260409182902082518084019093525464ffffffffff81168352600160281b90046001600160d81b031690820152605154600160d81b900460ff1661231057604f54815161223a919064ffffffffff16614df2565b4210156122815760405162461bcd60e51b815260206004820152601560248201527424a729aaa32324a1a4a2a72a2fa1a7a7a62227aba760591b6044820152606401610c30565b604f5481517f000000000000000000000000000000000000000000000000000000000002a300916122b89164ffffffffff16614df2565b6122c29042614d6e565b11156123105760405162461bcd60e51b815260206004820152601760248201527f554e5354414b455f57494e444f575f46494e49534845440000000000000000006044820152606401610c30565b600061231b856113b1565b605154909150600090600160d81b900460ff166123455782602001516001600160d81b0316612347565b815b9050806000036123995760405162461bcd60e51b815260206004820152601b60248201527f494e56414c49445f5a45524f5f4d41585f52454445454d41424c4500000000006044820152606401610c30565b600081856001600160681b0316116123ba57846001600160681b03166123bc565b815b90506123ca878460016135c8565b5060006123d68261121d565b90506123ea886123e58461213a565b613677565b845164ffffffffff16156124b7578185602001516001600160d81b03166124119190614d6e565b600003612436576001600160a01b0388166000908152603e60205260408120556124b7565b61243f826137f3565b6001600160a01b0389166000908152603e602052604090205461247b916001600160b81b031690600160281b90046001600160d81b0316614f8f565b6001600160a01b0389166000908152603e6020526040902080546001600160d81b0392909216600160281b0264ffffffffff9092169190911790555b6124eb6001600160a01b037f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9168883611fb2565b866001600160a01b0316886001600160a01b03167f3f693fff038bb8a046aa76d9516190ac7444f7d69cf952c4cbdc086fdef2d6fc8385604051612539929190918252602082015260400190565b60405180910390a35050505050505050565b61256c60408051606081018252600080825260208201819052909182015290565b6001600160a01b038216600090815260208181526040808320815160808101835281546001600160681b03811682526001600160481b03600160681b8204811695830195909552600160b01b8104909416928101929092529091606083019060ff600160f81b9091041660038111156125e7576125e7614e91565b60038111156125f8576125f8614e91565b815250509050604051806060016040528082602001516001600160481b0316815260200182604001516001600160481b031681526020018260600151600381111561264557612645614e91565b90529392505050565b60008082600181111561266357612663614e91565b036126b55760018360400151600381111561268057612680614e91565b1660ff166000036126925760006126ae565b6001600160a01b03808516600090815260476020526040902054165b9050610fd7565b6002836040015160038111156126cd576126cd614e91565b10156126da576000610fd4565b5050506001600160a01b039081166000908152604860205260409020541690565b60008160000361271d5760405162461bcd60e51b8152600401610c3090614f62565b60006127338561272c876113b1565b60006135c8565b905060008184116127445783612746565b815b9050806000036127685760405162461bcd60e51b8152600401610c3090614f62565b6127728183614d6e565b6001600160a01b038088166000908152603d60205260409020919091556127dd907f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9167f00000000000000000000000025f2226b597e8f9514b3f68f00f494cf4f2864918784612bfe565b846001600160a01b0316866001600160a01b03167f9310ccfcb8de723f578a9e4282ea9f521f05ae40dc08f3068dfad528a65ee3c78360405161282291815260200190565b60405180910390a395945050505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981146116cf57818110156128b25760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610c30565b6116cf8484848403612015565b60006128ca846113b1565b90506128d8848260016135c8565b50826001600160a01b0316846001600160a01b0316146129e55760006128fd846113b1565b905061290b848260016135c8565b506001600160a01b0385166000908152603e602090815260409182902082518084019093525464ffffffffff8116808452600160281b9091046001600160d81b031691830191909152156129e25783830361297e576001600160a01b0386166000908152603e60205260408120556129e2565b60208101516001600160d81b03166129968585614d6e565b10156129e2576129a68484614d6e565b6001600160a01b0387166000908152603e6020526040902080546001600160d81b0392909216600160281b0264ffffffffff9092169190911790555b50505b6116cf84848461385c565b60006129fb826113b1565b905080600003612a4d5760405162461bcd60e51b815260206004820152601b60248201527f494e56414c49445f42414c414e43455f4f4e5f434f4f4c444f574e00000000006044820152606401610c30565b60408051808201825264ffffffffff42811682526001600160d81b0380851660208085019182526001600160a01b0388166000818152603e9092529086902094519151909216600160281b0292169190911790915590517f8a05f911d8ab7fc50fec37ef4ba7f9bfcb1a3c191c81dcd824ad0946c4e20d6590611e439084815260200190565b6000306001600160a01b037f0000000000000000000000000fe58fe1caa69951dc924a8c222be19013b8947616148015612b2c57507f000000000000000000000000000000000000000000000000000000000000000146145b15612b5657507feb27f7e4e3311e3ab69e447339c7995dfd6668d04faa42bfea14f09caef873d990565b611074604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f1d230805e6c1719b3f833629ea0613917c0c2c6c68d9b5d4f667ca7062d513c5918101919091527fad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a560608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b6040516001600160a01b03808516602483015283166044820152606481018290526116cf9085906323b872dd60e01b90608401611fde565b6000836001600160a01b0316836001600160a01b031614612c575782612c5a565b60005b90506000612c678561254b565b90506000612c7686838661264e565b9050806001600160a01b0316836001600160a01b031603612c9957505050505050565b6001600160a01b03818116151590841615156000612cb689613a95565b90508215612ccb57612ccb816000868a613aa0565b8115612cde57612cde600082888a613aa0565b612ce9898888613b6a565b82151582151514612d0857612d0889612d03878a86613c0d565b613d2d565b856001600160a01b0316896001600160a01b03167fe8d51c8e11bd570db1734c8ec775785330e77007feed45c43b608ef33ff914bd89604051612d4b9190614fb6565b60405180910390a3505050505050505050565b600061107461106a565b600080600080612d7a88888888613dcd565b925092509250612d8a8282613e9c565b50909150505b949350505050565b6127108110612de95760405162461bcd60e51b815260206004820152601b60248201527f494e56414c49445f534c415348494e475f50455243454e5441474500000000006044820152606401610c30565b60508190556040518181527fb79c2d6c7f5c95eec9dc05affc0ed002620a4ec6d72b7b0744cc8638168c600a90602001611fa7565b60606110747f3200000000000000000000000000000000000000000000000000000000000001613f55565b604f8190556040518181527fbbf67247b5c97564e30ffc0a355e71c006836de7b9149e09e3d5d6054cb0335590602001611fa7565b60606110747f5374616b6564204161766500000000000000000000000000000000000000000b613f55565b600080805b8351811015612faf576000603c6000868481518110612ecf57612ecf614f33565b602090810291909101810151516001600160a01b031682528101919091526040016000908120600181015481548851929450612f3d926001600160801b0380831692600160801b900416908a9088908110612f2c57612f2c614f33565b602002602001015160400151613f94565b9050612f8e868481518110612f5457612f54614f33565b602002602001015160200151828460020160008b6001600160a01b03166001600160a01b031681526020019081526020016000205461409f565b612f989085614df2565b935050508080612fa790614f49565b915050612eae565b509392505050565b60007f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae96001600160a01b03167f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae96001600160a01b03161461305a5760405162461bcd60e51b815260206004820181905260248201527f5245574152445f544f4b454e5f49535f4e4f545f5354414b45445f544f4b454e6044820152606401610c30565b600061307085613069876113b1565b60016135c8565b905060008184116130815783613083565b815b905080156130a2576130968630836126fb565b506130a23086836130ab565b95945050505050565b605154600160d81b900460ff16156130f85760405162461bcd60e51b815260206004820152601060248201526f534c415348494e475f4f4e474f494e4760801b6044820152606401610c30565b806000036131185760405162461bcd60e51b8152600401610c3090614f62565b6000613123836113b1565b9050600061313b84308461313660025490565b6140cb565b905080156131be576001600160a01b0384166000908152603d6020526040902054613167908290614df2565b6001600160a01b0385166000818152603d60209081526040918290209390935580519182529181018390527f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a76910160405180910390a15b60006131c9846113d5565b90506132006001600160a01b037f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae916873087612bfe565b6132128561320d8361213a565b61418c565b846001600160a01b0316866001600160a01b03167f6c86f3fd5118b3aa8bb4f389a617046de0a3d3d477de1a1673d227f802f616dc8684604051613260929190918252602082015260400190565b60405180910390a3505050505050565b60005b8151811015610f89576000603c600084848151811061329457613294614f33565b6020026020010151604001516001600160a01b03166001600160a01b0316815260200190815260200160002090506133078383815181106132d7576132d7614f33565b602002602001015160400151828585815181106132f6576132f6614f33565b6020026020010151602001516142f1565b5082828151811061331a5761331a614f33565b60209081029190910101515181546fffffffffffffffffffffffffffffffff19166001600160801b03909116178155825183908390811061335d5761335d614f33565b6020026020010151604001516001600160a01b03167f87fa03892a0556cb6b8f97e6d533a150d4d55fcbf275fff5fa003fa636bcc7fa8484815181106133a5576133a5614f33565b602090810291909101810151516040516001600160801b0390911681520160405180910390a250806133d681614f49565b915050613273565b6000806133ea8461254b565b9050600083600181111561340057613400614e91565b61340b906001614fc4565b8260400151600381111561342157613421614e91565b1660ff1660001461343357600061343c565b61343c85613a95565b9050600061344a83866143a9565b90506134568183614df2565b9695505050505050565b6000610e2c61346d612ad3565b8360405161190160f01b8152600281019290925260228201526042902090565b60006001600160d81b038211156121a35760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663136206269747360c81b6064820152608401610c30565b600061354b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143e89092919063ffffffff16565b805190915015610f4457808060200190518101906135699190614fdd565b610f445760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c30565b6000806135da85308661313660025490565b6001600160a01b0386166000908152603d602052604081205491925090613602908390614df2565b905081156130a257831561362c576001600160a01b0386166000908152603d602052604090208190555b604080516001600160a01b0388168152602081018490527f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a76910160405180910390a195945050505050565b6001600160a01b0382166136d75760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610c30565b6001600160a01b0382166000908152602081905260409020546001600160681b039081169082168110156137585760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610c30565b6001600160a01b03831660008181526020818152604080832080546001600160681b0319168787036001600160681b03908116919091179091556002805491881691829003905590519081529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610f44836000836001600160681b03166000866001600160681b03166143f7565b60006001600160b81b038211156121a35760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663834206269747360c81b6064820152608401610c30565b6001600160a01b0383166138c05760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610c30565b6001600160a01b0382166139225760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610c30565b816001600160a01b0316836001600160a01b031614613a50576001600160a01b038084166000908152602081905260408082205492851682529020546001600160681b039182169116828210156139ca5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610c30565b6001600160a01b038516600090815260208190526040902080546001600160681b0319168484036001600160681b0316179055613a078382614fff565b6001600160a01b038516600090815260208190526040902080546001600160681b0319166001600160681b03928316179055613a4d9086908690858116908516876143f7565b50505b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161212d91815260200190565b6000610e2c826113b1565b6001600160a01b038216156116cf578383146116cf576000613acf613aca6402540be40087614e1c565b61442c565b90506000613ae5613aca6402540be40087614e1c565b90506000613af28561254b565b90506000846001811115613b0857613b08614e91565b03613b3b5781838260200151613b1e919061501f565b613b28919061503f565b6001600160481b03166020820152613b60565b80518290613b4a90859061501f565b613b54919061503f565b6001600160481b031681525b6117fe8582613d2d565b6000836001600160a01b0316826001600160a01b031614613b8b5781613b8e565b60005b90506000836001811115613ba457613ba4614e91565b03613bdc576001600160a01b03848116600090815260476020526040902080546001600160a01b0319169183169190911790556116cf565b6001600160a01b03938416600090815260486020526040902080546001600160a01b03191691909416179092555050565b613c2e60408051606081018252600080825260208201819052909182015290565b8115613cad57826001811115613c4657613c46614e91565b613c51906001614fc4565b84604001516003811115613c6757613c67614e91565b1760ff166003811115613c7c57613c7c614e91565b84604001906003811115613c9257613c92614e91565b90816003811115613ca557613ca5614e91565b905250613d25565b6003836001811115613cc157613cc1614e91565b613ccc906001614fc4565b1884604001516003811115613ce357613ce3614e91565b1660ff166003811115613cf857613cf8614e91565b84604001906003811115613d0e57613d0e614e91565b90816003811115613d2157613d21614e91565b9052505b509192915050565b6001600160a01b03821660009081526020818152604091829020835181549285015171ffffffffffffffffffffffffffffffffffff60681b19909316600160681b6001600160481b039283160268ffffffffffffffffff60b01b191617600160b01b91909316029190911780825591830151909182906001600160f81b0316600160f81b836003811115613dc357613dc3614e91565b0217905550505050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115613e085750600091506003905082613e92565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015613e5c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613e8857506000925060019150829050613e92565b9250600091508190505b9450945094915050565b6000826003811115613eb057613eb0614e91565b03613eb9575050565b6001826003811115613ecd57613ecd614e91565b03613eeb5760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115613eff57613eff614e91565b03613f205760405163fce698f760e01b815260048101829052602401610c30565b6003826003811115613f3457613f34614e91565b03610f89576040516335e2f38360e21b815260048101829052602401610c30565b60606000613f6283614494565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000831580613fa1575081155b80613fb4575042836001600160801b0316145b80613fe857507f000000000000000000000000000000000000000000000000000000012180763b836001600160801b031610155b15613ff4575083612d90565b60007f000000000000000000000000000000000000000000000000000000012180763b42116140235742614045565b7f000000000000000000000000000000000000000000000000000000012180763b5b9050600061405c6001600160801b03861683614d6e565b9050868461406c6012600a615143565b614076848a614e05565b6140809190614e05565b61408a9190614e1c565b6140949190614df2565b979650505050505050565b60006140ad6012600a615143565b6140b78385614d6e565b6140c19086614e05565b610fd49190614e1c565b6001600160a01b038084166000908152603c6020908152604080832093881683526002840190915281205490919082806141068885886142f1565b90508083146141805786156141235761412087828561409f565b91505b6001600160a01b03808a1660008181526002870160205260409081902084905551918a16917fbb123b5c06d5408bbea3c4fef481578175cfb432e3b482c6186f02ed9086585b906141779085815260200190565b60405180910390a35b50979650505050505050565b6001600160a01b0382166141e25760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610c30565b6001600160a01b038216600090815260208190526040812054600280546001600160681b0392831693928516929061421b908490614df2565b90915550506001600160a01b038316600090815260208190526040812080548492906142519084906001600160681b0316614fff565b92506101000a8154816001600160681b0302191690836001600160681b03160217905550826001600160a01b031660006001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516142c891906001600160681b0391909116815260200190565b60405180910390a3610f446000846000846001600160681b0316866001600160681b03166143f7565b6001820154825460009190600160801b90046001600160801b03164281900361431c57509050610fd7565b84546000906143379084906001600160801b03168488613f94565b905082811461438657600186018190556040518181526001600160a01b038816907f5777ca300dfe5bead41006fbce4389794dbc0ed8d6cccebfaf94630aa04184bc9060200160405180910390a25b85546001600160801b03428116600160801b029116178655925050509392505050565b6000808260018111156143be576143be614e91565b146143ca5782516143d0565b82602001515b610fd7906001600160481b03166402540be400614e05565b6060610fd484846000856144bc565b614404858585858561458c565b6053546001600160a01b0316801561442457614424818787878787614599565b505050505050565b60006001600160481b038211156121a35760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203760448201526532206269747360d01b6064820152608401610c30565b600060ff8216601f811115610e2c57604051632cd44ac360e21b815260040160405180910390fd5b60608247101561451d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610c30565b600080866001600160a01b03168587604051614539919061514f565b60006040518083038185875af1925050503d8060008114614576576040519150601f19603f3d011682016040523d82523d6000602084013e61457b565b606091505b509150915061409487838387614603565b611d77858585858561467c565b604051635b9c4cf160e01b80825260048201879052602482018690526044820185905260648201849052608482018390529062035b60905a60008060a48460008e88f16145f757826040603f83020410156145f7573d6000833e3d82fd5b50505050505050505050565b6060831561467257825160000361466b576001600160a01b0385163b61466b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c30565b5081612d90565b612d908383614779565b836001600160a01b0316856001600160a01b03160315611d77576001600160a01b038516156147105760006146b08661254b565b905060006146be8386614d6e565b90506000826040015160038111156146d8576146d8614e91565b1461470d576146f585826146ee8a86600061264e565b6000613aa0565b61470d85826147068a86600161264e565b6001613aa0565b50505b6001600160a01b03841615611d7757600061472a8561254b565b905060006147388385614df2565b905060008260400151600381111561475257614752614e91565b146117fe5761476884826146ee8986600061264e565b6117fe84826147068986600161264e565b8151156147895781518083602001fd5b8060405162461bcd60e51b8152600401610c309190614839565b80356001600160a01b03811681146147ba57600080fd5b919050565b600080604083850312156147d257600080fd5b6147db836147a3565b946020939093013593505050565b60005b838110156148045781810151838201526020016147ec565b50506000910152565b600081518084526148258160208601602086016147e9565b601f01601f19169290920160200192915050565b602081526000610fd7602083018461480d565b60006020828403121561485e57600080fd5b610fd7826147a3565b60006020828403121561487957600080fd5b5035919050565b60008060006060848603121561489557600080fd5b61489e846147a3565b92506148ac602085016147a3565b9150604084013590509250925092565b600080604083850312156148cf57600080fd5b6148d8836147a3565b91506148e6602084016147a3565b90509250929050565b8035600281106147ba57600080fd5b803560ff811681146147ba57600080fd5b600080600080600080600060e0888a03121561492a57600080fd5b614933886147a3565b9650614941602089016147a3565b955061494f604089016148ef565b945060608801359350614964608089016148fe565b925060a0880135915060c0880135905092959891949750929550565b6000806040838503121561499357600080fd5b61499c836147a3565b91506148e6602084016148ef565b60ff60f81b881681526000602060e0818401526149ca60e084018a61480d565b83810360408501526149dc818a61480d565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015614a2e57835183529284019291840191600101614a12565b50909c9b505050505050505050505050565b60008060008060808587031215614a5657600080fd5b614a5f856147a3565b9350614a6d602086016147a3565b93969395505050506040820135916060013590565b60008060008060008060c08789031215614a9b57600080fd5b614aa4876147a3565b9550614ab2602088016147a3565b945060408701359350614ac7606088016148fe565b92506080870135915060a087013590509295509295509295565b60008060408385031215614af457600080fd5b823591506148e6602084016147a3565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715614b3d57614b3d614b04565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715614b6c57614b6c614b04565b604052919050565b60006020808385031215614b8757600080fd5b823567ffffffffffffffff80821115614b9f57600080fd5b818501915085601f830112614bb357600080fd5b813581811115614bc557614bc5614b04565b614bd3848260051b01614b43565b81815284810192506060918202840185019188831115614bf257600080fd5b938501935b828510156141805780858a031215614c0f5760008081fd5b614c17614b1a565b85356001600160801b0381168114614c2f5760008081fd5b815285870135878201526040614c468188016147a3565b9082015284529384019392850192614bf7565b600080600080600080600060e0888a031215614c7457600080fd5b614c7d886147a3565b9650614c8b602089016147a3565b95506040880135945060608801359350614964608089016148fe565b600080600060608486031215614cbc57600080fd5b614cc5846147a3565b95602085013595506040909401359392505050565b600080600080600060a08688031215614cf257600080fd5b8535945060208601359350614d09604087016148fe565b94979396509394606081013594506080013592915050565b60208082526019908201527f43414c4c45525f4e4f545f534c415348494e475f41444d494e00000000000000604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610e2c57610e2c614d58565b600181811c90821680614d9557607f821691505b602082108103614db557634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526017908201527f43414c4c45525f4e4f545f434c41494d5f48454c504552000000000000000000604082015260600190565b80820180821115610e2c57610e2c614d58565b8082028115828204841417610e2c57610e2c614d58565b600082614e3957634e487b7160e01b600052601260045260246000fd5b500490565b6020808252600d908201526c24a72b20a624a22fa7aba722a960991b604082015260600190565b60208082526012908201527124a72b20a624a22fa2ac2824a920aa24a7a760711b604082015260600190565b634e487b7160e01b600052602160045260246000fd5b60028110614ec557634e487b7160e01b600052602160045260246000fd5b9052565b8681526001600160a01b0386811660208301528516604082015260c08101614ef46060830186614ea7565b608082019390935260a00152949350505050565b602080825260119082015270494e56414c49445f5349474e415455524560781b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060018201614f5b57614f5b614d58565b5060010190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b6001600160d81b03828116828216039080821115614faf57614faf614d58565b5092915050565b60208101610e2c8284614ea7565b60ff8181168382160190811115610e2c57610e2c614d58565b600060208284031215614fef57600080fd5b81518015158114610fd757600080fd5b6001600160681b03818116838216019080821115614faf57614faf614d58565b6001600160481b03828116828216039080821115614faf57614faf614d58565b6001600160481b03818116838216019080821115614faf57614faf614d58565b600181815b8085111561509a57816000190482111561508057615080614d58565b8085161561508d57918102915b93841c9390800290615064565b509250929050565b6000826150b157506001610e2c565b816150be57506000610e2c565b81600181146150d457600281146150de576150fa565b6001915050610e2c565b60ff8411156150ef576150ef614d58565b50506001821b610e2c565b5060208310610133831016604e8410600b841016171561511d575081810a610e2c565b615127838361505f565b806000190482111561513b5761513b614d58565b029392505050565b6000610fd783836150a2565b600082516151618184602087016147e9565b919091019291505056fea2646970667358221220385b96f1c8f473a813ebd23eecf2eaf0bec52cdecaeeff8cb048e4b8d7ea13d264736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae90000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9000000000000000000000000000000000000000000000000000000000002a30000000000000000000000000025f2226b597e8f9514b3f68f00f494cf4f2864910000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a00000000000000000000000000000000000000000000000000000000bc180c38
-----Decoded View---------------
Arg [0] : stakedToken (address): 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9
Arg [1] : rewardToken (address): 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9
Arg [2] : unstakeWindow (uint256): 172800
Arg [3] : rewardsVault (address): 0x25F2226B597E8F9514B3F68F00f494cF4f286491
Arg [4] : emissionManager (address): 0x5300A1a15135EA4dc7aD5a167152C01EFc9b192A
Arg [5] : distributionDuration (uint128): 3155692600
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9
Arg [1] : 0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9
Arg [2] : 000000000000000000000000000000000000000000000000000000000002a300
Arg [3] : 00000000000000000000000025f2226b597e8f9514b3f68f00f494cf4f286491
Arg [4] : 0000000000000000000000005300a1a15135ea4dc7ad5a167152c01efc9b192a
Arg [5] : 00000000000000000000000000000000000000000000000000000000bc180c38
Deployed Bytecode Sourcemap
578:3462:18:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8085:761:20;;;;;;:::i;:::-;;:::i;:::-;;;597:25:35;;;585:2;570:18;8085:761:20;;;;;;;;1115:92:0;;;:::i;:::-;;;;;;;:::i;1460:60:19:-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;1460:60:19;;-1:-1:-1;;;;;1460:60:19;;;;;;;1782:12:35;1770:25;;;1752:44;;-1:-1:-1;;;;;1832:32:35;;;1827:2;1812:18;;1805:60;1725:18;1460:60:19;1580:291:35;2082:183:0;;;;;;:::i;:::-;;:::i;:::-;;;2041:14:35;;2034:22;2016:41;;2004:2;1989:18;2082:183:0;1876:187:35;1013:93:33;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;2417:32:35;;;2399:51;;2387:2;2372:18;1013:93:33;2253:203:35;6568:164:20;;;;;;:::i;:::-;;:::i;:::-;;4126:366:1;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;3024:15:35;;;3006:34;;3076:15;;;;3071:2;3056:18;;3049:43;2941:18;4126:366:1;2794:304:35;797:53:18;;;;;-1:-1:-1;;;;;797:53:18;;;1499:100:0;1582:12;;1499:100;;6372:159:20;;;;;;:::i;:::-;;:::i;6965:189::-;;;;;;:::i;:::-;;:::i;2269:254:0:-;;;;;;:::i;:::-;;:::i;5925:102:20:-;;;;;;:::i;:::-;;:::i;5078:233:1:-;;;;;;:::i;:::-;;:::i;:::-;;;;3527:25:35;;;3583:2;3568:18;;3561:34;;;;3500:18;5078:233:1;3353:248:35;1635:153:19;;1681:107;1635:153;;1068:36;;;;;1410:85:0;1488:2;1410:85;;;4183:4:35;4171:17;;;4153:36;;4141:2;4126:18;1410:85:0;4011:184:35;7663:140:16;;;;;;:::i;:::-;-1:-1:-1;;;;;7773:13:16;;;7751:7;7773:13;;;:6;:13;;;;;;;;:25;;;;;:19;;;;:25;;;;7663:140;;;;;1229:39:19;;;;;2539:104;;;:::i;2527:222:0:-;;;;;;:::i;:::-;;:::i;1920:137:1:-;;1968:89;1920:137;;8883:453:20;;;;;;:::i;:::-;;:::i;1268:107:33:-;;;;;;:::i;:::-;1328:7;1350:20;;;:14;:20;;;;;;-1:-1:-1;;;;;1350:20:33;;1268:107;7892:156:20;;;;;;:::i;:::-;;:::i;1678:49:1:-;;1723:4;1678:49;;1501:52:20;;1549:4;1501:52;;;;;-1:-1:-1;;;;;4629:32:35;;;4611:51;;4599:2;4584:18;1501:52:20;4465:203:35;3571:209:1;;;;;;:::i;:::-;;:::i;10070:96:20:-;10145:16;;10070:96;;1826:36;;;;;5365:793:1;;;;;;:::i;:::-;;:::i;3834:238::-;;;;;;:::i;:::-;;:::i;1603:127:0:-;;;;;;:::i;:::-;;:::i;4952:138:20:-;;;;;;:::i;:::-;;:::i;9539:148::-;;;;;;:::i;:::-;;:::i;2724:105:19:-;;;:::i;5787:101:20:-;;;:::i;9898:135::-;;;;;;:::i;:::-;;:::i;1401:55:19:-;;;;;;:::i;:::-;;;;;;;;;;;;;;1407:54:18;;;:::i;5365:441:4:-;;;:::i;:::-;;;;;;;;;;;;;:::i;1353:44:20:-;;1396:1;1353:44;;3283:485:19;;;;;;:::i;:::-;;:::i;1557:49:20:-;;1602:4;1557:49;;442:41:16;;;;;1358:38:19;;;;;1497:177:18;;;;;;:::i;:::-;;:::i;1310:96:0:-;;;:::i;1108:36:19:-;;;;;6769:159:20;;;;;;:::i;:::-;;:::i;7456:258::-;;;;;;:::i;:::-;;:::i;1401:47::-;;1447:1;1401:47;;6212:741:1;;;;;;:::i;:::-;;:::i;2753:411:0:-;;;;;;:::i;:::-;;:::i;1734:175::-;;;;;;:::i;:::-;;:::i;1732:184:1:-;;1788:128;1732:184;;534:36:16;;568:2;534:36;;1584:205:33;;;;;;:::i;:::-;;:::i;5127:145:20:-;;;;;;:::i;:::-;;:::i;9373:129::-;;;:::i;4560:355::-;;;;;;:::i;:::-;;:::i;17926:242::-;;;;;;:::i;:::-;;:::i;1854:42:19:-;;;;;;:::i;:::-;;;;;;;;;;;;;;1710:213:18;;;;;;:::i;:::-;;:::i;488:41:16:-;;;;;3805:762:19;;;;;;:::i;:::-;;:::i;1452:45:20:-;;1496:1;1452:45;;3333:184:1;;;;;;:::i;:::-;;:::i;1913:165:0:-;;;;;;:::i;:::-;-1:-1:-1;;;;;2046:18:0;;;2022:7;2046:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;1913:165;855:86:18;935:1;855:86;;7751:104:20;7830:20;;-1:-1:-1;;;;;7830:20:20;7751:104;;7191:228;;;;;;:::i;:::-;;:::i;5309:441::-;;;;;;:::i;:::-;;:::i;2405:32::-;;;;;-1:-1:-1;;;2405:32:20;;;;;;575:43:16;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;575:43:16;;;;-1:-1:-1;;;575:43:16;;;;;;;;;;-1:-1:-1;;;;;12565:15:35;;;12547:34;;12617:15;;;;12612:2;12597:18;;12590:43;12649:18;;;12642:34;12482:2;12467:18;575:43:16;12292:390:35;9724:137:20;9833:23;;9724:137;;1940:190:33;;;;;;:::i;:::-;;:::i;8085:761:20:-;8194:7;2506:26;1396:1;2506:8;:26::i;:::-;-1:-1:-1;;;;;2492:40:20;:10;-1:-1:-1;;;;;2492:40:20;;2477:96;;;;-1:-1:-1;;;2477:96:20;;;;;;;:::i;:::-;;;;;;;;;8218:20:::1;::::0;-1:-1:-1;;;8218:20:20;::::1;;;8217:21;8209:63;;;::::0;-1:-1:-1;;;8209:63:20;;13243:2:35;8209:63:20::1;::::0;::::1;13225:21:35::0;13282:2;13262:18;;;13255:30;13321:31;13301:18;;;13294:59;13370:18;;8209:63:20::1;13041:353:35::0;8209:63:20::1;8295:1;8286:6;:10;8278:34;;;::::0;-1:-1:-1;;;8278:34:20;;13601:2:35;8278:34:20::1;::::0;::::1;13583:21:35::0;13640:2;13620:18;;;13613:30;-1:-1:-1;;;13659:18:35;;;13652:41;13710:18;;8278:34:20::1;13399:335:35::0;8278:34:20::1;8318:21;8342:13;1582:12:0::0;;;1499:100;8342:13:20::1;8318:37;;8361:15;8379:28;8393:13;8379;:28::i;:::-;8361:46;;8414:20;8437:43;8456:23;;8437:7;:18;;:43;;;;:::i;:::-;8414:66;;8500:12;8491:6;:21;8487:63;;;8531:12;8522:21;;8487:63;8583:11;8563:16;8573:6:::0;8563:7;:16:::1;:::i;:::-;:31;;8555:64;;;::::0;-1:-1:-1;;;8555:64:20;;14206:2:35;8555:64:20::1;::::0;::::1;14188:21:35::0;14245:2;14225:18;;;14218:30;-1:-1:-1;;;14264:18:35;;;14257:50;14324:18;;8555:64:20::1;14004:344:35::0;8555:64:20::1;8626:20;:27:::0;;-1:-1:-1;;;;8626:27:20::1;-1:-1:-1::0;;;8626:27:20::1;::::0;;8659:70:::1;8679:49;8696:16;8706:6:::0;8696:7;:16:::1;:::i;:::-;8714:13;8679:16;:49::i;:::-;8659:19;:70::i;:::-;8736:46;-1:-1:-1::0;;;;;8736:12:20::1;:25;8762:11:::0;8775:6;8736:25:::1;:46::i;:::-;8802:11;-1:-1:-1::0;;;;;8794:28:20::1;;8815:6;8794:28;;;;597:25:35::0;;585:2;570:18;;451:177;8794:28:20::1;;;;;;;;8835:6;8828:13;;;;;2579:1;8085:761:::0;;;;:::o;1115:92:0:-;1169:13;1197:5;1190:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1115:92;:::o;2082:183::-;2165:4;720:10:9;2211:32:0;720:10:9;2227:7:0;2236:6;2211:8;:32::i;:::-;-1:-1:-1;2256:4:0;;2082:183;-1:-1:-1;;;2082:183:0:o;1013:93:33:-;1066:7;1088:13;;;:7;:13;;;;;;-1:-1:-1;;;;;1088:13:33;;1013:93::o;6568:164:20:-;2801:27;1496:1;2801:8;:27::i;:::-;-1:-1:-1;;;;;2787:41:20;:10;-1:-1:-1;;;;;2787:41:20;;2772:95;;;;-1:-1:-1;;;2772:95:20;;;;;;;:::i;:::-;6690:37:::1;6698:4;6704:2;6708:18;:6;:16;:18::i;:::-;6690:7;:37::i;:::-;6568:164:::0;;;:::o;4126:366:1:-;4199:7;4208;4223:39;4265:30;4285:9;4265:19;:30::i;:::-;4223:72;;4316:76;4336:9;4347:16;4365:26;4316:19;:76::i;:::-;4400:81;4420:9;4431:16;4449:31;4400:19;:81::i;:::-;4301:186;;;;;4126:366;;;:::o;6372:159:20:-;6483:43;6491:10;6503:2;6507:18;:6;:16;:18::i;6483:43::-;6372:159;;:::o;6965:189::-;7096:7;2801:27;1496:1;2801:8;:27::i;:::-;-1:-1:-1;;;;;2787:41:20;:10;-1:-1:-1;;;;;2787:41:20;;2772:95;;;;-1:-1:-1;;;2772:95:20;;;;;;;:::i;:::-;7118:31:::1;7132:4;7138:2;7142:6;7118:13;:31::i;:::-;7111:38;;2873:1;6965:189:::0;;;;;:::o;2269:254:0:-;2382:4;720:10:9;2430:38:0;2446:4;720:10:9;2461:6:0;2430:15;:38::i;:::-;2474:27;2484:4;2490:2;2494:6;2474:9;:27::i;:::-;-1:-1:-1;2514:4:0;;2269:254;-1:-1:-1;;;;2269:254:0:o;5925:102:20:-;2801:27;1496:1;2801:8;:27::i;:::-;-1:-1:-1;;;;;2787:41:20;:10;-1:-1:-1;;;;;2787:41:20;;2772:95;;;;-1:-1:-1;;;2772:95:20;;;;;;;:::i;:::-;6007:15:::1;6017:4;6007:9;:15::i;:::-;5925:102:::0;:::o;5078:233:1:-;5150:7;5159;5189:49;5205:4;5211:26;5189:15;:49::i;:::-;5246:54;5262:4;5268:31;5246:15;:54::i;:::-;5174:132;;;;5078:233;;;:::o;2539:104:19:-;2596:7;2618:20;:18;:20::i;:::-;2611:27;;2539:104;:::o;2527:222:0:-;720:10:9;2615:4:0;2686:18;;;:11;:18;;;;;;;;-1:-1:-1;;;;;2686:27:0;;;;;;;;;;2615:4;;720:10:9;2661:66:0;;720:10:9;;2686:27:0;;:40;;2716:10;;2686:40;:::i;:::-;2661:8;:66::i;8883:453:20:-;8962:11;8952:6;:21;;8944:51;;;;-1:-1:-1;;;8944:51:20;;15422:2:35;8944:51:20;;;15404:21:35;15461:2;15441:18;;;15434:30;-1:-1:-1;;;15480:18:35;;;15473:47;15537:18;;8944:51:20;15220:341:35;8944:51:20;9001:21;9025:13;1582:12:0;;;1499:100;9025:13:20;9001:37;;9069:11;9052:13;:28;;9044:58;;;;-1:-1:-1;;;9044:58:20;;15768:2:35;9044:58:20;;;15750:21:35;15807:2;15787:18;;;15780:30;-1:-1:-1;;;15826:18:35;;;15819:47;15883:18;;9044:58:20;15566:341:35;9044:58:20;9108:14;9125:28;9139:13;9125;:28::i;:::-;9108:45;-1:-1:-1;9159:69:20;9179:48;9196:15;9205:6;9108:45;9196:15;:::i;:::-;9213:13;9179:16;:48::i;9159:69::-;9235:64;-1:-1:-1;;;;;9235:12:20;:29;9265:10;9285:4;9292:6;9235:29;:64::i;:::-;9310:21;;597:25:35;;;9310:21:20;;585:2:35;570:18;9310:21:20;;;;;;;8938:398;;8883:453;:::o;7892:156::-;8023:20;;7969:7;;-1:-1:-1;;;;;8023:20:20;7992:27;8013:6;1602:4;7992:27;:::i;:::-;7991:52;;;;:::i;3571:209:1:-;3632:66;3648:10;3660:9;3671:26;3632:15;:66::i;:::-;3704:71;3720:10;3732:9;3743:31;3704:15;:71::i;5365:793::-;-1:-1:-1;;;;;5580:23:1;;5572:49;;;;-1:-1:-1;;;5572:49:1;;;;;;;:::i;:::-;5685:8;5666:15;:27;;5658:58;;;;-1:-1:-1;;;5658:58:1;;;;;;;:::i;:::-;5722:14;5739:275;5768:21;:19;:21::i;:::-;1788:128;5875:9;5896;5917:14;5943:27;5960:9;-1:-1:-1;;;;;18798:13:20;18663:7;18798:13;;;:7;:13;;;;;:15;;;;;;;;;18596:228;5943:27:1;5982:8;5816:184;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;5797:211;;;;;;9220:4:13;9214:11;-1:-1:-1;;;9238:23:13;;9290:4;9281:14;;9274:39;;;;9342:4;9333:14;;9326:34;9396:4;9381:20;;;9020:397;5739:275:1;5722:292;;6042:30;6056:6;6064:1;6067;6070;6042:13;:30::i;:::-;-1:-1:-1;;;;;6029:43:1;:9;-1:-1:-1;;;;;6029:43:1;;6021:73;;;;-1:-1:-1;;;6021:73:1;;;;;;;:::i;:::-;6100:53;6116:9;6127;6138:14;6100:15;:53::i;:::-;5566:592;5365:793;;;;;;;:::o;3834:238::-;3965:7;3989:78;4009:9;4020:30;4040:9;4020:19;:30::i;:::-;4052:14;3989:19;:78::i;1603:127:0:-;-1:-1:-1;;;;;1699:18:0;1677:7;1699:18;;;;;;;;;;:26;-1:-1:-1;;;;;1699:26:0;;1603:127::o;4952:138:20:-;5043:20;;5011:7;;1602:4;;5034:29;;-1:-1:-1;;;;;5043:20:20;5034:6;:29;:::i;9539:148::-;2506:26;1396:1;2506:8;:26::i;:::-;-1:-1:-1;;;;;2492:40:20;:10;-1:-1:-1;;;;;2492:40:20;;2477:96;;;;-1:-1:-1;;;2477:96:20;;;;;;;:::i;:::-;9644:38:::1;9671:10;9644:26;:38::i;2724:105:19:-:0;2774:12;2807:16;:14;:16::i;5787:101:20:-;5862:21;5872:10;5862:9;:21::i;:::-;5787:101::o;9898:135::-;2653:29;1447:1;2653:8;:29::i;:::-;-1:-1:-1;;;;;2639:43:20;:10;-1:-1:-1;;;;;2639:43:20;;2624:99;;;;-1:-1:-1;;;2624:99:20;;18575:2:35;2624:99:20;;;18557:21:35;18614:2;18594:18;;;18587:30;18653:27;18633:18;;;18626:55;18698:18;;2624:99:20;18373:349:35;2624:99:20;9992:36:::1;10012:15;9992:19;:36::i;1407:54:18:-:0;1105:23:34;;935:1:18;;1094:34:34;;1079:111;;;;-1:-1:-1;;;1079:111:34;;18929:2:35;1079:111:34;;;18911:21:35;18968:2;18948:18;;;18941:30;19007:34;18987:18;;;18980:62;-1:-1:-1;;;19058:18:35;;;19051:44;19112:19;;1079:111:34;18727:410:35;1079:111:34;1197:23;:34;1407:54:18:o;5365:441:4:-;5441:13;5462:18;5488:21;5517:15;5540:25;5573:12;5593:27;5674:13;:11;:13::i;:::-;5695:16;:14;:16::i;:::-;5779;;;5769:1;5779:16;;;;;;;;;-1:-1:-1;;;5635:166:4;;;-1:-1:-1;5635:166:4;;-1:-1:-1;5719:13:4;;-1:-1:-1;5748:4:4;;-1:-1:-1;5769:1:4;-1:-1:-1;5779:16:4;-1:-1:-1;5635:166:4;-1:-1:-1;5365:441:4:o;3283:485:19:-;3443:41;;;3482:1;3443:41;;;;;;;;;3362:7;;;;3443:41;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3443:41:19;;;;;;;;;;;;;;;;3377:107;;3511:151;;;;;;;;3577:4;-1:-1:-1;;;;;3511:151:19;;;;;3604:17;3614:6;3604:9;:17::i;:::-;3511:151;;;;3642:13;1582:12:0;;;1499:100;3642:13:19;3511:151;;;3490:15;3506:1;3490:18;;;;;;;;:::i;:::-;;;;;;:172;;;;3718:45;3739:6;3747:15;3718:20;:45::i;:::-;-1:-1:-1;;;;;3681:28:19;;;;;;:20;:28;;;;;;:82;;;;:::i;1497:177:18:-;1594:7;1616:53;1646:10;1658:2;1662:6;1616:29;:53::i;1310:96:0:-;1366:13;1394:7;1387:14;;;;;:::i;6769:159:20:-;6886:37;6900:10;6912:2;6916:6;6886:13;:37::i;7456:258::-;2801:27;1496:1;2801:8;:27::i;:::-;-1:-1:-1;;;;;2787:41:20;:10;-1:-1:-1;;;;;2787:41:20;;2772:95;;;;-1:-1:-1;;;2772:95:20;;;;;;;:::i;:::-;7624:36:::1;7638:4;7644:2;7648:11;7624:13;:36::i;:::-;;7666:43;7674:4;7680:2;7684:24;:12;:22;:24::i;7666:43::-;7456:258:::0;;;;:::o;6212:741:1:-;-1:-1:-1;;;;;6381:23:1;;6373:49;;;;-1:-1:-1;;;6373:49:1;;;;;;;:::i;:::-;6486:8;6467:15;:27;;6459:58;;;;-1:-1:-1;;;6459:58:1;;;;;;;:::i;:::-;6523:14;6540:181;6569:21;:19;:21::i;:::-;1968:89;6647:9;6658;6669:27;6686:9;-1:-1:-1;;;;;18798:13:20;18663:7;18798:13;;;:7;:13;;;;;:15;;;;;;;;;18596:228;6669:27:1;6617:90;;;;;;19533:25:35;;;;-1:-1:-1;;;;;19632:15:35;;;19612:18;;;19605:43;19684:15;;19664:18;;;19657:43;19716:18;;;19709:34;19759:19;;;19752:35;;;19505:19;;6617:90:1;19274:519:35;6540:181:1;6523:198;;6749:30;6763:6;6771:1;6774;6777;6749:13;:30::i;:::-;-1:-1:-1;;;;;6736:43:1;:9;-1:-1:-1;;;;;6736:43:1;;6728:73;;;;-1:-1:-1;;;6728:73:1;;;;;;;:::i;:::-;6807:65;6823:9;6834;6845:26;6807:15;:65::i;:::-;6878:70;6894:9;6905;6916:31;6878:15;:70::i;:::-;6367:586;6212:741;;;;;;:::o;2753:411:0:-;720:10:9;2858:4:0;2933:18;;;:11;:18;;;;;;;;-1:-1:-1;;;;;2933:27:0;;;;;;;;;;2858:4;;720:10:9;2974:35:0;;;;2966:85;;;;-1:-1:-1;;;2966:85:0;;20000:2:35;2966:85:0;;;19982:21:35;20039:2;20019:18;;;20012:30;20078:34;20058:18;;;20051:62;-1:-1:-1;;;20129:18:35;;;20122:35;20174:19;;2966:85:0;19798:401:35;2966:85:0;3075:60;3084:5;3091:7;3119:15;3100:16;:34;3075:8;:60::i;1734:175::-;1813:4;720:10:9;1859:28:0;720:10:9;1876:2:0;1880:6;1859:9;:28::i;1584:205:33:-;642:13;;;;:7;:13;;;;;;1681:4;;-1:-1:-1;;;;;642:13:33;659:10;642:27;634:61;;;;-1:-1:-1;;;634:61:33;;20406:2:35;634:61:33;;;20388:21:35;20445:2;20425:18;;;20418:30;-1:-1:-1;;;20464:18:35;;;20457:51;20525:18;;634:61:33;20204:345:35;634:61:33;1693:20:::1;::::0;;;:14:::1;:20;::::0;;;;;;;;:38;;-1:-1:-1;;;;;;1693:38:33::1;-1:-1:-1::0;;;;;1693:38:33;::::1;::::0;;::::1;::::0;;;1742:42;;597:25:35;;;1742:42:33::1;::::0;570:18:35;1742:42:33::1;;;;;;;1584:205:::0;;;:::o;5127:145:20:-;5237:30;5244:10;5256:2;5260:6;5237;:30::i;9373:129::-;2506:26;1396:1;2506:8;:26::i;:::-;-1:-1:-1;;;;;2492:40:20;:10;-1:-1:-1;;;;;2492:40:20;;2477:96;;;;-1:-1:-1;;;2477:96:20;;;;;;;:::i;:::-;9441:20:::1;:28:::0;;-1:-1:-1;;;;9441:28:20::1;::::0;;9480:17:::1;::::0;::::1;::::0;9464:5:::1;::::0;9480:17:::1;9373:129::o:0;4560:355::-;4688:10;-1:-1:-1;;;;;4702:16:20;4688:30;;4680:64;;;;-1:-1:-1;;;4680:64:20;;20756:2:35;4680:64:20;;;20738:21:35;20795:2;20775:18;;;20768:30;-1:-1:-1;;;20814:18:35;;;20807:51;20875:18;;4680:64:20;20554:345:35;4680:64:20;4756:9;4751:118;4775:17;:24;4771:1;:28;4751:118;;;1582:12:0;;4814:17:20;4832:1;4814:20;;;;;;;;:::i;:::-;;;;;;;;;;;;:32;:48;4801:3;;;;:::i;:::-;;;;4751:118;;;;4875:35;4892:17;4875:16;:35::i;17926:242::-;18043:7;18146:17;7830:20;;-1:-1:-1;;;;;7830:20:20;;7751:104;18146:17;-1:-1:-1;;;;;18071:92:20;1602:4;18072:43;18094:4;18100:14;18072:21;:43::i;:::-;:64;;;;:::i;:::-;18071:92;;;;:::i;1710:213:18:-;1849:7;2801:27:20;1496:1;2801:8;:27::i;:::-;-1:-1:-1;;;;;2787:41:20;:10;-1:-1:-1;;;;;2787:41:20;;2772:95;;;;-1:-1:-1;;;2772:95:20;;;;;;;:::i;:::-;1871:47:18::1;1901:4;1907:2;1911:6;1871:29;:47::i;3805:762:19:-:0;-1:-1:-1;;;;;3972:19:19;;3964:45;;;;-1:-1:-1;;;3964:45:19;;;;;;;:::i;:::-;4073:8;4054:15;:27;;4046:58;;;;-1:-1:-1;;;4046:58:19;;;;;;;:::i;:::-;-1:-1:-1;;;;;4138:14:19;;;4110:25;4138:14;;;:7;:14;;;;;;;;;4218:149;;1681:107;4218:149;;;21331:25:35;;;;21410:18;;;21403:43;;;;21482:15;;;21462:18;;;21455:43;21514:18;;;21507:34;;;21557:19;;;21550:35;;;21601:19;;;21594:35;;;4138:14:19;;4175:206;;21303:19:35;;4218:149:19;;;;;;;;;;;;4199:176;;;;;;4175:16;:206::i;:::-;4158:223;;4405:30;4419:6;4427:1;4430;4433;4405:13;:30::i;:::-;-1:-1:-1;;;;;4396:39:19;:5;-1:-1:-1;;;;;4396:39:19;;4388:69;;;;-1:-1:-1;;;4388:69:19;;;;;;;:::i;:::-;-1:-1:-1;;;;;4481:14:19;;;;;;:7;:14;;;;;4518:1;4498:21;;4481:38;;4531:31;4489:5;4547:7;4556:5;4531:8;:31::i;:::-;3958:609;;3805:762;;;;;;;:::o;3333:184:1:-;3458:54;3474:10;3486:9;3497:14;3458:15;:54::i;7191:228:20:-;7317:42;7331:10;7343:2;7347:11;7317:13;:42::i;:::-;;7365:49;7373:10;7385:2;7389:24;:12;:22;:24::i;5309:441::-;5457:164;;-1:-1:-1;;;5457:164:20;;5513:10;5457:164;;;21989:34:35;5541:4:20;22039:18:35;;;22032:43;22091:18;;;22084:34;;;22134:18;;;22127:34;;;22210:4;22198:17;;22177:19;;;22170:46;22232:19;;;22225:35;;;22276:19;;;22269:35;;;5482:12:20;-1:-1:-1;;;;;5457:46:20;;;;21923:19:35;;5457:164:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5447:255;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5654:48;5447:255;5707:38;5714:10;5726;5738:6;5707;:38::i;:::-;5309:441;;;;;:::o;1940:190:33:-;776:20;;;;:14;:20;;;;;;2008:4;;-1:-1:-1;;;;;776:20:33;800:10;776:34;761:94;;;;-1:-1:-1;;;761:94:33;;22517:2:35;761:94:33;;;22499:21:35;22556:2;22536:18;;;22529:30;22595:31;22575:18;;;22568:59;22644:18;;761:94:33;22315:353:35;761:94:33;2020:13:::1;::::0;;;:7:::1;:13;::::0;;;;;;;:26;;2036:10:::1;-1:-1:-1::0;;;;;;2020:26:33;;::::1;::::0;::::1;::::0;;;2052:14:::1;:20:::0;;;;;;:33;;;;::::1;::::0;;;2096:29;597:25:35;;;2096:29:33::1;::::0;570:18:35;2096:29:33::1;;;;;;;;1940:190:::0;;:::o;773:384:30:-;875:7;902:10;;;:29;;-1:-1:-1;916:15:30;;902:29;898:68;;;-1:-1:-1;954:1:30;947:8;;898:68;1006:32;1028:10;-1:-1:-1;;1006:32:30;:::i;:::-;997:5;:41;;976:116;;;;-1:-1:-1;;;976:116:30;;22875:2:35;976:116:30;;;22857:21:35;22914:2;22894:18;;;22887:30;22953;22933:18;;;22926:58;23001:18;;976:116:30;22673:352:35;976:116:30;421:3;1111:18;1119:10;1111:5;:18;:::i;15973:227:20:-;16076:7;16104:91;16162:11;16157:1;16162:11;16107:32;1602:4;16107:11;:32;:::i;:::-;16106:48;;;;:::i;:::-;:52;;;;:::i;:::-;16105:68;;;;:::i;:::-;16104:89;:91::i;15393:224::-;15478:15;-1:-1:-1;;;;;15478:20:20;15497:1;15478:20;15470:51;;;;-1:-1:-1;;;15470:51:20;;23232:2:35;15470:51:20;;;23214:21:35;23271:2;23251:18;;;23244:30;-1:-1:-1;;;23290:18:35;;;23283:48;23348:18;;15470:51:20;23030:342:35;15470:51:20;15527:20;:38;;-1:-1:-1;;;;;;15527:38:20;-1:-1:-1;;;;;15527:38:20;;;;;;;;15576:36;;4611:51:35;;;15576:36:20;;4599:2:35;4584:18;15576:36:20;;;;;;;;15393:224;:::o;744:239:32:-;908:58;;-1:-1:-1;;;;;23569:32:35;;908:58:32;;;23551:51:35;23618:18;;;23611:34;;;856:120:32;;889:5;;-1:-1:-1;;;931:23:32;23524:18:35;;908:58:32;;;;-1:-1:-1;;908:58:32;;;;;;;;;;;;;;-1:-1:-1;;;;;908:58:32;-1:-1:-1;;;;;;908:58:32;;;;;;;;;;856:19;:120::i;3927:338:0:-;-1:-1:-1;;;;;4040:19:0;;4032:68;;;;-1:-1:-1;;;4032:68:0;;23858:2:35;4032:68:0;;;23840:21:35;23897:2;23877:18;;;23870:30;23936:34;23916:18;;;23909:62;-1:-1:-1;;;23987:18:35;;;23980:34;24031:19;;4032:68:0;23656:400:35;4032:68:0;-1:-1:-1;;;;;4114:21:0;;4106:68;;;;-1:-1:-1;;;4106:68:0;;24263:2:35;4106:68:0;;;24245:21:35;24302:2;24282:18;;;24275:30;24341:34;24321:18;;;24314:62;-1:-1:-1;;;24392:18:35;;;24385:32;24434:19;;4106:68:0;24061:398:35;4106:68:0;-1:-1:-1;;;;;4181:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;4228:32;;597:25:35;;;4228:32:0;;570:18:35;4228:32:0;;;;;;;;3927:338;;;:::o;10651:192:31:-;10708:7;-1:-1:-1;;;;;10735:26:31;;;10727:78;;;;-1:-1:-1;;;10727:78:31;;24666:2:35;10727:78:31;;;24648:21:35;24705:2;24685:18;;;24678:30;24744:34;24724:18;;;24717:62;-1:-1:-1;;;24795:18:35;;;24788:37;24842:19;;10727:78:31;24464:403:35;10727:78:31;-1:-1:-1;10830:5:31;10651:192::o;13846:1417:20:-;13928:6;-1:-1:-1;;;;;13928:11:20;13938:1;13928:11;13920:43;;;;-1:-1:-1;;;13920:43:20;;;;;;;:::i;:::-;-1:-1:-1;;;;;14013:22:20;;13970:40;14013:22;;;:16;:22;;;;;;;;;13970:65;;;;;;;;;;;;;;-1:-1:-1;;;13970:65:20;;-1:-1:-1;;;;;13970:65:20;;;;;14046:20;;-1:-1:-1;;;14046:20:20;;;;14041:329;;14142:16;;14113:26;;:45;;14142:16;14113:45;;;:::i;:::-;14094:15;:64;;14076:124;;;;-1:-1:-1;;;14076:124:20;;25422:2:35;14076:124:20;;;25404:21:35;25461:2;25441:18;;;25434:30;-1:-1:-1;;;25480:18:35;;;25473:51;25541:18;;14076:124:20;25220:345:35;14076:124:20;14274:16;;14245:26;;14305:14;;14245:45;;;;;:::i;:::-;14226:65;;:15;:65;:::i;:::-;:93;;14208:155;;;;-1:-1:-1;;;14208:155:20;;25772:2:35;14208:155:20;;;25754:21:35;25811:2;25791:18;;;25784:30;25850:25;25830:18;;;25823:53;25893:18;;14208:155:20;25570:347:35;14208:155:20;14376:21;14400:15;14410:4;14400:9;:15::i;:::-;14445:20;;14376:39;;-1:-1:-1;14421:21:20;;-1:-1:-1;;;14445:20:20;;;;:74;;14496:16;:23;;;-1:-1:-1;;;;;14445:74:20;;;;14474:13;14445:74;14421:98;;14533:13;14550:1;14533:18;14525:58;;;;-1:-1:-1;;;14525:58:20;;26124:2:35;14525:58:20;;;26106:21:35;26163:2;26143:18;;;26136:30;26202:29;26182:18;;;26175:57;26249:18;;14525:58:20;25922:351:35;14525:58:20;14590:22;14625:13;14616:6;-1:-1:-1;;;;;14616:22:20;;14615:49;;14658:6;-1:-1:-1;;;;;14615:49:20;;;;14642:13;14615:49;14590:74;;14671:57;14702:4;14708:13;14723:4;14671:30;:57::i;:::-;;14735:26;14764:29;14778:14;14764:13;:29::i;:::-;14735:58;;14800:39;14806:4;14812:26;:14;:24;:26::i;:::-;14800:5;:39::i;:::-;14850:26;;:31;;;14846:285;;14921:14;14895:16;:23;;;-1:-1:-1;;;;;14895:40:20;;;;;:::i;:::-;14939:1;14895:45;14891:234;;-1:-1:-1;;;;;14959:22:20;;;;;;:16;:22;;;;;14952:29;14891:234;;;15090:26;:14;:24;:26::i;:::-;-1:-1:-1;;;;;15048:22:20;;;;;;:16;:22;;;;;:29;:68;;-1:-1:-1;;;;;15048:68:20;;-1:-1:-1;;;15048:29:20;;-1:-1:-1;;;;;15048:29:20;:68;:::i;:::-;-1:-1:-1;;;;;15006:22:20;;;;;;:16;:22;;;;;:110;;-1:-1:-1;;;;;15006:110:20;;;;-1:-1:-1;;;15006:110:20;;;;;;;;;;;14891:234;15137:57;-1:-1:-1;;;;;15144:12:20;15137:33;15171:2;15175:18;15137:33;:57::i;:::-;15219:2;-1:-1:-1;;;;;15206:52:20;15213:4;-1:-1:-1;;;;;15206:52:20;;15223:18;15243:14;15206:52;;;;;;3527:25:35;;;3583:2;3568:18;;3561:34;3515:2;3500:18;;3353:248;15206:52:20;;;;;;;;13914:1349;;;;;13846:1417;;;:::o;17398:411::-;17481:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;17481:22:20;-1:-1:-1;;;;;17553:15:20;;17511:39;17553:15;;;;;;;;;;;17511:57;;;;;;;;;-1:-1:-1;;;;;17511:57:20;;;;-1:-1:-1;;;;;;;;17511:57:20;;;;;;;;;;;-1:-1:-1;;;17511:57:20;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;17511:57:20;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;17587:217;;;;;;;;17642:9;:37;;;-1:-1:-1;;;;;17587:217:20;;;;;17713:9;:32;;;-1:-1:-1;;;;;17587:217:20;;;;;17771:9;:24;;;17587:217;;;;;;;;:::i;:::-;;;17574:230;17398:411;-1:-1:-1;;;17398:411:20:o;12164:753:1:-;12321:7;;12340:14;:44;;;;;;;;:::i;:::-;;12336:430;;12658:31;12624:9;:24;;;12618:31;;;;;;;;:::i;:::-;:72;12617:79;;12695:1;12617:79;:142;;12757:1;12617:142;;;-1:-1:-1;;;;;12709:27:1;;;;;;;:16;:27;;;;;;;12617:142;12394:365;;;;12336:430;12812:36;12784:9;:24;;;:64;;;;;;;;:::i;:::-;;;:128;;12910:1;12784:128;;;-1:-1:-1;;;;;;;;12859:32:1;;;;;;;:21;:32;;;;;;;;12164:753::o;11287:642:20:-;11386:7;11409:6;11419:1;11409:11;11401:43;;;;-1:-1:-1;;;11401:43:20;;;;;;;:::i;:::-;11450:23;11476:84;11514:4;11526:15;11536:4;11526:9;:15::i;:::-;11549:5;11476:30;:84::i;:::-;11450:110;;11567:21;11601:15;11592:6;:24;11591:65;;11650:6;11591:65;;;11626:15;11591:65;11567:89;;11670:13;11687:1;11670:18;11662:50;;;;-1:-1:-1;;;11662:50:20;;;;;;;:::i;:::-;11748:31;11766:13;11748:15;:31;:::i;:::-;-1:-1:-1;;;;;11719:26:20;;;;;;;:20;:26;;;;;:60;;;;11785:63;;:12;:29;11815:13;11830:2;11834:13;11785:29;:63::i;:::-;11880:2;-1:-1:-1;;;;;11859:39:20;11874:4;-1:-1:-1;;;;;11859:39:20;;11884:13;11859:39;;;;597:25:35;;585:2;570:18;;451:177;11859:39:20;;;;;;;;11911:13;11287:642;-1:-1:-1;;;;;11287:642:20:o;4269:387:0:-;-1:-1:-1;;;;;2046:18:0;;;4381:24;2046:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;-1:-1:-1;;4443:37:0;;4439:213;;4518:6;4498:16;:26;;4490:68;;;;-1:-1:-1;;;4490:68:0;;26670:2:35;4490:68:0;;;26652:21:35;26709:2;26689:18;;;26682:30;26748:31;26728:18;;;26721:59;26797:18;;4490:68:0;26468:353:35;4490:68:0;4586:51;4595:5;4602:7;4630:6;4611:16;:25;4586:8;:51::i;16204:885:20:-;16305:21;16329:15;16339:4;16329:9;:15::i;:::-;16305:39;;16364:57;16395:4;16401:13;16416:4;16364:30;:57::i;:::-;;16457:2;-1:-1:-1;;;;;16449:10:20;:4;-1:-1:-1;;;;;16449:10:20;;16445:600;;16469:19;16491:13;16501:2;16491:9;:13::i;:::-;16469:35;;16512:53;16543:2;16547:11;16560:4;16512:30;:53::i;:::-;-1:-1:-1;;;;;;16623:22:20;;16574:46;16623:22;;;:16;:22;;;;;;;;;16574:71;;;;;;;;;;;;;;;-1:-1:-1;;;16574:71:20;;;-1:-1:-1;;;;;16574:71:20;;;;;;;;16657:37;16653:386;;16819:6;16802:13;:23;16798:233;;-1:-1:-1;;;;;16846:22:20;;;;;;:16;:22;;;;;16839:29;16798:233;;;16914:29;;;;-1:-1:-1;;;;;16889:54:20;:22;16905:6;16889:13;:22;:::i;:::-;:54;16885:146;;;16997:22;17013:6;16997:13;:22;:::i;:::-;-1:-1:-1;;;;;16957:22:20;;;;;;:16;:22;;;;;:63;;-1:-1:-1;;;;;16957:63:20;;;;-1:-1:-1;;;16957:63:20;;;;;;;;;;;16885:146;16461:584;;16445:600;17051:33;17067:4;17073:2;17077:6;17051:15;:33::i;6031:304::-;6079:14;6096:15;6106:4;6096:9;:15::i;:::-;6079:32;;6125:6;6135:1;6125:11;6117:51;;;;-1:-1:-1;;;6117:51:20;;27028:2:35;6117:51:20;;;27010:21:35;27067:2;27047:18;;;27040:30;27106:29;27086:18;;;27079:57;27153:18;;6117:51:20;26826:351:35;6117:51:20;6199:97;;;;;;;;;6242:15;6199:97;;;;-1:-1:-1;;;;;6199:97:20;;;;;;;;;;-1:-1:-1;;;;;6174:22:20;;-1:-1:-1;6174:22:20;;;:16;:22;;;;;;;:122;;;;;;;-1:-1:-1;;;6174:122:20;;;;;;;;;;6308:22;;;;;;6282:6;597:25:35;;585:2;570:18;;451:177;4117:236:4;4170:7;4197:4;-1:-1:-1;;;;;4206:11:4;4189:28;;:63;;;;;4238:14;4221:13;:31;4189:63;4185:164;;;-1:-1:-1;4269:22:4;;4117:236::o;4185:164::-;4319:23;4450:81;;;2301:95;4450:81;;;33436:25:35;4473:11:4;33477:18:35;;;33470:34;;;;4486:14:4;33520:18:35;;;33513:34;4502:13:4;33563:18:35;;;33556:34;4525:4:4;33606:19:35;;;33599:61;4412:7:4;;33408:19:35;;4450:81:4;;;;;;;;;;;;4440:92;;;;;;4427:105;;4357:180;;989:275:32;1179:68;;-1:-1:-1;;;;;27440:15:35;;;1179:68:32;;;27422:34:35;27492:15;;27472:18;;;27465:43;27524:18;;;27517:34;;;1127:130:32;;1160:5;;-1:-1:-1;;;1202:27:32;27357:18:35;;1179:68:32;27182:375:35;15187:1558:1;15527:17;15561:9;-1:-1:-1;;;;;15547:23:1;:10;-1:-1:-1;;;;;15547:23:1;;:49;;15586:10;15547:49;;;15581:1;15547:49;15527:69;;15787:37;15827:30;15847:9;15827:19;:30::i;:::-;15787:70;;15863:24;15890:62;15910:9;15921:14;15937;15890:19;:62::i;:::-;15863:89;;15975:16;-1:-1:-1;;;;;15962:29:1;:9;-1:-1:-1;;;;;15962:29:1;;15958:42;;15993:7;;;15187:1558;;;:::o;15958:42::-;-1:-1:-1;;;;;16027:30:1;;;;;;16088:23;;;;16006:18;16144:22;16156:9;16144:11;:22::i;:::-;16117:49;;16177:13;16173:119;;;16200:85;16231:16;16249:1;16252:16;16270:14;16200:30;:85::i;:::-;16302:17;16298:116;;;16329:78;16360:1;16363:16;16381:9;16392:14;16329:30;:78::i;:::-;16420:60;16443:9;16454:14;16470:9;16420:22;:60::i;:::-;16512:13;16491:34;;:17;:34;;;16487:189;;16535:134;16564:9;16583:78;16611:14;16627;16643:17;16583:27;:78::i;:::-;16535:19;:134::i;:::-;16714:9;-1:-1:-1;;;;;16687:53:1;16703:9;-1:-1:-1;;;;;16687:53:1;;16725:14;16687:53;;;;;;:::i;:::-;;;;;;;;15312:1433;;;;;;15187:1558;;;:::o;18828:108:20:-;18891:7;18913:18;:16;:18::i;7254:260:13:-;7339:7;7359:17;7378:18;7398:16;7418:25;7429:4;7435:1;7438;7441;7418:10;:25::i;:::-;7358:85;;;;;;7453:28;7465:5;7472:8;7453:11;:28::i;:::-;-1:-1:-1;7498:9:13;;-1:-1:-1;;7254:260:13;;;;;;;:::o;10478:274:20:-;421:3:30;10564:10:20;:45;10549:103;;;;-1:-1:-1;;;10549:103:20;;27997:2:35;10549:103:20;;;27979:21:35;28036:2;28016:18;;;28009:30;28075:29;28055:18;;;28048:57;28122:18;;10549:103:20;27795:351:35;10549:103:20;10659:23;:36;;;10706:41;;597:25:35;;;10706:41:20;;585:2:35;570:18;10706:41:20;451:177:35;6885:101:4;6934:13;6962:19;:8;:17;:19::i;10867:158:20:-;10936:16;:34;;;10981:39;;597:25:35;;;10981:39:20;;585:2:35;570:18;10981:39:20;451:177:35;6272:141:4;6318:13;6346:16;:5;:14;:16::i;5032:692:16:-;5161:7;;;5209:484;5233:6;:13;5229:1;:17;5209:484;;;5261:29;5293:6;:33;5300:6;5307:1;5300:9;;;;;;;;:::i;:::-;;;;;;;;;;;;:25;-1:-1:-1;;;;;5293:33:16;;;;;;;;;;;5300:25;5293:33;;;5379:17;;;;5406:29;;5486:9;;5293:33;;-1:-1:-1;5355:160:16;;-1:-1:-1;;;;;5406:29:16;;;;-1:-1:-1;;;5445:31:16;;;;5486:6;;5493:1;;5486:9;;;;;;:::i;:::-;;;;;;;:21;;;5355:14;:160::i;:::-;5334:181;;5574:112;5597:6;5604:1;5597:9;;;;;;;;:::i;:::-;;;;;;;:22;;;5631:10;5653:11;:17;;:23;5671:4;-1:-1:-1;;;;;5653:23:16;-1:-1:-1;;;;;5653:23:16;;;;;;;;;;;;;5574:11;:112::i;:::-;5549:137;;:14;:137;:::i;:::-;5524:162;;5253:440;;5248:3;;;;;:::i;:::-;;;;5209:484;;;-1:-1:-1;5705:14:16;5032:692;-1:-1:-1;;;5032:692:16:o;12163:597:20:-;12278:7;12317:12;-1:-1:-1;;;;;12301:28:20;:12;-1:-1:-1;;;;;12301:28:20;;12293:73;;;;-1:-1:-1;;;12293:73:20;;28353:2:35;12293:73:20;;;28335:21:35;;;28372:18;;;28365:30;28431:34;28411:18;;;28404:62;28483:18;;12293:73:20;28151:356:35;12293:73:20;12373:26;12402:83;12440:4;12452:15;12462:4;12452:9;:15::i;:::-;12475:4;12402:30;:83::i;:::-;12373:112;;12491:21;12525:18;12516:6;:27;12515:71;;12580:6;12515:71;;;12553:18;12515:71;12491:95;-1:-1:-1;12597:18:20;;12593:136;;12625:49;12639:4;12653;12660:13;12625;:49::i;:::-;;12682:40;12697:4;12704:2;12708:13;12682:6;:40::i;:::-;12742:13;12163:597;-1:-1:-1;;;;;12163:597:20:o;12940:720::-;13022:20;;-1:-1:-1;;;13022:20:20;;;;13021:21;13013:50;;;;-1:-1:-1;;;13013:50:20;;28714:2:35;13013:50:20;;;28696:21:35;28753:2;28733:18;;;28726:30;-1:-1:-1;;;28772:18:35;;;28765:46;28828:18;;13013:50:20;28512:340:35;13013:50:20;13077:6;13087:1;13077:11;13069:43;;;;-1:-1:-1;;;13069:43:20;;;;;;;:::i;:::-;13119:19;13141:13;13151:2;13141:9;:13::i;:::-;13119:35;;13161:22;13186:101;13218:2;13236:4;13249:11;13268:13;1582:12:0;;;1499:100;13268:13:20;13186:24;:101::i;:::-;13161:126;-1:-1:-1;13298:19:20;;13294:155;;-1:-1:-1;;;;;13354:24:20;;;;;;:20;:24;;;;;;:41;;13381:14;;13354:41;:::i;:::-;-1:-1:-1;;;;;13327:24:20;;;;;;:20;:24;;;;;;;;;:68;;;;13408:34;;23551:51:35;;;23618:18;;;23611:34;;;13408::20;;23524:18:35;13408:34:20;;;;;;;13294:155;13455:20;13478;13491:6;13478:12;:20::i;:::-;13455:43;-1:-1:-1;13505:58:20;-1:-1:-1;;;;;13505:12:20;:29;13535:4;13549;13556:6;13505:29;:58::i;:::-;13570:35;13576:2;13580:24;:12;:22;:24::i;:::-;13570:5;:35::i;:::-;13630:2;-1:-1:-1;;;;;13617:38:20;13624:4;-1:-1:-1;;;;;13617:38:20;;13634:6;13642:12;13617:38;;;;;;3527:25:35;;;3583:2;3568:18;;3561:34;3515:2;3500:18;;3353:248;13617:38:20;;;;;;;;13007:653;;;12940:720;;;:::o;1187:642:16:-;1304:9;1299:526;1323:17;:24;1319:1;:28;1299:526;;;1362:29;1394:6;:60;1410:17;1428:1;1410:20;;;;;;;;:::i;:::-;;;;;;;:36;;;-1:-1:-1;;;;;1394:60:16;-1:-1:-1;;;;;1394:60:16;;;;;;;;;;;;1362:92;;1463:142;1498:17;1516:1;1498:20;;;;;;;;:::i;:::-;;;;;;;:36;;;1544:11;1565:17;1583:1;1565:20;;;;;;;;:::i;:::-;;;;;;;:32;;;1463:25;:142::i;:::-;;1646:17;1664:1;1646:20;;;;;;;;:::i;:::-;;;;;;;;;;;:38;1614:70;;-1:-1:-1;;1614:70:16;-1:-1:-1;;;;;1614:70:16;;;;;;1726:20;;;;1744:1;;1726:20;;;;;;:::i;:::-;;;;;;;:36;;;-1:-1:-1;;;;;1698:120:16;;1772:17;1790:1;1772:20;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;1698:120;;-1:-1:-1;;;;;29021:47:35;;;29003:66;;28976:18;1698:120:16;;;;;;;-1:-1:-1;1349:3:16;;;;:::i;:::-;;;;1299:526;;4546:478:1;4679:7;4696:32;4731:25;4751:4;4731:19;:25::i;:::-;4696:60;;4762:20;4826:14;4820:21;;;;;;;;:::i;:::-;:25;;4844:1;4820:25;:::i;:::-;4791:9;:24;;;4785:31;;;;;;;;:::i;:::-;:61;:66;;4850:1;4785:66;:102;;4886:1;4785:102;;;4860:17;4872:4;4860:11;:17::i;:::-;4762:125;;4893:26;4922:51;4947:9;4958:14;4922:24;:51::i;:::-;4893:80;-1:-1:-1;4986:33:1;4893:80;4986:12;:33;:::i;:::-;4979:40;4546:478;-1:-1:-1;;;;;;4546:478:1:o;5130:159:4:-;5207:7;5229:55;5251:20;:18;:20::i;:::-;5273:10;9220:4:13;9214:11;-1:-1:-1;;;9238:23:13;;9290:4;9281:14;;9274:39;;;;9342:4;9333:14;;9326:34;9396:4;9381:20;;;9020:397;3357:192:31;3414:7;-1:-1:-1;;;;;3441:26:31;;;3433:78;;;;-1:-1:-1;;;3433:78:31;;29435:2:35;3433:78:31;;;29417:21:35;29474:2;29454:18;;;29447:30;29513:34;29493:18;;;29486:62;-1:-1:-1;;;29564:18:35;;;29557:37;29611:19;;3433:78:31;29233:403:35;3618:786:32;4037:23;4063:103;4104:4;4063:103;;;;;;;;;;;;;;;;;4071:5;-1:-1:-1;;;;;4063:27:32;;;:103;;;;;:::i;:::-;4180:17;;4037:129;;-1:-1:-1;4180:21:32;4176:222;;4292:10;4281:30;;;;;;;;;;;;:::i;:::-;4256:131;;;;-1:-1:-1;;;4256:131:32;;30125:2:35;4256:131:32;;;30107:21:35;30164:2;30144:18;;;30137:30;30203:34;30183:18;;;30176:62;-1:-1:-1;;;30254:18:35;;;30247:40;30304:19;;4256:131:32;29923:406:35;4912:560:19;5041:7;5056:22;5081:103;5113:4;5133;5146:11;5165:13;1582:12:0;;;1499:100;5081:103:19;-1:-1:-1;;;;;5217:26:19;;5190:24;5217:26;;;:20;:26;;;;;;5056:128;;-1:-1:-1;5190:24:19;5217:43;;5056:128;;5217:43;:::i;:::-;5190:70;-1:-1:-1;5271:19:19;;5267:171;;5304:13;5300:83;;;-1:-1:-1;;;;;5329:26:19;;;;;;:20;:26;;;;;:45;;;5300:83;5395:36;;;-1:-1:-1;;;;;23569:32:35;;23551:51;;23633:2;23618:18;;23611:34;;;5395:36:19;;23524:18:35;5395:36:19;;;;;;;5451:16;4912:560;-1:-1:-1;;;;;4912:560:19:o;1245:586:17:-;-1:-1:-1;;;;;1324:21:17;;1316:67;;;;-1:-1:-1;;;1316:67:17;;30536:2:35;1316:67:17;;;30518:21:35;30575:2;30555:18;;;30548:30;30614:34;30594:18;;;30587:62;-1:-1:-1;;;30665:18:35;;;30658:31;30706:19;;1316:67:17;30334:397:35;1316:67:17;-1:-1:-1;;;;;1415:18:17;;1390:22;1415:18;;;;;;;;;;:26;-1:-1:-1;;;;;1415:26:17;;;;1455:24;;;;;1447:71;;;;-1:-1:-1;;;1447:71:17;;30938:2:35;1447:71:17;;;30920:21:35;30977:2;30957:18;;;30950:30;31016:34;30996:18;;;30989:62;-1:-1:-1;;;31067:18:35;;;31060:32;31109:19;;1447:71:17;30736:398:35;1447:71:17;-1:-1:-1;;;;;1542:18:17;;:9;:18;;;;;;;;;;;:52;;-1:-1:-1;;;;;;1542:52:17;1571:23;;;-1:-1:-1;;;;;1542:52:17;;;;;;;;;;1675:12;:22;;;;;;;;;;;1715:37;;31285:60:35;;;1542:9:17;;:18;1715:37;;31258:18:35;1715:37:17;;;;;;;1759:67;1779:7;1796:1;1800:14;-1:-1:-1;;;;;1759:67:17;1816:1;1819:6;-1:-1:-1;;;;;1759:67:17;:19;:67::i;5441:192:31:-;5498:7;-1:-1:-1;;;;;5525:26:31;;;5517:78;;;;-1:-1:-1;;;5517:78:31;;31558:2:35;5517:78:31;;;31540:21:35;31597:2;31577:18;;;31570:30;31636:34;31616:18;;;31609:62;-1:-1:-1;;;31687:18:35;;;31680:37;31734:19;;5517:78:31;31356:403:35;3168:755:0;-1:-1:-1;;;;;3276:18:0;;3268:68;;;;-1:-1:-1;;;3268:68:0;;31966:2:35;3268:68:0;;;31948:21:35;32005:2;31985:18;;;31978:30;32044:34;32024:18;;;32017:62;-1:-1:-1;;;32095:18:35;;;32088:35;32140:19;;3268:68:0;31764:401:35;3268:68:0;-1:-1:-1;;;;;3350:16:0;;3342:64;;;;-1:-1:-1;;;3342:64:0;;32372:2:35;3342:64:0;;;32354:21:35;32411:2;32391:18;;;32384:30;32450:34;32430:18;;;32423:62;-1:-1:-1;;;32501:18:35;;;32494:33;32544:19;;3342:64:0;32170:399:35;3342:64:0;3425:2;-1:-1:-1;;;;;3417:10:0;:4;-1:-1:-1;;;;;3417:10:0;;3413:469;;-1:-1:-1;;;;;3465:15:0;;;3437:25;3465:15;;;;;;;;;;;:23;3522:13;;;;;;;:21;-1:-1:-1;;;;;3465:23:0;;;;3522:21;3560:27;;;;3552:78;;;;-1:-1:-1;;;3552:78:0;;32776:2:35;3552:78:0;;;32758:21:35;32815:2;32795:18;;;32788:30;32854:34;32834:18;;;32827:62;-1:-1:-1;;;32905:18:35;;;32898:36;32951:19;;3552:78:0;32574:402:35;3552:78:0;-1:-1:-1;;;;;3658:15:0;;:9;:15;;;;;;;;;;:61;;-1:-1:-1;;;;;;3658:61:0;3684:35;;;-1:-1:-1;;;;;3658:61:0;;;;3760:33;3684:35;3760:15;:33;:::i;:::-;-1:-1:-1;;;;;3736:13:0;;:9;:13;;;;;;;;;;:57;;-1:-1:-1;;;;;;3736:57:0;-1:-1:-1;;;;;3736:57:0;;;;;;3802:73;;3822:4;;3736:13;;3802:73;;;;;;3868:6;3802:19;:73::i;:::-;3429:453;;3413:469;3907:2;-1:-1:-1;;;;;3892:26:0;3901:4;-1:-1:-1;;;;;3892:26:0;;3911:6;3892:26;;;;597:25:35;;585:2;570:18;;451:177;17813:109:20;17880:7;17902:15;17912:4;17902:9;:15::i;7960:1281:1:-;-1:-1:-1;;;;;8161:23:1;;8157:36;8186:7;8157:36;8198:64;;;8255:7;8198:64;8458:33;8494:78;8521:45;1723:4;8521:24;:45;:::i;:::-;8494:19;:78::i;:::-;8458:114;-1:-1:-1;8578:32:1;8613:77;8640:44;1723:4;8640:23;:44;:::i;8613:77::-;8578:112;;8697:37;8737:30;8757:9;8737:19;:30::i;:::-;8697:70;-1:-1:-1;8795:26:1;8777:14;:44;;;;;;;;:::i;:::-;;8773:412;;8964:25;8927:26;8879:14;:37;;;:74;;;;:::i;:::-;:110;;;;:::i;:::-;-1:-1:-1;;;;;8831:158:1;:37;;;:158;8773:412;;;9063:42;;9153:25;;9063:79;;9116:26;;9063:79;:::i;:::-;:115;;;;:::i;:::-;-1:-1:-1;;;;;9010:168:1;;;8773:412;9190:46;9210:9;9221:14;9190:19;:46::i;13192:404::-;13333:20;13373:9;-1:-1:-1;;;;;13356:26:1;:13;-1:-1:-1;;;;;13356:26:1;;:55;;13398:13;13356:55;;;13393:1;13356:55;13333:78;-1:-1:-1;13439:26:1;13421:14;:44;;;;;;;;:::i;:::-;;13417:175;;-1:-1:-1;;;;;13475:27:1;;;;;;;:16;:27;;;;;:42;;-1:-1:-1;;;;;;13475:42:1;;;;;;;;;;13417:175;;;-1:-1:-1;;;;;13538:32:1;;;;;;;:21;:32;;;;;:47;;-1:-1:-1;;;;;;13538:47:1;;;;;;;;;-1:-1:-1;;13192:404:1:o;13921:840::-;14086:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;14086:22:1;14120:12;14116:619;;;14334:14;14328:21;;;;;;;;:::i;:::-;:25;;14352:1;14328:25;:::i;:::-;14299:9;:24;;;14293:31;;;;;;;;:::i;:::-;:61;14269:93;;;;;;;;;;:::i;:::-;14242:9;:24;;:120;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;14116:619:1;;;14683:35;14654:14;14648:21;;;;;;;;:::i;:::-;:25;;14672:1;14648:25;:::i;:::-;14647:72;14608:9;:24;;;14602:31;;;;;;;;:::i;:::-;:118;14578:150;;;;;;;;;;:::i;:::-;14551:9;:24;;:177;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;14116:619:1;-1:-1:-1;14747:9:1;;13921:840;-1:-1:-1;;13921:840:1:o;18172:420:20:-;-1:-1:-1;;;;;18334:15:20;;18291:40;18334:15;;;;;;;;;;;;18395:50;;18355:90;;18486:38;;;;-1:-1:-1;;;;18451:73:20;;;-1:-1:-1;;;;;;;;18355:90:20;;;;-1:-1:-1;;;;18451:73:20;;-1:-1:-1;;;18451:73:20;;;;;;;;;;;;18557:30;;;;18334:15;;;;-1:-1:-1;;;;;18530:57:20;-1:-1:-1;;;18557:30:20;18530:57;;;;;;;;:::i;:::-;;;;;;18285:307;18172:420;;:::o;5591:1530:13:-;5717:7;;;6650:66;6637:79;;6633:164;;;-1:-1:-1;6748:1:13;;-1:-1:-1;6752:30:13;;-1:-1:-1;6784:1:13;6732:54;;6633:164;6908:24;;;6891:14;6908:24;;;;;;;;;34275:25:35;;;34348:4;34336:17;;34316:18;;;34309:45;;;;34370:18;;;34363:34;;;34413:18;;;34406:34;;;6908:24:13;;34247:19:35;;6908:24:13;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6908:24:13;;-1:-1:-1;;6908:24:13;;;-1:-1:-1;;;;;;;6946:20:13;;6942:113;;-1:-1:-1;6998:1:13;;-1:-1:-1;7002:29:13;;-1:-1:-1;6998:1:13;;-1:-1:-1;6982:62:13;;6942:113;7073:6;-1:-1:-1;7081:20:13;;-1:-1:-1;7081:20:13;;-1:-1:-1;5591:1530:13;;;;;;;;;:::o;883:532::-;978:20;969:5;:29;;;;;;;;:::i;:::-;;965:444;;883:532;;:::o;965:444::-;1074:29;1065:5;:38;;;;;;;;:::i;:::-;;1061:348;;1126:23;;-1:-1:-1;;;1126:23:13;;;;;;;;;;;1061:348;1179:35;1170:5;:44;;;;;;;;:::i;:::-;;1166:243;;1237:46;;-1:-1:-1;;;1237:46:13;;;;;597:25:35;;;570:18;;1237:46:13;451:177:35;1166:243:13;1313:30;1304:5;:39;;;;;;;;:::i;:::-;;1300:109;;1366:32;;-1:-1:-1;;;1366:32:13;;;;;597:25:35;;;570:18;;1366:32:13;451:177:35;2060:405:10;2119:13;2144:11;2158:16;2169:4;2158:10;:16::i;:::-;2282:14;;;2293:2;2282:14;;;;;;;;;2144:30;;-1:-1:-1;2262:17:10;;2282:14;;;;;;;;;-1:-1:-1;;;2372:16:10;;;-1:-1:-1;2417:4:10;2408:14;;2401:28;;;;-1:-1:-1;2372:16:10;2060:405::o;6770:684:16:-;6937:7;6963:22;;;:49;;-1:-1:-1;6995:17:16;;6963:49;:97;;;;7045:15;7022:19;-1:-1:-1;;;;;7022:38:16;;6963:97;:146;;;;7093:16;7070:19;-1:-1:-1;;;;;7070:39:16;;;6963:146;6952:198;;;-1:-1:-1;7131:12:16;7124:19;;6952:198;7156:24;7201:16;7183:15;:34;:83;;7251:15;7183:83;;;7226:16;7183:83;7156:110;-1:-1:-1;7272:17:16;7292:38;-1:-1:-1;;;;;7292:38:16;;7156:110;7292:38;:::i;:::-;7272:58;-1:-1:-1;7437:12:16;7421;7384:24;568:2;7384;:24;:::i;:::-;7351:29;7371:9;7351:17;:29;:::i;:::-;:58;;;;:::i;:::-;7350:83;;;;:::i;:::-;7349:100;;;;:::i;:::-;7336:113;6770:684;-1:-1:-1;;;;;;;6770:684:16:o;6068:250::-;6199:7;6288:24;568:2;6288;:24;:::i;:::-;6252;6267:9;6252:12;:24;:::i;:::-;6228:49;;:20;:49;:::i;:::-;6227:86;;;;:::i;3356:641::-;-1:-1:-1;;;;;3545:13:16;;;3500:7;3545:13;;;:6;:13;;;;;;;;3584:21;;;;;:15;;;:21;;;;;;3500:7;;3545:13;3500:7;;3663:56;3552:5;3545:13;3707:11;3663:25;:56::i;:::-;3644:75;;3743:8;3730:9;:21;3726:239;;3765:17;;3761:105;;3811:46;3823:12;3837:8;3847:9;3811:11;:46::i;:::-;3794:63;;3761:105;-1:-1:-1;;;;;3874:21:16;;;;;;;:15;;;:21;;;;;;;:32;;;3919:39;;;;;;;;;3898:8;597:25:35;;585:2;570:18;;451:177;3919:39:16;;;;;;;;3726:239;-1:-1:-1;3978:14:16;3356:641;-1:-1:-1;;;;;;;3356:641:16:o;560:389:17:-;-1:-1:-1;;;;;639:21:17;;631:65;;;;-1:-1:-1;;;631:65:17;;36027:2:35;631:65:17;;;36009:21:35;36066:2;36046:18;;;36039:30;36105:33;36085:18;;;36078:61;36156:18;;631:65:17;35825:355:35;631:65:17;-1:-1:-1;;;;;727:18:17;;703:21;727:18;;;;;;;;;;:26;759:12;:22;;-1:-1:-1;;;;;727:26:17;;;;759:22;;;;703:21;759:22;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;787:18:17;;:9;:18;;;;;;;;;;:36;;817:6;;787:9;:36;;817:6;;-1:-1:-1;;;;;787:36:17;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;787:36:17;;;;;-1:-1:-1;;;;;787:36:17;;;;;;855:7;-1:-1:-1;;;;;834:37:17;851:1;-1:-1:-1;;;;;834:37:17;;864:6;834:37;;;;;-1:-1:-1;;;;;31303:41:35;;;;31285:60;;31273:2;31258:18;;31139:212;834:37:17;;;;;;;;878:66;906:1;910:7;919:1;922:13;-1:-1:-1;;;;;878:66:17;937:6;-1:-1:-1;;;;;878:66:17;:19;:66::i;2239:713:16:-;2419:17;;;;2472:31;;2385:7;;2419:17;-1:-1:-1;;;2472:31:16;;-1:-1:-1;;;;;2472:31:16;2514:15;:38;;;2510:74;;-1:-1:-1;2569:8:16;-1:-1:-1;2562:15:16;;2510:74;2647:29;;2590:16;;2609:119;;2631:8;;-1:-1:-1;;;;;2647:29:16;2684:19;2711:11;2609:14;:119::i;:::-;2590:138;;2751:8;2739;:20;2735:126;;2769:17;;;:28;;;2810:44;;597:25:35;;;-1:-1:-1;;;;;2810:44:16;;;;;585:2:35;570:18;2810:44:16;;;;;;;2735:126;2867:58;;-1:-1:-1;;;;;2909:15:16;2867:58;;-1:-1:-1;;;2867:58:16;;;;;;2939:8;-1:-1:-1;;;2239:713:16;;;;;:::o;11428:356:1:-;11567:7;;11632:14;:44;;;;;;;;:::i;:::-;;:139;;11734:37;;11632:139;;;11689:9;:32;;;11632:139;11595:184;;-1:-1:-1;;;;;11595:184:1;1723:4;11595:184;:::i;3872:223:27:-;4005:12;4036:52;4058:6;4066:4;4072:1;4075:12;4036:21;:52::i;2328:563:18:-;2499:115;2532:4;2544:2;2554:17;2579:15;2602:6;2499:25;:115::i;:::-;2658:12;;-1:-1:-1;;;;;2658:12:18;2681:32;;2677:210;;2723:157;2760:18;2788:4;2802:2;2814:17;2841:15;2866:6;2723:27;:157::i;:::-;2493:398;2328:563;;;;;:::o;450:177:5:-;506:6;-1:-1:-1;;;;;528:25:5;;;520:76;;;;-1:-1:-1;;;520:76:5;;36387:2:35;520:76:5;;;36369:21:35;36426:2;36406:18;;;36399:30;36465:34;36445:18;;;36438:62;-1:-1:-1;;;36516:18:35;;;36509:36;36562:19;;520:76:5;36185:402:35;2537:245:10;2598:7;2670:4;2634:40;;2697:2;2688:11;;2684:69;;;2722:20;;-1:-1:-1;;;2722:20:10;;;;;;;;;;;4959:446:27;5124:12;5181:5;5156:21;:30;;5148:81;;;;-1:-1:-1;;;5148:81:27;;36794:2:35;5148:81:27;;;36776:21:35;36833:2;36813:18;;;36806:30;36872:34;36852:18;;;36845:62;-1:-1:-1;;;36923:18:35;;;36916:36;36969:19;;5148:81:27;36592:402:35;5148:81:27;5240:12;5254:23;5281:6;-1:-1:-1;;;;;5281:11:27;5300:5;5307:4;5281:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5239:73;;;;5329:69;5356:6;5364:7;5373:10;5385:12;5329:26;:69::i;17093:301:20:-;17272:117;17307:4;17319:2;17329:17;17354:15;17377:6;17272:27;:117::i;3068:970:18:-;3532:4;3526:11;-1:-1:-1;;;3544:21:18;;;3588:4;3579:14;;3572:28;;;3623:4;3614:14;;3607:26;;;3656:4;3647:14;;3640:41;;;3704:4;3695:14;;3688:39;;;3750:4;3741:14;;3734:30;;;3288:83;3396:7;;3787:5;3861:1;3858;3852:4;3847:3;3844:1;3824:18;3814:8;3809:54;3799:229;;3908:8;3903:2;3898;3889:7;3885:16;3881:25;3878:39;3875:145;;;3953:16;3950:1;3945:3;3930:40;3993:16;3988:3;3981:29;3875:145;3799:229;;3458:576;;3068:970;;;;;;:::o;7465:628:27:-;7645:12;7673:7;7669:418;;;7700:10;:17;7721:1;7700:22;7696:286;;-1:-1:-1;;;;;1465:19:27;;;7907:60;;;;-1:-1:-1;;;7907:60:27;;37493:2:35;7907:60:27;;;37475:21:35;37532:2;37512:18;;;37505:30;37571:31;37551:18;;;37544:59;37620:18;;7907:60:27;37291:353:35;7907:60:27;-1:-1:-1;8002:10:27;7995:17;;7669:418;8043:33;8051:10;8063:12;8043:7;:33::i;9573:1608:1:-;9755:2;-1:-1:-1;;;;;9747:10:1;:4;-1:-1:-1;;;;;9747:10:1;;9743:37;9767:7;9743:37;-1:-1:-1;;;;;9790:18:1;;;9786:706;;9818:36;9857:25;9877:4;9857:19;:25::i;:::-;9818:64;-1:-1:-1;9890:24:1;9917:26;9937:6;9917:17;:26;:::i;:::-;9890:53;-1:-1:-1;9987:28:1;9955:13;:28;;;:60;;;;;;;;:::i;:::-;;9951:535;;10027:215;10069:17;10098:16;10126:68;10146:4;10152:13;10167:26;10126:19;:68::i;:::-;10206:26;10027:30;:215::i;:::-;10252:225;10294:17;10323:16;10351:73;10371:4;10377:13;10392:31;10351:19;:73::i;:::-;10436:31;10252:30;:225::i;:::-;9810:682;;9786:706;-1:-1:-1;;;;;10502:16:1;;;10498:679;;10528:34;10565:23;10585:2;10565:19;:23::i;:::-;10528:60;-1:-1:-1;10596:22:1;10621:24;10639:6;10621:15;:24;:::i;:::-;10596:49;-1:-1:-1;10688:28:1;10658:11;:26;;;:58;;;;;;;;:::i;:::-;;10654:517;;10728:207;10770:15;10797:14;10823:64;10843:2;10847:11;10860:26;10823:19;:64::i;10728:207::-;10945:217;10987:15;11014:14;11040:69;11060:2;11064:11;11077:31;11040:19;:69::i;8615:540:27:-;8774:17;;:21;8770:379;;9002:10;8996:17;9058:15;9045:10;9041:2;9037:19;9030:44;8770:379;9125:12;9118:20;;-1:-1:-1;;;9118:20:27;;;;;;;;:::i;14:173:35:-;82:20;;-1:-1:-1;;;;;131:31:35;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:254::-;260:6;268;321:2;309:9;300:7;296:23;292:32;289:52;;;337:1;334;327:12;289:52;360:29;379:9;360:29;:::i;:::-;350:39;436:2;421:18;;;;408:32;;-1:-1:-1;;;192:254:35:o;633:250::-;718:1;728:113;742:6;739:1;736:13;728:113;;;818:11;;;812:18;799:11;;;792:39;764:2;757:10;728:113;;;-1:-1:-1;;875:1:35;857:16;;850:27;633:250::o;888:271::-;930:3;968:5;962:12;995:6;990:3;983:19;1011:76;1080:6;1073:4;1068:3;1064:14;1057:4;1050:5;1046:16;1011:76;:::i;:::-;1141:2;1120:15;-1:-1:-1;;1116:29:35;1107:39;;;;1148:4;1103:50;;888:271;-1:-1:-1;;888:271:35:o;1164:220::-;1313:2;1302:9;1295:21;1276:4;1333:45;1374:2;1363:9;1359:18;1351:6;1333:45;:::i;1389:186::-;1448:6;1501:2;1489:9;1480:7;1476:23;1472:32;1469:52;;;1517:1;1514;1507:12;1469:52;1540:29;1559:9;1540:29;:::i;2068:180::-;2127:6;2180:2;2168:9;2159:7;2155:23;2151:32;2148:52;;;2196:1;2193;2186:12;2148:52;-1:-1:-1;2219:23:35;;2068:180;-1:-1:-1;2068:180:35:o;2461:328::-;2538:6;2546;2554;2607:2;2595:9;2586:7;2582:23;2578:32;2575:52;;;2623:1;2620;2613:12;2575:52;2646:29;2665:9;2646:29;:::i;:::-;2636:39;;2694:38;2728:2;2717:9;2713:18;2694:38;:::i;:::-;2684:48;;2779:2;2768:9;2764:18;2751:32;2741:42;;2461:328;;;;;:::o;4200:260::-;4268:6;4276;4329:2;4317:9;4308:7;4304:23;4300:32;4297:52;;;4345:1;4342;4335:12;4297:52;4368:29;4387:9;4368:29;:::i;:::-;4358:39;;4416:38;4450:2;4439:9;4435:18;4416:38;:::i;:::-;4406:48;;4200:260;;;;;:::o;4673:160::-;4758:20;;4807:1;4797:12;;4787:40;;4823:1;4820;4813:12;4838:156;4904:20;;4964:4;4953:16;;4943:27;;4933:55;;4984:1;4981;4974:12;4999:653;5134:6;5142;5150;5158;5166;5174;5182;5235:3;5223:9;5214:7;5210:23;5206:33;5203:53;;;5252:1;5249;5242:12;5203:53;5275:29;5294:9;5275:29;:::i;:::-;5265:39;;5323:38;5357:2;5346:9;5342:18;5323:38;:::i;:::-;5313:48;;5380:55;5431:2;5420:9;5416:18;5380:55;:::i;:::-;5370:65;;5482:2;5471:9;5467:18;5454:32;5444:42;;5505:37;5537:3;5526:9;5522:19;5505:37;:::i;:::-;5495:47;;5589:3;5578:9;5574:19;5561:33;5551:43;;5641:3;5630:9;5626:19;5613:33;5603:43;;4999:653;;;;;;;;;;:::o;5657:301::-;5749:6;5757;5810:2;5798:9;5789:7;5785:23;5781:32;5778:52;;;5826:1;5823;5816:12;5778:52;5849:29;5868:9;5849:29;:::i;:::-;5839:39;;5897:55;5948:2;5937:9;5933:18;5897:55;:::i;6186:1259::-;6592:3;6587;6583:13;6575:6;6571:26;6560:9;6553:45;6534:4;6617:2;6655:3;6650:2;6639:9;6635:18;6628:31;6682:46;6723:3;6712:9;6708:19;6700:6;6682:46;:::i;:::-;6776:9;6768:6;6764:22;6759:2;6748:9;6744:18;6737:50;6810:33;6836:6;6828;6810:33;:::i;:::-;6874:2;6859:18;;6852:34;;;-1:-1:-1;;;;;6923:32:35;;6917:3;6902:19;;6895:61;6943:3;6972:19;;6965:35;;;7037:22;;;7031:3;7016:19;;7009:51;7109:13;;7131:22;;;7207:15;;;;-1:-1:-1;7169:15:35;;;;-1:-1:-1;7250:169:35;7264:6;7261:1;7258:13;7250:169;;;7325:13;;7313:26;;7394:15;;;;7359:12;;;;7286:1;7279:9;7250:169;;;-1:-1:-1;7436:3:35;;6186:1259;-1:-1:-1;;;;;;;;;;;;6186:1259:35:o;7450:397::-;7536:6;7544;7552;7560;7613:3;7601:9;7592:7;7588:23;7584:33;7581:53;;;7630:1;7627;7620:12;7581:53;7653:29;7672:9;7653:29;:::i;:::-;7643:39;;7701:38;7735:2;7724:9;7720:18;7701:38;:::i;:::-;7450:397;;7691:48;;-1:-1:-1;;;;7786:2:35;7771:18;;7758:32;;7837:2;7822:18;7809:32;;7450:397::o;7852:537::-;7954:6;7962;7970;7978;7986;7994;8047:3;8035:9;8026:7;8022:23;8018:33;8015:53;;;8064:1;8061;8054:12;8015:53;8087:29;8106:9;8087:29;:::i;:::-;8077:39;;8135:38;8169:2;8158:9;8154:18;8135:38;:::i;:::-;8125:48;;8220:2;8209:9;8205:18;8192:32;8182:42;;8243:36;8275:2;8264:9;8260:18;8243:36;:::i;:::-;8233:46;;8326:3;8315:9;8311:19;8298:33;8288:43;;8378:3;8367:9;8363:19;8350:33;8340:43;;7852:537;;;;;;;;:::o;8394:254::-;8462:6;8470;8523:2;8511:9;8502:7;8498:23;8494:32;8491:52;;;8539:1;8536;8529:12;8491:52;8575:9;8562:23;8552:33;;8604:38;8638:2;8627:9;8623:18;8604:38;:::i;8653:127::-;8714:10;8709:3;8705:20;8702:1;8695:31;8745:4;8742:1;8735:15;8769:4;8766:1;8759:15;8785:253;8857:2;8851:9;8899:4;8887:17;;8934:18;8919:34;;8955:22;;;8916:62;8913:88;;;8981:18;;:::i;:::-;9017:2;9010:22;8785:253;:::o;9043:275::-;9114:2;9108:9;9179:2;9160:13;;-1:-1:-1;;9156:27:35;9144:40;;9214:18;9199:34;;9235:22;;;9196:62;9193:88;;;9261:18;;:::i;:::-;9297:2;9290:22;9043:275;;-1:-1:-1;9043:275:35:o;9323:1565::-;9441:6;9472:2;9515;9503:9;9494:7;9490:23;9486:32;9483:52;;;9531:1;9528;9521:12;9483:52;9571:9;9558:23;9600:18;9641:2;9633:6;9630:14;9627:34;;;9657:1;9654;9647:12;9627:34;9695:6;9684:9;9680:22;9670:32;;9740:7;9733:4;9729:2;9725:13;9721:27;9711:55;;9762:1;9759;9752:12;9711:55;9798:2;9785:16;9820:2;9816;9813:10;9810:36;;;9826:18;;:::i;:::-;9866:36;9898:2;9893;9890:1;9886:10;9882:19;9866:36;:::i;:::-;9936:15;;;9967:12;;;;-1:-1:-1;9998:4:35;10037:11;;;10029:20;;10025:29;;;10066:19;;;10063:39;;;10098:1;10095;10088:12;10063:39;10122:11;;;;10142:716;10158:6;10153:3;10150:15;10142:716;;;10238:2;10232:3;10223:7;10219:17;10215:26;10212:116;;;10282:1;10311:2;10307;10300:14;10212:116;10354:22;;:::i;:::-;10417:3;10404:17;-1:-1:-1;;;;;10460:7:35;10456:48;10447:7;10444:61;10434:159;;10547:1;10576:2;10572;10565:14;10434:159;10606:22;;10677:12;;;10664:26;10648:14;;;10641:50;10714:2;10752:32;10771:12;;;10752:32;:::i;:::-;10736:14;;;10729:56;10798:18;;10175:12;;;;10836;;;;10142:716;;10893:606;11004:6;11012;11020;11028;11036;11044;11052;11105:3;11093:9;11084:7;11080:23;11076:33;11073:53;;;11122:1;11119;11112:12;11073:53;11145:29;11164:9;11145:29;:::i;:::-;11135:39;;11193:38;11227:2;11216:9;11212:18;11193:38;:::i;:::-;11183:48;;11278:2;11267:9;11263:18;11250:32;11240:42;;11329:2;11318:9;11314:18;11301:32;11291:42;;11352:37;11384:3;11373:9;11369:19;11352:37;:::i;11504:322::-;11581:6;11589;11597;11650:2;11638:9;11629:7;11625:23;11621:32;11618:52;;;11666:1;11663;11656:12;11618:52;11689:29;11708:9;11689:29;:::i;:::-;11679:39;11765:2;11750:18;;11737:32;;-1:-1:-1;11816:2:35;11801:18;;;11788:32;;11504:322;-1:-1:-1;;;11504:322:35:o;11831:456::-;11924:6;11932;11940;11948;11956;12009:3;11997:9;11988:7;11984:23;11980:33;11977:53;;;12026:1;12023;12016:12;11977:53;12062:9;12049:23;12039:33;;12119:2;12108:9;12104:18;12091:32;12081:42;;12142:36;12174:2;12163:9;12159:18;12142:36;:::i;:::-;11831:456;;;;-1:-1:-1;12132:46:35;;12225:2;12210:18;;12197:32;;-1:-1:-1;12276:3:35;12261:19;12248:33;;11831:456;-1:-1:-1;;11831:456:35:o;12687:349::-;12889:2;12871:21;;;12928:2;12908:18;;;12901:30;12967:27;12962:2;12947:18;;12940:55;13027:2;13012:18;;12687:349::o;13739:127::-;13800:10;13795:3;13791:20;13788:1;13781:31;13831:4;13828:1;13821:15;13855:4;13852:1;13845:15;13871:128;13938:9;;;13959:11;;;13956:37;;;13973:18;;:::i;14353:380::-;14432:1;14428:12;;;;14475;;;14496:61;;14550:4;14542:6;14538:17;14528:27;;14496:61;14603:2;14595:6;14592:14;14572:18;14569:38;14566:161;;14649:10;14644:3;14640:20;14637:1;14630:31;14684:4;14681:1;14674:15;14712:4;14709:1;14702:15;14566:161;;14353:380;;;:::o;14738:347::-;14940:2;14922:21;;;14979:2;14959:18;;;14952:30;15018:25;15013:2;14998:18;;14991:53;15076:2;15061:18;;14738:347::o;15090:125::-;15155:9;;;15176:10;;;15173:36;;;15189:18;;:::i;15912:168::-;15985:9;;;16016;;16033:15;;;16027:22;;16013:37;16003:71;;16054:18;;:::i;16085:217::-;16125:1;16151;16141:132;;16195:10;16190:3;16186:20;16183:1;16176:31;16230:4;16227:1;16220:15;16258:4;16255:1;16248:15;16141:132;-1:-1:-1;16287:9:35;;16085:217::o;16307:337::-;16509:2;16491:21;;;16548:2;16528:18;;;16521:30;-1:-1:-1;;;16582:2:35;16567:18;;16560:43;16635:2;16620:18;;16307:337::o;16649:342::-;16851:2;16833:21;;;16890:2;16870:18;;;16863:30;-1:-1:-1;;;16924:2:35;16909:18;;16902:48;16982:2;16967:18;;16649:342::o;16996:127::-;17057:10;17052:3;17048:20;17045:1;17038:31;17088:4;17085:1;17078:15;17112:4;17109:1;17102:15;17128:247;17219:1;17212:5;17209:12;17199:143;;17264:10;17259:3;17255:20;17252:1;17245:31;17299:4;17296:1;17289:15;17327:4;17324:1;17317:15;17199:143;17351:18;;17128:247::o;17380:642::-;17689:25;;;-1:-1:-1;;;;;17788:15:35;;;17783:2;17768:18;;17761:43;17840:15;;17835:2;17820:18;;17813:43;17676:3;17661:19;;17865:63;17924:2;17909:18;;17901:6;17865:63;:::i;:::-;17959:3;17944:19;;17937:35;;;;18003:3;17988:19;17981:35;17380:642;;-1:-1:-1;;;;17380:642:35:o;18027:341::-;18229:2;18211:21;;;18268:2;18248:18;;;18241:30;-1:-1:-1;;;18302:2:35;18287:18;;18280:47;18359:2;18344:18;;18027:341::o;19142:127::-;19203:10;19198:3;19194:20;19191:1;19184:31;19234:4;19231:1;19224:15;19258:4;19255:1;19248:15;20904:135;20943:3;20964:17;;;20961:43;;20984:18;;:::i;:::-;-1:-1:-1;21031:1:35;21020:13;;20904:135::o;24872:343::-;25074:2;25056:21;;;25113:2;25093:18;;;25086:30;-1:-1:-1;;;25147:2:35;25132:18;;25125:49;25206:2;25191:18;;24872:343::o;26278:185::-;-1:-1:-1;;;;;26399:10:35;;;26387;;;26383:27;;26422:12;;;26419:38;;;26437:18;;:::i;:::-;26419:38;26278:185;;;;:::o;27562:228::-;27718:2;27703:18;;27730:54;27707:9;27766:6;27730:54;:::i;29080:148::-;29168:4;29147:12;;;29161;;;29143:31;;29186:13;;29183:39;;;29202:18;;:::i;29641:277::-;29708:6;29761:2;29749:9;29740:7;29736:23;29732:32;29729:52;;;29777:1;29774;29767:12;29729:52;29809:9;29803:16;29862:5;29855:13;29848:21;29841:5;29838:32;29828:60;;29884:1;29881;29874:12;32981:191;-1:-1:-1;;;;;33097:10:35;;;33109;;;33093:27;;33132:11;;;33129:37;;;33146:18;;:::i;33671:185::-;-1:-1:-1;;;;;33792:10:35;;;33780;;;33776:27;;33815:12;;;33812:38;;;33830:18;;:::i;33861:182::-;-1:-1:-1;;;;;33968:10:35;;;33980;;;33964:27;;34003:11;;;34000:37;;;34017:18;;:::i;34451:422::-;34540:1;34583:5;34540:1;34597:270;34618:7;34608:8;34605:21;34597:270;;;34677:4;34673:1;34669:6;34665:17;34659:4;34656:27;34653:53;;;34686:18;;:::i;:::-;34736:7;34726:8;34722:22;34719:55;;;34756:16;;;;34719:55;34835:22;;;;34795:15;;;;34597:270;;;34601:3;34451:422;;;;;:::o;34878:806::-;34927:5;34957:8;34947:80;;-1:-1:-1;34998:1:35;35012:5;;34947:80;35046:4;35036:76;;-1:-1:-1;35083:1:35;35097:5;;35036:76;35128:4;35146:1;35141:59;;;;35214:1;35209:130;;;;35121:218;;35141:59;35171:1;35162:10;;35185:5;;;35209:130;35246:3;35236:8;35233:17;35230:43;;;35253:18;;:::i;:::-;-1:-1:-1;;35309:1:35;35295:16;;35324:5;;35121:218;;35423:2;35413:8;35410:16;35404:3;35398:4;35395:13;35391:36;35385:2;35375:8;35372:16;35367:2;35361:4;35358:12;35354:35;35351:77;35348:159;;;-1:-1:-1;35460:19:35;;;35492:5;;35348:159;35539:34;35564:8;35558:4;35539:34;:::i;:::-;35609:6;35605:1;35601:6;35597:19;35588:7;35585:32;35582:58;;;35620:18;;:::i;:::-;35658:20;;34878:806;-1:-1:-1;;;34878:806:35:o;35689:131::-;35749:5;35778:36;35805:8;35799:4;35778:36;:::i;36999:287::-;37128:3;37166:6;37160:13;37182:66;37241:6;37236:3;37229:4;37221:6;37217:17;37182:66;:::i;:::-;37264:16;;;;;36999:287;-1:-1:-1;;36999:287:35:o
Swarm Source
ipfs://385b96f1c8f473a813ebd23eecf2eaf0bec52cdecaeeff8cb048e4b8d7ea13d2
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.