Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
StakedTokenV3
Compiler Version
v0.7.5+commit.eb77ed08
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // File contracts/stake/StakedTokenV3.sol /** * @title StakedToken * @notice Contract to stake Aave token, tokenize the position and get rewards, inheriting from a distribution manager contract * @author Aave **/ pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import "./helper/ReentrancyGuardUpgradeable.sol"; import "./AaveDistributionManager.sol"; import "./interface/IERC20.sol"; import "./interface/IGovernancePowerDelegationToken.sol"; import "./interface/ITransferHook.sol"; import "./interface/IStakedAave.sol"; import "./helper/Context.sol"; import "./helper/GovernancePowerWithSnapshot.sol"; import "./helper/GovernancePowerDelegationERC20.sol"; import "./helper/VersionedInitializable.sol"; import "./helper/ERC2771Context.sol"; import "./lib/SafeERC20.sol"; /** * @title StakedToken V3 * @notice Contract to stake Aave token, tokenize the position and get rewards, inheriting from a distribution manager contract * @author Aave **/ contract StakedTokenV3 is IStakedAave, GovernancePowerWithSnapshot, VersionedInitializable, AaveDistributionManager, ERC2771Context, ReentrancyGuardUpgradeable { using SafeMath for uint256; using SafeERC20 for IERC20; /// @dev Start of Storage layout from StakedToken v1 uint256 public constant REVISION = 1; IERC20 public immutable STAKED_TOKEN; IERC20 public immutable REWARD_TOKEN; uint256 public immutable COOLDOWN_SECONDS; /// @notice Seconds available to redeem once the cooldown period is fullfilled 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 => uint256) public stakersCooldowns; /// @dev End of Storage layout from StakedToken v1 /// @dev To see the voting mappings, go to GovernancePowerWithSnapshot.sol mapping(address => address) internal _votingDelegates; mapping(address => mapping(uint256 => Snapshot)) internal _propositionPowerSnapshots; mapping(address => uint256) internal _propositionPowerSnapshotsCounts; mapping(address => address) internal _propositionPowerDelegates; bytes32 public DOMAIN_SEPARATOR; bytes public constant EIP712_REVISION = bytes('1'); bytes32 internal constant EIP712_DOMAIN = keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'); 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; event Staked(address indexed from, address indexed onBehalfOf, uint256 amount); event Redeem(address indexed from, address indexed to, uint256 amount); event RewardsAccrued(address user, uint256 amount); event RewardsClaimed(address indexed from, address indexed to, uint256 amount); event Cooldown(address indexed user); constructor( IERC20 stakedToken, IERC20 rewardToken, uint256 cooldownSeconds, uint256 unstakeWindow, address rewardsVault, address emissionManager, uint128 distributionDuration, string memory name, string memory symbol, uint8 decimals, address governance ) public ERC20(name, symbol) AaveDistributionManager(emissionManager, distributionDuration) { require(address(stakedToken) != address(0), "STAKED_TOKEN_ADDRESS_CANNOT_BE_ZERO"); require(address(rewardToken) != address(0), "REWARD_TOKEN_ADDRESS_CANNOT_BE_ZERO"); require(rewardsVault != address(0), "REWARD_VAULT_ADDRESS_CANNOT_BE_ZERO"); STAKED_TOKEN = stakedToken; REWARD_TOKEN = rewardToken; COOLDOWN_SECONDS = cooldownSeconds; UNSTAKE_WINDOW = unstakeWindow; REWARDS_VAULT = rewardsVault; _aaveGovernance = ITransferHook(governance); ERC20._setupDecimals(decimals); } /** * @dev Called by the proxy contract **/ function initialize( string calldata name, string calldata symbol, uint8 decimals, address _trustedForwarder ) external { require(_trustedForwarder != address(0), "TrustForwarder address can't be 0"); initializeTrustedForwarder(_trustedForwarder); __ReentrancyGuard_init(); uint256 chainId; //solium-disable-next-line assembly { chainId := chainid() } DOMAIN_SEPARATOR = keccak256( abi.encode( EIP712_DOMAIN, keccak256(bytes(super.name())), keccak256(EIP712_REVISION), chainId, address(this) ) ); if (REVISION == 1) { _name = name; _symbol = symbol; _setupDecimals(decimals); } } function _msgSender() internal view override(ERC2771Context, Context) returns (address payable sender) { return ERC2771Context._msgSender(); } function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { return ERC2771Context._msgData(); } function stake(address onBehalfOf, uint256 amount) external override { require(amount != 0, 'INVALID_ZERO_AMOUNT'); uint256 balanceOfUser = balanceOf(onBehalfOf); uint256 accruedRewards = _updateUserAssetInternal(onBehalfOf, address(this), balanceOfUser, totalSupply()); if (accruedRewards != 0) { emit RewardsAccrued(onBehalfOf, accruedRewards); stakerRewardsToClaim[onBehalfOf] = stakerRewardsToClaim[onBehalfOf].add(accruedRewards); } stakersCooldowns[onBehalfOf] = getNextCooldownTimestamp(0, amount, onBehalfOf, balanceOfUser); _mint(onBehalfOf, amount); IERC20(STAKED_TOKEN).safeTransferFrom(_msgSender(), address(this), amount); emit Staked(_msgSender(), onBehalfOf, amount); } /** * @dev Redeems staked tokens, and stop earning rewards * @param to Address to redeem to * @param amount Amount to redeem **/ function redeem(address to, uint256 amount) external override nonReentrant { require(amount != 0, 'INVALID_ZERO_AMOUNT'); //solium-disable-next-line uint256 cooldownStartTimestamp = stakersCooldowns[_msgSender()]; require( block.timestamp > cooldownStartTimestamp.add(COOLDOWN_SECONDS), 'INSUFFICIENT_COOLDOWN' ); require( block.timestamp.sub(cooldownStartTimestamp.add(COOLDOWN_SECONDS)) <= UNSTAKE_WINDOW, 'UNSTAKE_WINDOW_FINISHED' ); uint256 balanceOfMessageSender = balanceOf(_msgSender()); uint256 amountToRedeem = (amount > balanceOfMessageSender) ? balanceOfMessageSender : amount; _updateCurrentUnclaimedRewards(_msgSender(), balanceOfMessageSender, true); _burn(_msgSender(), amountToRedeem); if (balanceOfMessageSender.sub(amountToRedeem) == 0) { stakersCooldowns[_msgSender()] = 0; } IERC20(STAKED_TOKEN).safeTransfer(to, amountToRedeem); emit Redeem(_msgSender(), to, amountToRedeem); } /** * @dev Activates the cooldown period to unstake * - It can't be called if the user is not staking **/ function cooldown() external override { require(balanceOf(_msgSender()) != 0, 'INVALID_BALANCE_ON_COOLDOWN'); //solium-disable-next-line stakersCooldowns[_msgSender()] = block.timestamp; emit Cooldown(_msgSender()); } /** * @dev Claims an `amount` of `REWARD_TOKEN` to the address `to` * @param to Address to stake for * @param amount Amount to stake **/ function claimRewards(address to, uint256 amount) external override nonReentrant { uint256 newTotalRewards = _updateCurrentUnclaimedRewards(_msgSender(), balanceOf(_msgSender()), false); uint256 amountToClaim = (amount == type(uint256).max) ? newTotalRewards : amount; stakerRewardsToClaim[_msgSender()] = newTotalRewards.sub(amountToClaim, 'INVALID_AMOUNT'); REWARD_TOKEN.safeTransferFrom(REWARDS_VAULT, to, amountToClaim); emit RewardsClaimed(_msgSender(), to, amountToClaim); } /** * @dev Internal ERC20 _transfer of the tokenized staked tokens * @param from Address to transfer from * @param to Address to transfer to * @param amount Amount to transfer **/ 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); uint256 previousSenderCooldown = stakersCooldowns[from]; stakersCooldowns[to] = getNextCooldownTimestamp( previousSenderCooldown, amount, to, balanceOfTo ); // if cooldown was set and whole balance of sender was transferred - clear cooldown if (balanceOfFrom == amount && previousSenderCooldown != 0) { stakersCooldowns[from] = 0; } } super._transfer(from, to, amount); } /** * @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].add(accruedRewards); if (accruedRewards != 0) { if (updateStorage) { stakerRewardsToClaim[user] = unclaimedRewards; } emit RewardsAccrued(user, accruedRewards); } return unclaimedRewards; } /** * @dev Calculates the how is gonna be a new cooldown timestamp depending on the sender/receiver situation * - If the timestamp of the sender is "better" or the timestamp of the recipient is 0, we take the one of the recipient * - Weighted average of from/to cooldown timestamps if: * # The sender doesn't have the cooldown activated (timestamp 0). * # The sender timestamp is expired * # The sender has a "worse" timestamp * - If the receiver's cooldown timestamp expired (too old), the next is 0 * @param fromCooldownTimestamp Cooldown timestamp of the sender * @param amountToReceive Amount * @param toAddress Address of the recipient * @param toBalance Current balance of the receiver * @return The new cooldown timestamp **/ function getNextCooldownTimestamp( uint256 fromCooldownTimestamp, uint256 amountToReceive, address toAddress, uint256 toBalance ) public view returns (uint256) { uint256 toCooldownTimestamp = stakersCooldowns[toAddress]; if (toCooldownTimestamp == 0) { return 0; } uint256 minimalValidCooldownTimestamp = block.timestamp.sub(COOLDOWN_SECONDS).sub(UNSTAKE_WINDOW); if (minimalValidCooldownTimestamp > toCooldownTimestamp) { toCooldownTimestamp = 0; } else { uint256 fromCooldownTimestamp = (minimalValidCooldownTimestamp > fromCooldownTimestamp) ? block.timestamp : fromCooldownTimestamp; if (fromCooldownTimestamp < toCooldownTimestamp) { return toCooldownTimestamp; } else { toCooldownTimestamp = ( amountToReceive.mul(fromCooldownTimestamp).add(toBalance.mul(toCooldownTimestamp)) ) .div(amountToReceive.add(toBalance)); } } return toCooldownTimestamp; } /** * @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) { DistributionTypes.UserStakeInput[] memory userStakeInputs = new DistributionTypes.UserStakeInput[](1); userStakeInputs[0] = DistributionTypes.UserStakeInput({ underlyingAsset: address(this), stakedByUser: balanceOf(staker), totalStaked: totalSupply() }); return stakerRewardsToClaim[staker].add(_getUnclaimedRewards(staker, userStakeInputs)); } /** * @dev returns the revision of the implementation contract * @return The revision */ function getRevision() internal pure override returns (uint256) { return REVISION; } /** * @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 { require(owner != address(0), 'INVALID_OWNER'); //solium-disable-next-line require(block.timestamp <= deadline, 'INVALID_EXPIRATION'); uint256 currentValidNonce = _nonces[owner]; bytes32 digest = keccak256( abi.encodePacked( '\x19\x01', DOMAIN_SEPARATOR, keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline)) ) ); require(owner == ecrecover(digest, v, r, s), 'INVALID_SIGNATURE'); _nonces[owner] = currentValidNonce.add(1); _approve(owner, spender, value); } /** * @dev Writes a snapshot before any operation involving transfer of value: _transfer, _mint and _burn * - On _transfer, it writes snapshots for both "from" and "to" * - On _mint, only for _to * - On _burn, only for _from * @param from the from address * @param to the to address * @param amount the amount to transfer */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal override { address votingFromDelegatee = _votingDelegates[from]; address votingToDelegatee = _votingDelegates[to]; if (votingFromDelegatee == address(0)) { votingFromDelegatee = from; } if (votingToDelegatee == address(0)) { votingToDelegatee = to; } _moveDelegatesByType( votingFromDelegatee, votingToDelegatee, amount, DelegationType.VOTING_POWER ); address propPowerFromDelegatee = _propositionPowerDelegates[from]; address propPowerToDelegatee = _propositionPowerDelegates[to]; if (propPowerFromDelegatee == address(0)) { propPowerFromDelegatee = from; } if (propPowerToDelegatee == address(0)) { propPowerToDelegatee = to; } _moveDelegatesByType( propPowerFromDelegatee, propPowerToDelegatee, amount, DelegationType.PROPOSITION_POWER ); // caching the aave governance address to avoid multiple state loads ITransferHook aaveGovernance = _aaveGovernance; if (aaveGovernance != ITransferHook(0)) { aaveGovernance.onTransfer(from, to, amount); } } function _getDelegationDataByType(DelegationType delegationType) internal view override returns ( mapping(address => mapping(uint256 => Snapshot)) storage, //snapshots mapping(address => uint256) storage, //snapshots count mapping(address => address) storage //delegatees list ) { if (delegationType == DelegationType.VOTING_POWER) { return (_votingSnapshots, _votingSnapshotsCounts, _votingDelegates); } else { return ( _propositionPowerSnapshots, _propositionPowerSnapshotsCounts, _propositionPowerDelegates ); } } /** * @dev Delegates power from signatory to `delegatee` * @param delegatee The address to delegate votes to * @param delegationType the type of delegation (VOTING_POWER, PROPOSITION_POWER) * @param nonce The contract state required to match the signature * @param expiry The time at which to expire the signature * @param v The recovery byte of the signature * @param r Half of the ECDSA signature pair * @param s Half of the ECDSA signature pair */ function delegateByTypeBySig( address delegatee, DelegationType delegationType, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) external { bytes32 structHash = keccak256( abi.encode(DELEGATE_BY_TYPE_TYPEHASH, delegatee, uint256(delegationType), nonce, expiry) ); bytes32 digest = keccak256(abi.encodePacked('\x19\x01', DOMAIN_SEPARATOR, structHash)); address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), 'INVALID_SIGNATURE'); require(nonce == _nonces[signatory]++, 'INVALID_NONCE'); require(block.timestamp <= expiry, 'INVALID_EXPIRATION'); _delegateByType(signatory, delegatee, delegationType); } /** * @dev Delegates power from signatory to `delegatee` * @param delegatee The address to delegate votes to * @param nonce The contract state required to match the signature * @param expiry The time at which to expire the signature * @param v The recovery byte of the signature * @param r Half of the ECDSA signature pair * @param s Half of the ECDSA signature pair */ function delegateBySig( address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) public { bytes32 structHash = keccak256(abi.encode(DELEGATE_TYPEHASH, delegatee, nonce, expiry)); bytes32 digest = keccak256(abi.encodePacked('\x19\x01', DOMAIN_SEPARATOR, structHash)); address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), 'INVALID_SIGNATURE'); require(nonce == _nonces[signatory]++, 'INVALID_NONCE'); require(block.timestamp <= expiry, 'INVALID_EXPIRATION'); _delegateByType(signatory, delegatee, DelegationType.VOTING_POWER); _delegateByType(signatory, delegatee, DelegationType.PROPOSITION_POWER); } }
//SPDX-License-Identifier: MIT pragma solidity 0.7.5; import "./Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal reentrancy_initializer { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal reentrancy_initializer { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // File contracts/stake/AaveDistributionManager.sol pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import "./DistributionTypes.sol"; import "./lib/SafeMath.sol"; import "./interface/IAaveDistributionManager.sol"; /** * @title AaveDistributionManager * @notice Accounting contract to manage multiple staking distributions * @author Aave **/ contract AaveDistributionManager is IAaveDistributionManager { using SafeMath for uint256; struct AssetData { uint128 emissionPerSecond; uint128 lastUpdateTimestamp; uint256 index; mapping(address => uint256) users; } uint256 public immutable DISTRIBUTION_END; address public immutable EMISSION_MANAGER; 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) public { require(emissionManager!=address(0), "EMMISSION_MANAGER_CANNOT_BE_ZERO"); DISTRIBUTION_END = block.timestamp.add(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[] calldata assetsConfigInput) external override { require(msg.sender == EMISSION_MANAGER, 'ONLY_EMISSION_MANAGER'); 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.add( _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.add( _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.mul(reserveIndex.sub(userIndex)).div(1e18); } /** * @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.sub(lastUpdateTimestamp); return emissionPerSecond.mul(timeDelta).mul(1e18).div(totalBalance).add( 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) external view returns (uint256) { return assets[asset].users[user]; } }
// SPDX-License-Identifier: MIT // File contracts/interfaces/IERC20.sol pragma solidity 0.7.5; /** * @dev Interface of the ERC20 standard as defined in the EIP. * From https://github.com/OpenZeppelin/openzeppelin-contracts */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // File @aave/aave-token/contracts/interfaces/[email protected] pragma solidity 0.7.5; interface IGovernancePowerDelegationToken { enum DelegationType {VOTING_POWER, PROPOSITION_POWER} /** * @dev emitted when a user delegates to another * @param delegator the delegator * @param delegatee the delegatee * @param delegationType the type of delegation (VOTING_POWER, PROPOSITION_POWER) **/ event DelegateChanged( address indexed delegator, address indexed delegatee, DelegationType delegationType ); /** * @dev emitted when an action changes the delegated power of a user * @param user the user which delegated power has changed * @param amount the amount of delegated power for the user * @param delegationType the type of delegation (VOTING_POWER, PROPOSITION_POWER) **/ event DelegatedPowerChanged(address indexed user, uint256 amount, DelegationType delegationType); /** * @dev delegates the specific power to a delegatee * @param delegatee the user which delegated power has changed * @param delegationType the type of delegation (VOTING_POWER, PROPOSITION_POWER) **/ function delegateByType(address delegatee, DelegationType delegationType) external virtual; /** * @dev delegates all the powers to a specific user * @param delegatee the user to which the power will be delegated **/ function delegate(address delegatee) external virtual; /** * @dev returns the delegatee of an user * @param delegator the address of the delegator **/ function getDelegateeByType(address delegator, DelegationType delegationType) external view virtual returns (address); /** * @dev returns the current delegated power of a user. The current power is the * power delegated at the time of the last snapshot * @param user the user **/ function getPowerCurrent(address user, DelegationType delegationType) external view virtual returns (uint256); /** * @dev returns the delegated power of a user at a certain block * @param user the user **/ function getPowerAtBlock( address user, uint256 blockNumber, DelegationType delegationType ) external view virtual returns (uint256); /** * @dev returns the total supply at a certain block number **/ function totalSupplyAt(uint256 blockNumber) external view virtual returns (uint256); }
// SPDX-License-Identifier: MIT // File contracts/interfaces/ITransferHook.sol pragma solidity 0.7.5; interface ITransferHook { function onTransfer( address from, address to, uint256 amount ) external; }
// SPDX-License-Identifier: MIT // File contracts/interfaces/IStakedAave.sol pragma solidity 0.7.5; interface IStakedAave { function stake(address to, uint256 amount) external; function redeem(address to, uint256 amount) external; function cooldown() external; function claimRewards(address to, uint256 amount) external; }
// SPDX-License-Identifier: MIT // File contracts/lib/Context.sol pragma solidity 0.7.5; /** * @dev From https://github.com/OpenZeppelin/openzeppelin-contracts * 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 GSN 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 payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data[:msg.data.length - 20]; } }
// SPDX-License-Identifier: MIT // File contracts/lib/GovernancePowerWithSnapshot.sol /** * @title ERC20WithSnapshot * @notice ERC20 including snapshots of balances on transfer-related actions * @author Aave **/ pragma solidity 0.7.5; import "./GovernancePowerDelegationERC20.sol"; import "../interface/ITransferHook.sol"; abstract contract GovernancePowerWithSnapshot is GovernancePowerDelegationERC20 { using SafeMath for uint256; /** * @dev The following storage layout points to the prior StakedToken.sol implementation: * _snapshots => _votingSnapshots * _snapshotsCounts => _votingSnapshotsCounts * _aaveGovernance => _aaveGovernance */ mapping(address => mapping(uint256 => Snapshot)) public _votingSnapshots; mapping(address => uint256) public _votingSnapshotsCounts; /// @dev reference to the Aave governance contract to call (if initialized) on _beforeTokenTransfer /// !!! IMPORTANT The Aave governance is considered a trustable contract, being its responsibility /// to control all potential reentrancies by calling back the this contract ITransferHook public _aaveGovernance; function _setAaveGovernance(ITransferHook aaveGovernance) internal virtual { _aaveGovernance = aaveGovernance; } }
// SPDX-License-Identifier: MIT // File @aave/aave-token/contracts/token/base/[email protected] /** * @notice implementation of the AAVE token contract * @author Aave */ pragma solidity 0.7.5; import "./ERC20.sol"; import "../interface/IGovernancePowerDelegationToken.sol"; abstract contract GovernancePowerDelegationERC20 is ERC20, IGovernancePowerDelegationToken { using SafeMath for uint256; /// @notice The EIP-712 typehash for the delegation struct used by the contract bytes32 public constant DELEGATE_BY_TYPE_TYPEHASH = keccak256('DelegateByType(address delegatee,uint256 type,uint256 nonce,uint256 expiry)'); bytes32 public constant DELEGATE_TYPEHASH = keccak256('Delegate(address delegatee,uint256 nonce,uint256 expiry)'); /// @dev snapshot of a value on a specific block, used for votes struct Snapshot { uint128 blockNumber; uint128 value; } /** * @dev delegates one specific power to a delegatee * @param delegatee the user which delegated power has changed * @param delegationType the type of delegation (VOTING_POWER, PROPOSITION_POWER) **/ function delegateByType(address delegatee, DelegationType delegationType) external override { _delegateByType(msg.sender, delegatee, delegationType); } /** * @dev delegates all the powers to a specific user * @param delegatee the user to which the power will be delegated **/ function delegate(address delegatee) external override { _delegateByType(msg.sender, delegatee, DelegationType.VOTING_POWER); _delegateByType(msg.sender, delegatee, DelegationType.PROPOSITION_POWER); } /** * @dev returns the delegatee of an user * @param delegator the address of the delegator **/ function getDelegateeByType(address delegator, DelegationType delegationType) external view override returns (address) { (, , mapping(address => address) storage delegates) = _getDelegationDataByType(delegationType); return _getDelegatee(delegator, delegates); } /** * @dev returns the current delegated power of a user. The current power is the * power delegated at the time of the last snapshot * @param user the user **/ function getPowerCurrent(address user, DelegationType delegationType) external view override returns (uint256) { ( mapping(address => mapping(uint256 => Snapshot)) storage snapshots, mapping(address => uint256) storage snapshotsCounts, ) = _getDelegationDataByType(delegationType); return _searchByBlockNumber(snapshots, snapshotsCounts, user, block.number); } /** * @dev returns the delegated power of a user at a certain block * @param user the user **/ function getPowerAtBlock( address user, uint256 blockNumber, DelegationType delegationType ) external view override returns (uint256) { ( mapping(address => mapping(uint256 => Snapshot)) storage snapshots, mapping(address => uint256) storage snapshotsCounts, ) = _getDelegationDataByType(delegationType); return _searchByBlockNumber(snapshots, snapshotsCounts, user, blockNumber); } /** * @dev returns the total supply at a certain block number * used by the voting strategy contracts to calculate the total votes needed for threshold/quorum * In this initial implementation with no AAVE minting, simply returns the current supply * A snapshots mapping will need to be added in case a mint function is added to the AAVE token in the future **/ function totalSupplyAt(uint256 blockNumber) external view override returns (uint256) { return super.totalSupply(); } /** * @dev delegates the specific power to a delegatee * @param delegatee the user which delegated power has changed * @param delegationType the type of delegation (VOTING_POWER, PROPOSITION_POWER) **/ function _delegateByType( address delegator, address delegatee, DelegationType delegationType ) internal { require(delegatee != address(0), 'INVALID_DELEGATEE'); (, , mapping(address => address) storage delegates) = _getDelegationDataByType(delegationType); uint256 delegatorBalance = balanceOf(delegator); address previousDelegatee = _getDelegatee(delegator, delegates); delegates[delegator] = delegatee; _moveDelegatesByType(previousDelegatee, delegatee, delegatorBalance, delegationType); emit DelegateChanged(delegator, delegatee, delegationType); } /** * @dev moves delegated power from one user to another * @param from the user from which delegated power is moved * @param to the user that will receive the delegated power * @param amount the amount of delegated power to be moved * @param delegationType the type of delegation (VOTING_POWER, PROPOSITION_POWER) **/ function _moveDelegatesByType( address from, address to, uint256 amount, DelegationType delegationType ) internal { if (from == to) { return; } ( mapping(address => mapping(uint256 => Snapshot)) storage snapshots, mapping(address => uint256) storage snapshotsCounts, ) = _getDelegationDataByType(delegationType); if (from != address(0)) { uint256 previous = 0; uint256 fromSnapshotsCount = snapshotsCounts[from]; if (fromSnapshotsCount != 0) { previous = snapshots[from][fromSnapshotsCount - 1].value; } else { previous = balanceOf(from); } _writeSnapshot( snapshots, snapshotsCounts, from, uint128(previous), uint128(previous.sub(amount)) ); emit DelegatedPowerChanged(from, previous.sub(amount), delegationType); } if (to != address(0)) { uint256 previous = 0; uint256 toSnapshotsCount = snapshotsCounts[to]; if (toSnapshotsCount != 0) { previous = snapshots[to][toSnapshotsCount - 1].value; } else { previous = balanceOf(to); } _writeSnapshot( snapshots, snapshotsCounts, to, uint128(previous), uint128(previous.add(amount)) ); emit DelegatedPowerChanged(to, previous.add(amount), delegationType); } } /** * @dev searches a snapshot by block number. Uses binary search. * @param snapshots the snapshots mapping * @param snapshotsCounts the number of snapshots * @param user the user for which the snapshot is being searched * @param blockNumber the block number being searched **/ function _searchByBlockNumber( mapping(address => mapping(uint256 => Snapshot)) storage snapshots, mapping(address => uint256) storage snapshotsCounts, address user, uint256 blockNumber ) internal view returns (uint256) { require(blockNumber <= block.number, 'INVALID_BLOCK_NUMBER'); uint256 snapshotsCount = snapshotsCounts[user]; if (snapshotsCount == 0) { return balanceOf(user); } // First check most recent balance if (snapshots[user][snapshotsCount - 1].blockNumber <= blockNumber) { return snapshots[user][snapshotsCount - 1].value; } // Next check implicit zero balance if (snapshots[user][0].blockNumber > blockNumber) { return 0; } uint256 lower = 0; uint256 upper = snapshotsCount - 1; while (upper > lower) { uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow Snapshot memory snapshot = snapshots[user][center]; if (snapshot.blockNumber == blockNumber) { return snapshot.value; } else if (snapshot.blockNumber < blockNumber) { lower = center; } else { upper = center - 1; } } return snapshots[user][lower].value; } /** * @dev returns the delegation data (snapshot, snapshotsCount, list of delegates) by delegation type * NOTE: Ideal implementation would have mapped this in a struct by delegation type. Unfortunately, * the AAVE token and StakeToken already include a mapping for the snapshots, so we require contracts * who inherit from this to provide access to the delegation data by overriding this method. * @param delegationType the type of delegation **/ function _getDelegationDataByType(DelegationType delegationType) internal view virtual returns ( mapping(address => mapping(uint256 => Snapshot)) storage, //snapshots mapping(address => uint256) storage, //snapshots count mapping(address => address) storage //delegatees list ); /** * @dev Writes a snapshot for an owner of tokens * @param owner The owner of the tokens * @param oldValue The value before the operation that is gonna be executed after the snapshot * @param newValue The value after the operation */ function _writeSnapshot( mapping(address => mapping(uint256 => Snapshot)) storage snapshots, mapping(address => uint256) storage snapshotsCounts, address owner, uint128 oldValue, uint128 newValue ) internal { uint128 currentBlock = uint128(block.number); uint256 ownerSnapshotsCount = snapshotsCounts[owner]; mapping(uint256 => Snapshot) storage snapshotsOwner = snapshots[owner]; // Doing multiple operations in the same block if ( ownerSnapshotsCount != 0 && snapshotsOwner[ownerSnapshotsCount - 1].blockNumber == currentBlock ) { snapshotsOwner[ownerSnapshotsCount - 1].value = newValue; } else { snapshotsOwner[ownerSnapshotsCount] = Snapshot(currentBlock, newValue); snapshotsCounts[owner] = ownerSnapshotsCount + 1; } } /** * @dev returns the user delegatee. If a user never performed any delegation, * his delegated address will be 0x0. In that case we simply return the user itself * @param delegator the address of the user for which return the delegatee * @param delegates the array of delegates for a particular type of delegation **/ function _getDelegatee(address delegator, mapping(address => address) storage delegates) internal view returns (address) { address previousDelegatee = delegates[delegator]; if (previousDelegatee == address(0)) { return delegator; } return previousDelegatee; } }
// SPDX-License-Identifier: MIT // File contracts/utils/VersionedInitializable.sol pragma solidity 0.7.5; /** * @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: MIT // OpenZeppelin Contracts v4.4.1 (metatx/ERC2771Context.sol) pragma solidity 0.7.5; import "./Context.sol"; import "./VersionedInitializable.sol"; /** * @dev Context variant with ERC2771 support. */ abstract contract ERC2771Context is Context, VersionedInitializable { address internal _trustedForwarder; function initializeTrustedForwarder( address trustedForwarder ) public initializer { _trustedForwarder = trustedForwarder; } function isTrustedForwarder(address forwarder) public view virtual returns (bool) { return forwarder == _trustedForwarder; } function _msgSender() internal view virtual override returns (address payable sender) { if (isTrustedForwarder(msg.sender)) { // The assembly code is more direct than the Solidity version using `abi.decode`. assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) } } else { return super._msgSender(); } } function _msgData() internal view virtual override returns (bytes calldata) { if (isTrustedForwarder(msg.sender)) { return msg.data[:msg.data.length - 20]; } else { return super._msgData(); } } }
// SPDX-License-Identifier: MIT // File contracts/lib/SafeERC20.sol pragma solidity 0.7.5; import "./SafeMath.sol"; import "./Address.sol"; import "../interface/IERC20.sol"; /** * @title SafeERC20 * @dev From https://github.com/OpenZeppelin/openzeppelin-contracts * 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 SafeMath for uint256; using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove( IERC20 token, address spender, uint256 value ) internal { 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 callOptionalReturn(IERC20 token, bytes memory data) private { require(address(token).isContract(), 'SafeERC20: call to non-contract'); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, 'SafeERC20: low-level call failed'); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), 'SafeERC20: ERC20 operation did not succeed'); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.7.5; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier reentrancy_initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.7.5; // File contracts/lib/DistributionTypes.sol library DistributionTypes { struct AssetConfigInput { uint128 emissionPerSecond; uint256 totalStaked; address underlyingAsset; } struct UserStakeInput { address underlyingAsset; uint256 stakedByUser; uint256 totalStaked; } }
// SPDX-License-Identifier: MIT pragma solidity 0.7.5; // File contracts/lib/SafeMath.sol /** * @dev From https://github.com/OpenZeppelin/openzeppelin-contracts * Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, 'SafeMath: addition overflow'); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, 'SafeMath: subtraction overflow'); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, 'SafeMath: multiplication overflow'); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, 'SafeMath: division by zero'); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, 'SafeMath: modulo by zero'); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT // File contracts/interfaces/IAaveDistributionManager.sol pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import "../DistributionTypes.sol"; interface IAaveDistributionManager { function configureAssets(DistributionTypes.AssetConfigInput[] calldata assetsConfigInput) external; }
// SPDX-License-Identifier: MIT // File @aave/aave-token/contracts/open-zeppelin/[email protected] pragma solidity 0.7.5; import "./Context.sol"; import "../interface/IERC20.sol"; import "../lib/SafeMath.sol"; import "../lib/Address.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; using Address for address; mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string internal _name; string internal _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor(string memory name, string memory symbol) public { _name = name; _symbol = symbol; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve( sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, 'ERC20: transfer amount exceeds allowance') ); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve( _msgSender(), spender, _allowances[_msgSender()][spender].sub( subtractedValue, 'ERC20: decreased allowance below zero' ) ); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), 'ERC20: transfer from the zero address'); require(recipient != address(0), 'ERC20: transfer to the zero address'); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, 'ERC20: transfer amount exceeds balance'); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @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 * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), 'ERC20: mint to the zero address'); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, 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, uint256 amount) internal virtual { require(account != address(0), 'ERC20: burn from the zero address'); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, 'ERC20: burn amount exceeds balance'); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // File contracts/lib/Address.sol pragma solidity 0.7.5; /** * @dev Collection of functions related to the address type * From https://github.com/OpenZeppelin/openzeppelin-contracts */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, 'Address: insufficient balance'); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{value: amount}(''); require(success, 'Address: unable to send value, recipient may have reverted'); } }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IERC20","name":"stakedToken","type":"address"},{"internalType":"contract IERC20","name":"rewardToken","type":"address"},{"internalType":"uint256","name":"cooldownSeconds","type":"uint256"},{"internalType":"uint256","name":"unstakeWindow","type":"uint256"},{"internalType":"address","name":"rewardsVault","type":"address"},{"internalType":"address","name":"emissionManager","type":"address"},{"internalType":"uint128","name":"distributionDuration","type":"uint128"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"address","name":"governance","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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"}],"name":"Cooldown","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.DelegationType","name":"delegationType","type":"uint8"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"enum IGovernancePowerDelegationToken.DelegationType","name":"delegationType","type":"uint8"}],"name":"DelegatedPowerChanged","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":"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":"from","type":"address"},{"indexed":true,"internalType":"address","name":"onBehalfOf","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","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":"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":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REVISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"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":[],"name":"_aaveGovernance","outputs":[{"internalType":"contract ITransferHook","name":"","type":"address"}],"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":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"_votingSnapshots","outputs":[{"internalType":"uint128","name":"blockNumber","type":"uint128"},{"internalType":"uint128","name":"value","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_votingSnapshotsCounts","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":[{"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":[],"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":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"enum IGovernancePowerDelegationToken.DelegationType","name":"delegationType","type":"uint8"}],"name":"delegateByType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"enum IGovernancePowerDelegationToken.DelegationType","name":"delegationType","type":"uint8"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateByTypeBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"enum IGovernancePowerDelegationToken.DelegationType","name":"delegationType","type":"uint8"}],"name":"getDelegateeByType","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromCooldownTimestamp","type":"uint256"},{"internalType":"uint256","name":"amountToReceive","type":"uint256"},{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"toBalance","type":"uint256"}],"name":"getNextCooldownTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"enum IGovernancePowerDelegationToken.DelegationType","name":"delegationType","type":"uint8"}],"name":"getPowerAtBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"enum IGovernancePowerDelegationToken.DelegationType","name":"delegationType","type":"uint8"}],"name":"getPowerCurrent","outputs":[{"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":[{"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":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"address","name":"_trustedForwarder","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"trustedForwarder","type":"address"}],"name":"initializeTrustedForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"onBehalfOf","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","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":"uint256","name":"","type":"uint256"}],"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":"uint256","name":"blockNumber","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61016060405260006009553480156200001757600080fd5b506040516200449d3803806200449d8339810160408190526200003a91620003e2565b85856001600160801b0316858581600390805190602001906200005f9291906200024c565b508051620000759060049060208401906200024c565b50506005805460ff19166012179055506001600160a01b038216620000b75760405162461bcd60e51b8152600401620000ae90620005b2565b60405180910390fd5b620000d18142620001d460201b62001bb91790919060201c565b6080525060601b6001600160601b03191660a0526001600160a01b038b166200010e5760405162461bcd60e51b8152600401620000ae906200052c565b6001600160a01b038a16620001375760405162461bcd60e51b8152600401620000ae906200056f565b6001600160a01b038716620001605760405162461bcd60e51b8152600401620000ae90620004e9565b60608b811b6001600160601b031990811660c0528b821b811660e0526101008b90526101208a90529088901b1661014052600880546001600160a01b0319166001600160a01b038316179055620001c38262000236602090811b62001c1317901c565b5050505050505050505050620005e7565b6000828201838110156200022f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6005805460ff191660ff92909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620002845760008555620002cf565b82601f106200029f57805160ff1916838001178555620002cf565b82800160010185558215620002cf579182015b82811115620002cf578251825591602001919060010190620002b2565b50620002dd929150620002e1565b5090565b5b80821115620002dd5760008155600101620002e2565b80516001600160a01b03811681146200031057600080fd5b919050565b600082601f83011262000326578081fd5b81516001600160401b03808211156200033b57fe5b6040516020601f8401601f19168201810183811183821017156200035b57fe5b806040525081945083825286818588010111156200037857600080fd5b600092505b838310156200039c57858301810151828401820152918201916200037d565b83831115620003ae5760008185840101525b5050505092915050565b80516001600160801b03811681146200031057600080fd5b805160ff811681146200031057600080fd5b60008060008060008060008060008060006101608c8e03121562000404578687fd5b6200040f8c620002f8565b9a506200041f60208d01620002f8565b995060408c0151985060608c015197506200043d60808d01620002f8565b96506200044d60a08d01620002f8565b95506200045d60c08d01620003b8565b60e08d01519095506001600160401b0381111562000479578485fd5b620004878e828f0162000315565b6101008e015190955090506001600160401b03811115620004a6578384fd5b620004b48e828f0162000315565b935050620004c66101208d01620003d0565b9150620004d76101408d01620002f8565b90509295989b509295989b9093969950565b60208082526023908201527f5245574152445f5641554c545f414444524553535f43414e4e4f545f42455f5a60408201526245524f60e81b606082015260800190565b60208082526023908201527f5354414b45445f544f4b454e5f414444524553535f43414e4e4f545f42455f5a60408201526245524f60e81b606082015260800190565b60208082526023908201527f5245574152445f544f4b454e5f414444524553535f43414e4e4f545f42455f5a60408201526245524f60e81b606082015260800190565b6020808252818101527f454d4d495353494f4e5f4d414e414745525f43414e4e4f545f42455f5a45524f604082015260600190565b60805160a05160601c60c05160601c60e05160601c61010051610120516101405160601c613e156200068860003980610e195280610feb52508061081b5280610b1852806119765250806107d752806108435280610c54528061199b525080610ea85280610fc95250806109175280610abb528061121052508061129b5280611633525080610df55280612fea528061302652806130535250613e156000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c80638dbefee21161019d578063b9844d8d116100e9578063dc937e1c116100a2578063de7ea79d1161007c578063de7ea79d146105fc578063f11b81881461060f578063f1cc432a14610631578063f713d8a814610644576102f1565b8063dc937e1c146105ce578063dd62ed3e146105e1578063dde43cba146105f4576102f1565b8063b9844d8d14610572578063c2ffbb9114610585578063c3863ada14610598578063c3cda520146105a0578063cbcbb507146105b3578063d505accf146105bb576102f1565b80639a99b4f011610156578063aa9fbe0211610130578063aa9fbe0214610531578063adc9772e14610539578063b2a5dbfa1461054c578063b2f4201d1461055f576102f1565b80639a99b4f0146104f8578063a457c2d71461050b578063a9059cbb1461051e576102f1565b80638dbefee2146104b2578063919cd40f146104c5578063946776cd146104cd57806395d89b41146104d5578063981b24d0146104dd57806399248ea7146104f0576102f1565b80633644e5151161025c5780636f50458d1161021557806378160376116101ef578063781603761461047c578063787a08a6146104845780637bb73c971461048c5780637e90d7ef1461049f576102f1565b80636f50458d1461044e57806370a082311461046157806372b49d6314610474576102f1565b80633644e515146103e457806339509351146103ec57806341cbf54a146103ff578063572b6c05146104075780635b3cc0cf1461041a5780635c19a95c1461043b576102f1565b8063249aea9b116102ae578063249aea9b1461038457806330adf81f14610397578063312f6b831461039f578063313ce567146103b45780633373ee4c146103c9578063359c4a96146103dc576102f1565b806306fdde03146102f6578063091030c314610314578063095ea7b31461033457806318160ddd146103545780631e9a69501461035c57806323b872dd14610371575b600080fd5b6102fe610657565b60405161030b91906139a2565b60405180910390f35b61032761032236600461348c565b6106ee565b60405161030b91906138cb565b6103476103423660046135d6565b610700565b60405161030b91906138c0565b61032761071e565b61036f61036a3660046135d6565b610724565b005b61034761037f3660046134d8565b61099c565b61036f61039236600461348c565b610a24565b610327610a95565b6103a7610ab9565b60405161030b919061386f565b6103bc610add565b60405161030b9190613be6565b6103276103d73660046134a6565b610ae6565b610327610b16565b610327610b3a565b6103476103fa3660046135d6565b610b40565b610327610b8e565b61034761041536600461348c565b610bb2565b61042d6104283660046135d6565b610bc9565b60405161030b929190613ba8565b61036f61044936600461348c565b610bfa565b6103a761045c36600461357c565b610c15565b61032761046f36600461348c565b610c37565b610327610c52565b6102fe610c76565b61036f610c93565b61032761049a36600461348c565b610d20565b6103276104ad36600461348c565b610d32565b6103276104c036600461348c565b610d44565b610327610df3565b6103a7610e17565b6102fe610e3b565b6103276104eb3660046137b5565b610e9c565b6103a7610ea6565b61036f6105063660046135d6565b610eca565b6103476105193660046135d6565b61106e565b61034761052c3660046135d6565b6110d6565b6103276110ea565b61036f6105473660046135d6565b61110e565b61036f61055a366004613691565b611290565b61032761056d36600461357c565b611443565b61032761058036600461348c565b61146b565b6103276105933660046135ff565b61147d565b6103a76114a6565b61036f6105ae36600461363a565b6114b5565b6103a7611631565b61036f6105c9366004613513565b611655565b61036f6105dc36600461357c565b6117e2565b6103276105ef3660046134a6565b6117f1565b61032761181c565b61036f61060a366004613701565b611821565b61062261061d36600461348c565b611919565b60405161030b93929190613bc2565b61032761063f3660046137cd565b611947565b61036f6106523660046135a5565b611a3c565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106e35780601f106106b8576101008083540402835291602001916106e3565b820191906000526020600020905b8154815290600101906020018083116106c657829003601f168201915b505050505090505b90565b60716020526000908152604090205481565b600061071461070d611c29565b8484611c38565b5060015b92915050565b60025490565b6002603e54141561077c576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002603e55806107a75760405162461bcd60e51b815260040161079e906139b5565b60405180910390fd5b6000607160006107b5611c29565b6001600160a01b0316815260208101919091526040016000205490506107fb817f0000000000000000000000000000000000000000000000000000000000000000611bb9565b42116108195760405162461bcd60e51b815260040161079e90613a0d565b7f000000000000000000000000000000000000000000000000000000000000000061086e610867837f0000000000000000000000000000000000000000000000000000000000000000611bb9565b4290611d24565b111561088c5760405162461bcd60e51b815260040161079e90613ae5565b600061089961046f611c29565b905060008184116108aa57836108ac565b815b90506108c16108b9611c29565b836001611d66565b506108d36108cd611c29565b82611e0a565b6108dd8282611d24565b61090a576000607160006108ef611c29565b6001600160a01b031681526020810191909152604001600020555b61093e6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168683611f06565b846001600160a01b0316610950611c29565b6001600160a01b03167fd12200efa34901b99367694174c3b0d32c99585fdf37c7c26892136ddd0836d98360405161098891906138cb565b60405180910390a350506001603e55505050565b60006109a9848484611f58565b610a19846109b5611c29565b610a1485604051806060016040528060288152602001613cd1602891396001600160a01b038a166000908152600160205260408120906109f3611c29565b6001600160a01b031681526020810191909152604001600020549190612024565b611c38565b5060015b9392505050565b6000610a2e6120bb565b90506009548111610a705760405162461bcd60e51b815260040180806020018281038252602e815260200180613cf9602e913960400191505060405180910390fd5b600955603d80546001600160a01b0319166001600160a01b0392909216919091179055565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055460ff1690565b6001600160a01b038082166000908152603c60209081526040808320938616835260029093019052205492915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60765481565b6000610714610b4d611c29565b84610a148560016000610b5e611c29565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611bb9565b7f9a9a49b990ba9bb39f8048c490a40ab25c18f55d208d5fbcf958261a9b48716d81565b603d546001600160a01b038281169116145b919050565b60066020908152600092835260408084209091529082529020546001600160801b0380821691600160801b90041682565b610c06338260006120c0565b610c12338260016120c0565b50565b600080610c21836121d1565b92505050610c2f848261220b565b949350505050565b6001600160a01b031660009081526020819052604090205490565b7f000000000000000000000000000000000000000000000000000000000000000081565b604051806040016040528060018152602001603160f81b81525081565b610c9e61046f611c29565b610cba5760405162461bcd60e51b815260040161079e90613b5d565b4260716000610cc7611c29565b6001600160a01b03168152602081019190915260400160002055610ce9611c29565b6001600160a01b03167ff52f50426b32362d3e6bb8cb36b7074756b224622def6352a59eac7f66ebe6e860405160405180910390a2565b60076020526000908152604090205481565b60706020526000908152604090205481565b60408051600180825281830190925260009160609190816020015b610d6761332c565b815260200190600190039081610d5f5790505090506040518060600160405280306001600160a01b03168152602001610d9f85610c37565b8152602001610dac61071e565b81525081600081518110610dbc57fe5b6020026020010181905250610a1d610dd48483612236565b6001600160a01b03851660009081526070602052604090205490611bb9565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106e35780601f106106b8576101008083540402835291602001916106e3565b600061071861071e565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002603e541415610f22576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002603e556000610f46610f34611c29565b610f3f61046f611c29565b6000611d66565b905060006000198314610f595782610f5b565b815b9050610f98816040518060400160405280600e81526020016d1253959053125117d05353d5539560921b815250846120249092919063ffffffff16565b60706000610fa4611c29565b6001600160a01b039081168252602082019290925260400160002091909155611011907f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000008684612327565b836001600160a01b0316611023611c29565b6001600160a01b03167f9310ccfcb8de723f578a9e4282ea9f521f05ae40dc08f3068dfad528a65ee3c78360405161105b91906138cb565b60405180910390a350506001603e555050565b600061071461107b611c29565b84610a1485604051806060016040528060258152602001613dbb60259139600160006110a5611c29565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190612024565b60006107146110e3611c29565b8484611f58565b7f10d8d059343739efce7dad10d09f0806da52b252b3e6a7951920d2d6ec4102e581565b8061112b5760405162461bcd60e51b815260040161079e906139b5565b600061113683610c37565b9050600061114d84308461114861071e565b612381565b905080156111cb577f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a7684826040516111869291906138a7565b60405180910390a16001600160a01b0384166000908152607060205260409020546111b19082611bb9565b6001600160a01b0385166000908152607060205260409020555b6111d86000848685611947565b6001600160a01b0385166000908152607160205260409020556111fb8484612440565b611238611206611c29565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016903086612327565b836001600160a01b031661124a611c29565b6001600160a01b03167f5dac0c1b1112564a045ba943c9d50270893e8e826c49be8e7073adc713ab7bd78560405161128291906138cb565b60405180910390a350505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146112d85760405162461bcd60e51b815260040161079e90613a8f565b60005b8181101561143e576000603c60008585858181106112f557fe5b905060600201604001602081019061130d919061348c565b6001600160a01b03166001600160a01b03168152602001908152602001600020905061137284848481811061133e57fe5b9050606002016040016020810190611356919061348c565b8286868681811061136357fe5b90506060020160200135612530565b5083838381811061137f57fe5b611395926020606090920201908101915061378e565b81546001600160801b0319166001600160801b03919091161781558383838181106113bc57fe5b90506060020160400160208101906113d4919061348c565b6001600160a01b03167f87fa03892a0556cb6b8f97e6d533a150d4d55fcbf275fff5fa003fa636bcc7fa85858581811061140a57fe5b611420926020606090920201908101915061378e565b60405161142d9190613b94565b60405180910390a2506001016112db565b505050565b6000806000611451846121d1565b5091509150611462828287436125ed565b95945050505050565b60776020526000908152604090205481565b600080600061148b846121d1565b509150915061149c828288886125ed565b9695505050505050565b6008546001600160a01b031681565b60007f9a9a49b990ba9bb39f8048c490a40ab25c18f55d208d5fbcf958261a9b48716d8787876040516020016114ee9493929190613908565b60405160208183030381529060405280519060200120905060006076548260405160200161151d929190613854565b60405160208183030381529060405280519060200120905060006001828787876040516000815260200160405260405161155a9493929190613984565b6020604051602081039080840390855afa15801561157c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166115af5760405162461bcd60e51b815260040161079e906139e2565b6001600160a01b038116600090815260776020526040902080546001810190915588146115ee5760405162461bcd60e51b815260040161079e90613a68565b8642111561160e5760405162461bcd60e51b815260040161079e90613a3c565b61161a818a60006120c0565b611626818a60016120c0565b505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03871661167b5760405162461bcd60e51b815260040161079e90613abe565b8342111561169b5760405162461bcd60e51b815260040161079e90613a3c565b6001600160a01b03871660009081526077602090815260408083205460765491519093926116f5917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918d918d918d9189918e91016138d4565b6040516020818303038152906040528051906020012060405160200161171c929190613854565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117579493929190613984565b6020604051602081039080840390855afa158015611779573d6000803e3d6000fd5b505050602060405103516001600160a01b0316896001600160a01b0316146117b35760405162461bcd60e51b815260040161079e906139e2565b6117be826001611bb9565b6001600160a01b038a16600090815260776020526040902055611626898989611c38565b6117ed3383836120c0565b5050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600181565b6001600160a01b0381166118475760405162461bcd60e51b815260040161079e90613b1c565b61185081610a24565b611858612809565b467f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611882610657565b805160209182012060408051808201825260018152603160f81b90840152516118d293927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6918691309101613958565b60408051601f1981840301815291905280516020909101206076556118f960038888613356565b5061190660048686613356565b5061191083611c13565b50505050505050565b603c60205260009081526040902080546001909101546001600160801b0380831692600160801b9004169083565b6001600160a01b0382166000908152607160205260408120548061196f576000915050610c2f565b60006119c57f00000000000000000000000000000000000000000000000000000000000000006119bf427f0000000000000000000000000000000000000000000000000000000000000000611d24565b90611d24565b9050818111156119d85760009150611a32565b60008782116119e757876119e9565b425b9050828110156119fe57829350505050610c2f565b611a2e611a0b8887611bb9565b611a28611a1888876128bb565b611a228b866128bb565b90611bb9565b90612914565b9250505b5095945050505050565b60007f10d8d059343739efce7dad10d09f0806da52b252b3e6a7951920d2d6ec4102e588886001811115611a6c57fe5b8888604051602001611a8295949392919061392c565b604051602081830303815290604052805190602001209050600060765482604051602001611ab1929190613854565b604051602081830303815290604052805190602001209050600060018287878760405160008152602001604052604051611aee9493929190613984565b6020604051602081039080840390855afa158015611b10573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611b435760405162461bcd60e51b815260040161079e906139e2565b6001600160a01b03811660009081526077602052604090208054600181019091558814611b825760405162461bcd60e51b815260040161079e90613a68565b86421115611ba25760405162461bcd60e51b815260040161079e90613a3c565b611bad818b8b6120c0565b50505050505050505050565b600082820183811015610a1d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6005805460ff191660ff92909216919091179055565b6000611c33612956565b905090565b6001600160a01b038316611c7d5760405162461bcd60e51b8152600401808060200182810382526024815260200180613d6d6024913960400191505060405180910390fd5b6001600160a01b038216611cc25760405162461bcd60e51b8152600401808060200182810382526022815260200180613c3a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6000610a1d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612024565b600080611d7785308661114861071e565b6001600160a01b03861660009081526070602052604081205491925090611d9e9083611bb9565b90508115611462578315611dc8576001600160a01b03861660009081526070602052604090208190555b7f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a768683604051611df99291906138a7565b60405180910390a195945050505050565b6001600160a01b038216611e4f5760405162461bcd60e51b8152600401808060200182810382526021815260200180613d276021913960400191505060405180910390fd5b611e5b82600083612984565b611e9881604051806060016040528060228152602001613c18602291396001600160a01b0385166000908152602081905260409020549190612024565b6001600160a01b038316600090815260208190526040902055600254611ebe9082611d24565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261143e908490612aa1565b6000611f6384610c37565b9050611f7184826001611d66565b50826001600160a01b0316846001600160a01b031614612013576000611f9684610c37565b9050611fa484826001611d66565b506001600160a01b038516600090815260716020526040902054611fca81858785611947565b6001600160a01b0386166000908152607160205260409020558284148015611ff157508015155b15612010576001600160a01b0386166000908152607160205260408120555b50505b61201e848484612c59565b50505050565b600081848411156120b35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612078578181015183820152602001612060565b50505050905090810190601f1680156120a55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600190565b6001600160a01b03821661210f576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f44454c45474154454560781b604482015290519081900360640190fd5b600061211a826121d1565b92505050600061212985610c37565b90506000612137868461220b565b6001600160a01b03878116600090815260208690526040902080546001600160a01b031916918816919091179055905061217381868487612db4565b846001600160a01b0316866001600160a01b03167fe8d51c8e11bd570db1734c8ec775785330e77007feed45c43b608ef33ff914bd86604051808260018111156121b957fe5b815260200191505060405180910390a3505050505050565b60008080808460018111156121e257fe5b14156121f8575060069150600790506072612204565b50607391506074905060755b9193909250565b6001600160a01b0380831660009081526020839052604081205490911680610a1d5783915050610718565b600080805b835181101561231f576000603c600086848151811061225657fe5b602090810291909101810151516001600160a01b0316825281019190915260400160009081206001810154815488519294506122be926001600160801b0380831692600160801b900416908a90889081106122ad57fe5b602002602001015160400151612fc2565b905061231361230c8785815181106122d257fe5b602002602001015160200151838560020160008c6001600160a01b03166001600160a01b03168152602001908152602001600020546130bb565b8590611bb9565b9350505060010161223b565b509392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261201e908590612aa1565b6001600160a01b038084166000908152603c6020908152604080832093881683526002840190915281205490919082806123bc888588612530565b90508083146124345786156123d9576123d68782856130bb565b91505b6001600160a01b03808a1660008181526002870160205260409081902084905551918a16917fbb123b5c06d5408bbea3c4fef481578175cfb432e3b482c6186f02ed9086585b9061242b9085906138cb565b60405180910390a35b50979650505050505050565b6001600160a01b03821661249b576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6124a760008383612984565b6002546124b49082611bb9565b6002556001600160a01b0382166000908152602081905260409020546124da9082611bb9565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001820154825460009190600160801b90046001600160801b03164281141561255b57509050610a1d565b84546000906125769084906001600160801b03168488612fc2565b90508281146125ca57808660010181905550866001600160a01b03167f5777ca300dfe5bead41006fbce4389794dbc0ed8d6cccebfaf94630aa04184bc826040516125c191906138cb565b60405180910390a25b85546001600160801b03428116600160801b029116178655925050509392505050565b60004382111561263b576040805162461bcd60e51b815260206004820152601460248201527324a72b20a624a22fa12627a1a5afa72aa6a122a960611b604482015290519081900360640190fd5b6001600160a01b0383166000908152602085905260409020548061266a5761266284610c37565b915050610c2f565b6001600160a01b038416600090815260208781526040808320600019850184529091529020546001600160801b031683106126dd576001600160a01b038416600090815260208781526040808320600019909401835292905220546001600160801b03600160801b909104169050610c2f565b6001600160a01b0384166000908152602087815260408083208380529091529020546001600160801b0316831015612719576000915050610c2f565b600060001982015b818111156127cb5760028282030481036127396133e2565b506001600160a01b038716600090815260208a815260408083208484528252918290208251808401909352546001600160801b03808216808552600160801b90920416918301919091528714156127a357602001516001600160801b03169450610c2f9350505050565b80516001600160801b03168711156127bd578193506127c4565b6001820392505b5050612721565b506001600160a01b03851660009081526020888152604080832093835292905220546001600160801b03600160801b90910416915050949350505050565b603d54600160a81b900460ff168061282b5750603d54600160a01b900460ff16155b6128665760405162461bcd60e51b815260040180806020018281038252602e815260200180613c82602e913960400191505060405180910390fd5b603d54600160a81b900460ff1615801561289d57603d805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6128a56130dd565b8015610c1257603d805460ff60a81b1916905550565b6000826128ca57506000610718565b828202828482816128d757fe5b0414610a1d5760405162461bcd60e51b8152600401808060200182810382526021815260200180613cb06021913960400191505060405180910390fd5b6000610a1d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061318c565b600061296133610bb2565b15612975575060131936013560601c6106eb565b61297d6131f1565b90506106eb565b6001600160a01b038084166000908152607260205260408082205485841683529120549082169116816129b5578491505b6001600160a01b0381166129c65750825b6129d38282856000612db4565b6001600160a01b03808616600090815260756020526040808220548784168352912054908216911681612a04578691505b6001600160a01b038116612a155750845b612a228282876001612db4565b6008546001600160a01b03168015612a9757604051634a39314960e01b81526001600160a01b03821690634a39314990612a64908b908b908b90600401613883565b600060405180830381600087803b158015612a7e57600080fd5b505af1158015612a92573d6000803e3d6000fd5b505050505b5050505050505050565b612ab3826001600160a01b03166131f5565b612b04576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612b425780518252601f199092019160209182019101612b23565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612ba4576040519150601f19603f3d011682016040523d82523d6000602084013e612ba9565b606091505b509150915081612c00576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b80511561201e57808060200190516020811015612c1c57600080fd5b505161201e5760405162461bcd60e51b815260040180806020018281038252602a815260200180613d91602a913960400191505060405180910390fd5b6001600160a01b038316612c9e5760405162461bcd60e51b8152600401808060200182810382526025815260200180613d486025913960400191505060405180910390fd5b6001600160a01b038216612ce35760405162461bcd60e51b8152600401808060200182810382526023815260200180613bf56023913960400191505060405180910390fd5b612cee838383612984565b612d2b81604051806060016040528060268152602001613c5c602691396001600160a01b0386166000908152602081905260409020549190612024565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612d5a9082611bb9565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b826001600160a01b0316846001600160a01b03161415612dd35761201e565b600080612ddf836121d1565b5090925090506001600160a01b03861615612ed2576001600160a01b0386166000908152602082905260408120548015612e50576001600160a01b03881660009081526020858152604080832060001985018452909152902054600160801b90046001600160801b03169150612e5c565b612e5988610c37565b91505b612e7284848a85612e6d818c611d24565b61322e565b6001600160a01b0388167fa0a19463ee116110c9b282012d9b65cc5522dc38a9520340cbaf3142e550127f612ea78489611d24565b8760405180838152602001826001811115612ebe57fe5b81526020019250505060405180910390a250505b6001600160a01b03851615612fba576001600160a01b0385166000908152602082905260408120548015612f3d576001600160a01b03871660009081526020858152604080832060001985018452909152902054600160801b90046001600160801b03169150612f49565b612f4687610c37565b91505b612f5a84848985612e6d818c611bb9565b6001600160a01b0387167fa0a19463ee116110c9b282012d9b65cc5522dc38a9520340cbaf3142e550127f612f8f8489611bb9565b8760405180838152602001826001811115612fa657fe5b81526020019250505060405180910390a250505b505050505050565b6000831580612fcf575081155b80612fe2575042836001600160801b0316145b8061301657507f0000000000000000000000000000000000000000000000000000000000000000836001600160801b031610155b15613022575083610c2f565b60007f000000000000000000000000000000000000000000000000000000000000000042116130515742613073565b7f00000000000000000000000000000000000000000000000000000000000000005b9050600061308a826001600160801b038716611d24565b90506130b087611a2286611a28670de0b6b3a76400006130aa8c886128bb565b906128bb565b979650505050505050565b6000610c2f670de0b6b3a7640000611a286130d68686611d24565b87906128bb565b603d54600160a81b900460ff16806130ff5750603d54600160a01b900460ff16155b61313a5760405162461bcd60e51b815260040180806020018281038252602e815260200180613c82602e913960400191505060405180910390fd5b603d54600160a81b900460ff1615801561317157603d805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001603e558015610c1257603d805460ff60a81b1916905550565b600081836131db5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612078578181015183820152602001612060565b5060008385816131e757fe5b0495945050505050565b3390565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610c2f575050151592915050565b6001600160a01b0383166000908152602085815260408083205491889052909120439190811580159061327f575060001982016000908152602082905260409020546001600160801b038481169116145b156132b4576000198201600090815260208290526040902080546001600160801b03808716600160801b029116179055612a97565b6040805180820182526001600160801b038086168252868116602080840191825260008781528682528581209451855493518516600160801b029085166001600160801b031990941693909317909316919091179092556001600160a01b038916815290899052206001830190555050505050505050565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928261338c57600085556133d2565b82601f106133a55782800160ff198235161785556133d2565b828001600101855582156133d2579182015b828111156133d25782358255916020019190600101906133b7565b506133de9291506133f9565b5090565b604080518082019091526000808252602082015290565b5b808211156133de57600081556001016133fa565b80356001600160a01b0381168114610bc457600080fd5b803560028110610bc457600080fd5b60008083601f840112613445578182fd5b50813567ffffffffffffffff81111561345c578182fd5b60208301915083602082850101111561347457600080fd5b9250929050565b803560ff81168114610bc457600080fd5b60006020828403121561349d578081fd5b610a1d8261340e565b600080604083850312156134b8578081fd5b6134c18361340e565b91506134cf6020840161340e565b90509250929050565b6000806000606084860312156134ec578081fd5b6134f58461340e565b92506135036020850161340e565b9150604084013590509250925092565b600080600080600080600060e0888a03121561352d578283fd5b6135368861340e565b96506135446020890161340e565b955060408801359450606088013593506135606080890161347b565b925060a0880135915060c0880135905092959891949750929550565b6000806040838503121561358e578182fd5b6135978361340e565b91506134cf60208401613425565b600080600080600080600060e0888a0312156135bf578283fd5b6135c88861340e565b965061354460208901613425565b600080604083850312156135e8578182fd5b6135f18361340e565b946020939093013593505050565b600080600060608486031215613613578283fd5b61361c8461340e565b92506020840135915061363160408501613425565b90509250925092565b60008060008060008060c08789031215613652578182fd5b61365b8761340e565b955060208701359450604087013593506136776060880161347b565b92506080870135915060a087013590509295509295509295565b600080602083850312156136a3578081fd5b823567ffffffffffffffff808211156136ba578283fd5b818501915085601f8301126136cd578283fd5b8135818111156136db578384fd5b8660206060830285010111156136ef578384fd5b60209290920196919550909350505050565b60008060008060008060808789031215613719578384fd5b863567ffffffffffffffff80821115613730578586fd5b61373c8a838b01613434565b90985096506020890135915080821115613754578586fd5b5061376189828a01613434565b909550935061377490506040880161347b565b91506137826060880161340e565b90509295509295509295565b60006020828403121561379f578081fd5b81356001600160801b0381168114610a1d578182fd5b6000602082840312156137c6578081fd5b5035919050565b600080600080608085870312156137e2578182fd5b84359350602085013592506137f96040860161340e565b9396929550929360600135925050565b60008151808452815b8181101561382e57602081850181015186830182015201613812565b8181111561383f5782602083870101525b50601f01601f19169290920160200192915050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b9485526001600160a01b0393909316602085015260408401919091526060830152608082015260a00190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b93845260ff9290921660208401526040830152606082015260800190565b600060208252610a1d6020830184613809565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260119082015270494e56414c49445f5349474e415455524560781b604082015260600190565b60208082526015908201527424a729aaa32324a1a4a2a72a2fa1a7a7a62227aba760591b604082015260600190565b60208082526012908201527124a72b20a624a22fa2ac2824a920aa24a7a760711b604082015260600190565b6020808252600d908201526c494e56414c49445f4e4f4e434560981b604082015260600190565b60208082526015908201527427a7262cafa2a6a4a9a9a4a7a72fa6a0a720a3a2a960591b604082015260600190565b6020808252600d908201526c24a72b20a624a22fa7aba722a960991b604082015260600190565b60208082526017908201527f554e5354414b455f57494e444f575f46494e4953484544000000000000000000604082015260600190565b60208082526021908201527f5472757374466f7277617264657220616464726573732063616e2774206265206040820152600360fc1b606082015260800190565b6020808252601b908201527f494e56414c49445f42414c414e43455f4f4e5f434f4f4c444f574e0000000000604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b039384168152919092166020820152604081019190915260600190565b60ff9190911681526020019056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220e49629af1a53054adaaf37b1ac31875a48cb942fa6646fb3d71c81959be8490664736f6c6343000705003300000000000000000000000016f8383e99c22fb33144ee9808b4ab25b06c5bb5000000000000000000000000f17e65822b568b3903685a7c9f496cf7656cc6c200000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000003f480000000000000000000000000a6737d7fdf4dd5307ab632d401df7f8a42ea258800000000000000000000000012eea3f557e8537b05a5d2ec5ebb3c7d2f7f1a0800000000000000000000000000000000000000000000000000000000bbf81e00000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000155374616b6564204269636f2042505420546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000773746b4242505400000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102f15760003560e01c80638dbefee21161019d578063b9844d8d116100e9578063dc937e1c116100a2578063de7ea79d1161007c578063de7ea79d146105fc578063f11b81881461060f578063f1cc432a14610631578063f713d8a814610644576102f1565b8063dc937e1c146105ce578063dd62ed3e146105e1578063dde43cba146105f4576102f1565b8063b9844d8d14610572578063c2ffbb9114610585578063c3863ada14610598578063c3cda520146105a0578063cbcbb507146105b3578063d505accf146105bb576102f1565b80639a99b4f011610156578063aa9fbe0211610130578063aa9fbe0214610531578063adc9772e14610539578063b2a5dbfa1461054c578063b2f4201d1461055f576102f1565b80639a99b4f0146104f8578063a457c2d71461050b578063a9059cbb1461051e576102f1565b80638dbefee2146104b2578063919cd40f146104c5578063946776cd146104cd57806395d89b41146104d5578063981b24d0146104dd57806399248ea7146104f0576102f1565b80633644e5151161025c5780636f50458d1161021557806378160376116101ef578063781603761461047c578063787a08a6146104845780637bb73c971461048c5780637e90d7ef1461049f576102f1565b80636f50458d1461044e57806370a082311461046157806372b49d6314610474576102f1565b80633644e515146103e457806339509351146103ec57806341cbf54a146103ff578063572b6c05146104075780635b3cc0cf1461041a5780635c19a95c1461043b576102f1565b8063249aea9b116102ae578063249aea9b1461038457806330adf81f14610397578063312f6b831461039f578063313ce567146103b45780633373ee4c146103c9578063359c4a96146103dc576102f1565b806306fdde03146102f6578063091030c314610314578063095ea7b31461033457806318160ddd146103545780631e9a69501461035c57806323b872dd14610371575b600080fd5b6102fe610657565b60405161030b91906139a2565b60405180910390f35b61032761032236600461348c565b6106ee565b60405161030b91906138cb565b6103476103423660046135d6565b610700565b60405161030b91906138c0565b61032761071e565b61036f61036a3660046135d6565b610724565b005b61034761037f3660046134d8565b61099c565b61036f61039236600461348c565b610a24565b610327610a95565b6103a7610ab9565b60405161030b919061386f565b6103bc610add565b60405161030b9190613be6565b6103276103d73660046134a6565b610ae6565b610327610b16565b610327610b3a565b6103476103fa3660046135d6565b610b40565b610327610b8e565b61034761041536600461348c565b610bb2565b61042d6104283660046135d6565b610bc9565b60405161030b929190613ba8565b61036f61044936600461348c565b610bfa565b6103a761045c36600461357c565b610c15565b61032761046f36600461348c565b610c37565b610327610c52565b6102fe610c76565b61036f610c93565b61032761049a36600461348c565b610d20565b6103276104ad36600461348c565b610d32565b6103276104c036600461348c565b610d44565b610327610df3565b6103a7610e17565b6102fe610e3b565b6103276104eb3660046137b5565b610e9c565b6103a7610ea6565b61036f6105063660046135d6565b610eca565b6103476105193660046135d6565b61106e565b61034761052c3660046135d6565b6110d6565b6103276110ea565b61036f6105473660046135d6565b61110e565b61036f61055a366004613691565b611290565b61032761056d36600461357c565b611443565b61032761058036600461348c565b61146b565b6103276105933660046135ff565b61147d565b6103a76114a6565b61036f6105ae36600461363a565b6114b5565b6103a7611631565b61036f6105c9366004613513565b611655565b61036f6105dc36600461357c565b6117e2565b6103276105ef3660046134a6565b6117f1565b61032761181c565b61036f61060a366004613701565b611821565b61062261061d36600461348c565b611919565b60405161030b93929190613bc2565b61032761063f3660046137cd565b611947565b61036f6106523660046135a5565b611a3c565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106e35780601f106106b8576101008083540402835291602001916106e3565b820191906000526020600020905b8154815290600101906020018083116106c657829003601f168201915b505050505090505b90565b60716020526000908152604090205481565b600061071461070d611c29565b8484611c38565b5060015b92915050565b60025490565b6002603e54141561077c576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002603e55806107a75760405162461bcd60e51b815260040161079e906139b5565b60405180910390fd5b6000607160006107b5611c29565b6001600160a01b0316815260208101919091526040016000205490506107fb817f00000000000000000000000000000000000000000000000000000000001baf80611bb9565b42116108195760405162461bcd60e51b815260040161079e90613a0d565b7f000000000000000000000000000000000000000000000000000000000003f48061086e610867837f00000000000000000000000000000000000000000000000000000000001baf80611bb9565b4290611d24565b111561088c5760405162461bcd60e51b815260040161079e90613ae5565b600061089961046f611c29565b905060008184116108aa57836108ac565b815b90506108c16108b9611c29565b836001611d66565b506108d36108cd611c29565b82611e0a565b6108dd8282611d24565b61090a576000607160006108ef611c29565b6001600160a01b031681526020810191909152604001600020555b61093e6001600160a01b037f00000000000000000000000016f8383e99c22fb33144ee9808b4ab25b06c5bb5168683611f06565b846001600160a01b0316610950611c29565b6001600160a01b03167fd12200efa34901b99367694174c3b0d32c99585fdf37c7c26892136ddd0836d98360405161098891906138cb565b60405180910390a350506001603e55505050565b60006109a9848484611f58565b610a19846109b5611c29565b610a1485604051806060016040528060288152602001613cd1602891396001600160a01b038a166000908152600160205260408120906109f3611c29565b6001600160a01b031681526020810191909152604001600020549190612024565b611c38565b5060015b9392505050565b6000610a2e6120bb565b90506009548111610a705760405162461bcd60e51b815260040180806020018281038252602e815260200180613cf9602e913960400191505060405180910390fd5b600955603d80546001600160a01b0319166001600160a01b0392909216919091179055565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b7f00000000000000000000000016f8383e99c22fb33144ee9808b4ab25b06c5bb581565b60055460ff1690565b6001600160a01b038082166000908152603c60209081526040808320938616835260029093019052205492915050565b7f000000000000000000000000000000000000000000000000000000000003f48081565b60765481565b6000610714610b4d611c29565b84610a148560016000610b5e611c29565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611bb9565b7f9a9a49b990ba9bb39f8048c490a40ab25c18f55d208d5fbcf958261a9b48716d81565b603d546001600160a01b038281169116145b919050565b60066020908152600092835260408084209091529082529020546001600160801b0380821691600160801b90041682565b610c06338260006120c0565b610c12338260016120c0565b50565b600080610c21836121d1565b92505050610c2f848261220b565b949350505050565b6001600160a01b031660009081526020819052604090205490565b7f00000000000000000000000000000000000000000000000000000000001baf8081565b604051806040016040528060018152602001603160f81b81525081565b610c9e61046f611c29565b610cba5760405162461bcd60e51b815260040161079e90613b5d565b4260716000610cc7611c29565b6001600160a01b03168152602081019190915260400160002055610ce9611c29565b6001600160a01b03167ff52f50426b32362d3e6bb8cb36b7074756b224622def6352a59eac7f66ebe6e860405160405180910390a2565b60076020526000908152604090205481565b60706020526000908152604090205481565b60408051600180825281830190925260009160609190816020015b610d6761332c565b815260200190600190039081610d5f5790505090506040518060600160405280306001600160a01b03168152602001610d9f85610c37565b8152602001610dac61071e565b81525081600081518110610dbc57fe5b6020026020010181905250610a1d610dd48483612236565b6001600160a01b03851660009081526070602052604090205490611bb9565b7f000000000000000000000000000000000000000000000000000000011e55e31181565b7f000000000000000000000000a6737d7fdf4dd5307ab632d401df7f8a42ea258881565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106e35780601f106106b8576101008083540402835291602001916106e3565b600061071861071e565b7f000000000000000000000000f17e65822b568b3903685a7c9f496cf7656cc6c281565b6002603e541415610f22576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002603e556000610f46610f34611c29565b610f3f61046f611c29565b6000611d66565b905060006000198314610f595782610f5b565b815b9050610f98816040518060400160405280600e81526020016d1253959053125117d05353d5539560921b815250846120249092919063ffffffff16565b60706000610fa4611c29565b6001600160a01b039081168252602082019290925260400160002091909155611011907f000000000000000000000000f17e65822b568b3903685a7c9f496cf7656cc6c2167f000000000000000000000000a6737d7fdf4dd5307ab632d401df7f8a42ea25888684612327565b836001600160a01b0316611023611c29565b6001600160a01b03167f9310ccfcb8de723f578a9e4282ea9f521f05ae40dc08f3068dfad528a65ee3c78360405161105b91906138cb565b60405180910390a350506001603e555050565b600061071461107b611c29565b84610a1485604051806060016040528060258152602001613dbb60259139600160006110a5611c29565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190612024565b60006107146110e3611c29565b8484611f58565b7f10d8d059343739efce7dad10d09f0806da52b252b3e6a7951920d2d6ec4102e581565b8061112b5760405162461bcd60e51b815260040161079e906139b5565b600061113683610c37565b9050600061114d84308461114861071e565b612381565b905080156111cb577f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a7684826040516111869291906138a7565b60405180910390a16001600160a01b0384166000908152607060205260409020546111b19082611bb9565b6001600160a01b0385166000908152607060205260409020555b6111d86000848685611947565b6001600160a01b0385166000908152607160205260409020556111fb8484612440565b611238611206611c29565b6001600160a01b037f00000000000000000000000016f8383e99c22fb33144ee9808b4ab25b06c5bb516903086612327565b836001600160a01b031661124a611c29565b6001600160a01b03167f5dac0c1b1112564a045ba943c9d50270893e8e826c49be8e7073adc713ab7bd78560405161128291906138cb565b60405180910390a350505050565b336001600160a01b037f00000000000000000000000012eea3f557e8537b05a5d2ec5ebb3c7d2f7f1a0816146112d85760405162461bcd60e51b815260040161079e90613a8f565b60005b8181101561143e576000603c60008585858181106112f557fe5b905060600201604001602081019061130d919061348c565b6001600160a01b03166001600160a01b03168152602001908152602001600020905061137284848481811061133e57fe5b9050606002016040016020810190611356919061348c565b8286868681811061136357fe5b90506060020160200135612530565b5083838381811061137f57fe5b611395926020606090920201908101915061378e565b81546001600160801b0319166001600160801b03919091161781558383838181106113bc57fe5b90506060020160400160208101906113d4919061348c565b6001600160a01b03167f87fa03892a0556cb6b8f97e6d533a150d4d55fcbf275fff5fa003fa636bcc7fa85858581811061140a57fe5b611420926020606090920201908101915061378e565b60405161142d9190613b94565b60405180910390a2506001016112db565b505050565b6000806000611451846121d1565b5091509150611462828287436125ed565b95945050505050565b60776020526000908152604090205481565b600080600061148b846121d1565b509150915061149c828288886125ed565b9695505050505050565b6008546001600160a01b031681565b60007f9a9a49b990ba9bb39f8048c490a40ab25c18f55d208d5fbcf958261a9b48716d8787876040516020016114ee9493929190613908565b60405160208183030381529060405280519060200120905060006076548260405160200161151d929190613854565b60405160208183030381529060405280519060200120905060006001828787876040516000815260200160405260405161155a9493929190613984565b6020604051602081039080840390855afa15801561157c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166115af5760405162461bcd60e51b815260040161079e906139e2565b6001600160a01b038116600090815260776020526040902080546001810190915588146115ee5760405162461bcd60e51b815260040161079e90613a68565b8642111561160e5760405162461bcd60e51b815260040161079e90613a3c565b61161a818a60006120c0565b611626818a60016120c0565b505050505050505050565b7f00000000000000000000000012eea3f557e8537b05a5d2ec5ebb3c7d2f7f1a0881565b6001600160a01b03871661167b5760405162461bcd60e51b815260040161079e90613abe565b8342111561169b5760405162461bcd60e51b815260040161079e90613a3c565b6001600160a01b03871660009081526077602090815260408083205460765491519093926116f5917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918d918d918d9189918e91016138d4565b6040516020818303038152906040528051906020012060405160200161171c929190613854565b604051602081830303815290604052805190602001209050600181868686604051600081526020016040526040516117579493929190613984565b6020604051602081039080840390855afa158015611779573d6000803e3d6000fd5b505050602060405103516001600160a01b0316896001600160a01b0316146117b35760405162461bcd60e51b815260040161079e906139e2565b6117be826001611bb9565b6001600160a01b038a16600090815260776020526040902055611626898989611c38565b6117ed3383836120c0565b5050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600181565b6001600160a01b0381166118475760405162461bcd60e51b815260040161079e90613b1c565b61185081610a24565b611858612809565b467f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611882610657565b805160209182012060408051808201825260018152603160f81b90840152516118d293927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6918691309101613958565b60408051601f1981840301815291905280516020909101206076556118f960038888613356565b5061190660048686613356565b5061191083611c13565b50505050505050565b603c60205260009081526040902080546001909101546001600160801b0380831692600160801b9004169083565b6001600160a01b0382166000908152607160205260408120548061196f576000915050610c2f565b60006119c57f000000000000000000000000000000000000000000000000000000000003f4806119bf427f00000000000000000000000000000000000000000000000000000000001baf80611d24565b90611d24565b9050818111156119d85760009150611a32565b60008782116119e757876119e9565b425b9050828110156119fe57829350505050610c2f565b611a2e611a0b8887611bb9565b611a28611a1888876128bb565b611a228b866128bb565b90611bb9565b90612914565b9250505b5095945050505050565b60007f10d8d059343739efce7dad10d09f0806da52b252b3e6a7951920d2d6ec4102e588886001811115611a6c57fe5b8888604051602001611a8295949392919061392c565b604051602081830303815290604052805190602001209050600060765482604051602001611ab1929190613854565b604051602081830303815290604052805190602001209050600060018287878760405160008152602001604052604051611aee9493929190613984565b6020604051602081039080840390855afa158015611b10573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611b435760405162461bcd60e51b815260040161079e906139e2565b6001600160a01b03811660009081526077602052604090208054600181019091558814611b825760405162461bcd60e51b815260040161079e90613a68565b86421115611ba25760405162461bcd60e51b815260040161079e90613a3c565b611bad818b8b6120c0565b50505050505050505050565b600082820183811015610a1d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6005805460ff191660ff92909216919091179055565b6000611c33612956565b905090565b6001600160a01b038316611c7d5760405162461bcd60e51b8152600401808060200182810382526024815260200180613d6d6024913960400191505060405180910390fd5b6001600160a01b038216611cc25760405162461bcd60e51b8152600401808060200182810382526022815260200180613c3a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6000610a1d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612024565b600080611d7785308661114861071e565b6001600160a01b03861660009081526070602052604081205491925090611d9e9083611bb9565b90508115611462578315611dc8576001600160a01b03861660009081526070602052604090208190555b7f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a768683604051611df99291906138a7565b60405180910390a195945050505050565b6001600160a01b038216611e4f5760405162461bcd60e51b8152600401808060200182810382526021815260200180613d276021913960400191505060405180910390fd5b611e5b82600083612984565b611e9881604051806060016040528060228152602001613c18602291396001600160a01b0385166000908152602081905260409020549190612024565b6001600160a01b038316600090815260208190526040902055600254611ebe9082611d24565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261143e908490612aa1565b6000611f6384610c37565b9050611f7184826001611d66565b50826001600160a01b0316846001600160a01b031614612013576000611f9684610c37565b9050611fa484826001611d66565b506001600160a01b038516600090815260716020526040902054611fca81858785611947565b6001600160a01b0386166000908152607160205260409020558284148015611ff157508015155b15612010576001600160a01b0386166000908152607160205260408120555b50505b61201e848484612c59565b50505050565b600081848411156120b35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612078578181015183820152602001612060565b50505050905090810190601f1680156120a55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600190565b6001600160a01b03821661210f576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f44454c45474154454560781b604482015290519081900360640190fd5b600061211a826121d1565b92505050600061212985610c37565b90506000612137868461220b565b6001600160a01b03878116600090815260208690526040902080546001600160a01b031916918816919091179055905061217381868487612db4565b846001600160a01b0316866001600160a01b03167fe8d51c8e11bd570db1734c8ec775785330e77007feed45c43b608ef33ff914bd86604051808260018111156121b957fe5b815260200191505060405180910390a3505050505050565b60008080808460018111156121e257fe5b14156121f8575060069150600790506072612204565b50607391506074905060755b9193909250565b6001600160a01b0380831660009081526020839052604081205490911680610a1d5783915050610718565b600080805b835181101561231f576000603c600086848151811061225657fe5b602090810291909101810151516001600160a01b0316825281019190915260400160009081206001810154815488519294506122be926001600160801b0380831692600160801b900416908a90889081106122ad57fe5b602002602001015160400151612fc2565b905061231361230c8785815181106122d257fe5b602002602001015160200151838560020160008c6001600160a01b03166001600160a01b03168152602001908152602001600020546130bb565b8590611bb9565b9350505060010161223b565b509392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261201e908590612aa1565b6001600160a01b038084166000908152603c6020908152604080832093881683526002840190915281205490919082806123bc888588612530565b90508083146124345786156123d9576123d68782856130bb565b91505b6001600160a01b03808a1660008181526002870160205260409081902084905551918a16917fbb123b5c06d5408bbea3c4fef481578175cfb432e3b482c6186f02ed9086585b9061242b9085906138cb565b60405180910390a35b50979650505050505050565b6001600160a01b03821661249b576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6124a760008383612984565b6002546124b49082611bb9565b6002556001600160a01b0382166000908152602081905260409020546124da9082611bb9565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001820154825460009190600160801b90046001600160801b03164281141561255b57509050610a1d565b84546000906125769084906001600160801b03168488612fc2565b90508281146125ca57808660010181905550866001600160a01b03167f5777ca300dfe5bead41006fbce4389794dbc0ed8d6cccebfaf94630aa04184bc826040516125c191906138cb565b60405180910390a25b85546001600160801b03428116600160801b029116178655925050509392505050565b60004382111561263b576040805162461bcd60e51b815260206004820152601460248201527324a72b20a624a22fa12627a1a5afa72aa6a122a960611b604482015290519081900360640190fd5b6001600160a01b0383166000908152602085905260409020548061266a5761266284610c37565b915050610c2f565b6001600160a01b038416600090815260208781526040808320600019850184529091529020546001600160801b031683106126dd576001600160a01b038416600090815260208781526040808320600019909401835292905220546001600160801b03600160801b909104169050610c2f565b6001600160a01b0384166000908152602087815260408083208380529091529020546001600160801b0316831015612719576000915050610c2f565b600060001982015b818111156127cb5760028282030481036127396133e2565b506001600160a01b038716600090815260208a815260408083208484528252918290208251808401909352546001600160801b03808216808552600160801b90920416918301919091528714156127a357602001516001600160801b03169450610c2f9350505050565b80516001600160801b03168711156127bd578193506127c4565b6001820392505b5050612721565b506001600160a01b03851660009081526020888152604080832093835292905220546001600160801b03600160801b90910416915050949350505050565b603d54600160a81b900460ff168061282b5750603d54600160a01b900460ff16155b6128665760405162461bcd60e51b815260040180806020018281038252602e815260200180613c82602e913960400191505060405180910390fd5b603d54600160a81b900460ff1615801561289d57603d805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6128a56130dd565b8015610c1257603d805460ff60a81b1916905550565b6000826128ca57506000610718565b828202828482816128d757fe5b0414610a1d5760405162461bcd60e51b8152600401808060200182810382526021815260200180613cb06021913960400191505060405180910390fd5b6000610a1d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061318c565b600061296133610bb2565b15612975575060131936013560601c6106eb565b61297d6131f1565b90506106eb565b6001600160a01b038084166000908152607260205260408082205485841683529120549082169116816129b5578491505b6001600160a01b0381166129c65750825b6129d38282856000612db4565b6001600160a01b03808616600090815260756020526040808220548784168352912054908216911681612a04578691505b6001600160a01b038116612a155750845b612a228282876001612db4565b6008546001600160a01b03168015612a9757604051634a39314960e01b81526001600160a01b03821690634a39314990612a64908b908b908b90600401613883565b600060405180830381600087803b158015612a7e57600080fd5b505af1158015612a92573d6000803e3d6000fd5b505050505b5050505050505050565b612ab3826001600160a01b03166131f5565b612b04576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612b425780518252601f199092019160209182019101612b23565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612ba4576040519150601f19603f3d011682016040523d82523d6000602084013e612ba9565b606091505b509150915081612c00576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b80511561201e57808060200190516020811015612c1c57600080fd5b505161201e5760405162461bcd60e51b815260040180806020018281038252602a815260200180613d91602a913960400191505060405180910390fd5b6001600160a01b038316612c9e5760405162461bcd60e51b8152600401808060200182810382526025815260200180613d486025913960400191505060405180910390fd5b6001600160a01b038216612ce35760405162461bcd60e51b8152600401808060200182810382526023815260200180613bf56023913960400191505060405180910390fd5b612cee838383612984565b612d2b81604051806060016040528060268152602001613c5c602691396001600160a01b0386166000908152602081905260409020549190612024565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612d5a9082611bb9565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b826001600160a01b0316846001600160a01b03161415612dd35761201e565b600080612ddf836121d1565b5090925090506001600160a01b03861615612ed2576001600160a01b0386166000908152602082905260408120548015612e50576001600160a01b03881660009081526020858152604080832060001985018452909152902054600160801b90046001600160801b03169150612e5c565b612e5988610c37565b91505b612e7284848a85612e6d818c611d24565b61322e565b6001600160a01b0388167fa0a19463ee116110c9b282012d9b65cc5522dc38a9520340cbaf3142e550127f612ea78489611d24565b8760405180838152602001826001811115612ebe57fe5b81526020019250505060405180910390a250505b6001600160a01b03851615612fba576001600160a01b0385166000908152602082905260408120548015612f3d576001600160a01b03871660009081526020858152604080832060001985018452909152902054600160801b90046001600160801b03169150612f49565b612f4687610c37565b91505b612f5a84848985612e6d818c611bb9565b6001600160a01b0387167fa0a19463ee116110c9b282012d9b65cc5522dc38a9520340cbaf3142e550127f612f8f8489611bb9565b8760405180838152602001826001811115612fa657fe5b81526020019250505060405180910390a250505b505050505050565b6000831580612fcf575081155b80612fe2575042836001600160801b0316145b8061301657507f000000000000000000000000000000000000000000000000000000011e55e311836001600160801b031610155b15613022575083610c2f565b60007f000000000000000000000000000000000000000000000000000000011e55e31142116130515742613073565b7f000000000000000000000000000000000000000000000000000000011e55e3115b9050600061308a826001600160801b038716611d24565b90506130b087611a2286611a28670de0b6b3a76400006130aa8c886128bb565b906128bb565b979650505050505050565b6000610c2f670de0b6b3a7640000611a286130d68686611d24565b87906128bb565b603d54600160a81b900460ff16806130ff5750603d54600160a01b900460ff16155b61313a5760405162461bcd60e51b815260040180806020018281038252602e815260200180613c82602e913960400191505060405180910390fd5b603d54600160a81b900460ff1615801561317157603d805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001603e558015610c1257603d805460ff60a81b1916905550565b600081836131db5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612078578181015183820152602001612060565b5060008385816131e757fe5b0495945050505050565b3390565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610c2f575050151592915050565b6001600160a01b0383166000908152602085815260408083205491889052909120439190811580159061327f575060001982016000908152602082905260409020546001600160801b038481169116145b156132b4576000198201600090815260208290526040902080546001600160801b03808716600160801b029116179055612a97565b6040805180820182526001600160801b038086168252868116602080840191825260008781528682528581209451855493518516600160801b029085166001600160801b031990941693909317909316919091179092556001600160a01b038916815290899052206001830190555050505050505050565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928261338c57600085556133d2565b82601f106133a55782800160ff198235161785556133d2565b828001600101855582156133d2579182015b828111156133d25782358255916020019190600101906133b7565b506133de9291506133f9565b5090565b604080518082019091526000808252602082015290565b5b808211156133de57600081556001016133fa565b80356001600160a01b0381168114610bc457600080fd5b803560028110610bc457600080fd5b60008083601f840112613445578182fd5b50813567ffffffffffffffff81111561345c578182fd5b60208301915083602082850101111561347457600080fd5b9250929050565b803560ff81168114610bc457600080fd5b60006020828403121561349d578081fd5b610a1d8261340e565b600080604083850312156134b8578081fd5b6134c18361340e565b91506134cf6020840161340e565b90509250929050565b6000806000606084860312156134ec578081fd5b6134f58461340e565b92506135036020850161340e565b9150604084013590509250925092565b600080600080600080600060e0888a03121561352d578283fd5b6135368861340e565b96506135446020890161340e565b955060408801359450606088013593506135606080890161347b565b925060a0880135915060c0880135905092959891949750929550565b6000806040838503121561358e578182fd5b6135978361340e565b91506134cf60208401613425565b600080600080600080600060e0888a0312156135bf578283fd5b6135c88861340e565b965061354460208901613425565b600080604083850312156135e8578182fd5b6135f18361340e565b946020939093013593505050565b600080600060608486031215613613578283fd5b61361c8461340e565b92506020840135915061363160408501613425565b90509250925092565b60008060008060008060c08789031215613652578182fd5b61365b8761340e565b955060208701359450604087013593506136776060880161347b565b92506080870135915060a087013590509295509295509295565b600080602083850312156136a3578081fd5b823567ffffffffffffffff808211156136ba578283fd5b818501915085601f8301126136cd578283fd5b8135818111156136db578384fd5b8660206060830285010111156136ef578384fd5b60209290920196919550909350505050565b60008060008060008060808789031215613719578384fd5b863567ffffffffffffffff80821115613730578586fd5b61373c8a838b01613434565b90985096506020890135915080821115613754578586fd5b5061376189828a01613434565b909550935061377490506040880161347b565b91506137826060880161340e565b90509295509295509295565b60006020828403121561379f578081fd5b81356001600160801b0381168114610a1d578182fd5b6000602082840312156137c6578081fd5b5035919050565b600080600080608085870312156137e2578182fd5b84359350602085013592506137f96040860161340e565b9396929550929360600135925050565b60008151808452815b8181101561382e57602081850181015186830182015201613812565b8181111561383f5782602083870101525b50601f01601f19169290920160200192915050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b9485526001600160a01b0393909316602085015260408401919091526060830152608082015260a00190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b93845260ff9290921660208401526040830152606082015260800190565b600060208252610a1d6020830184613809565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260119082015270494e56414c49445f5349474e415455524560781b604082015260600190565b60208082526015908201527424a729aaa32324a1a4a2a72a2fa1a7a7a62227aba760591b604082015260600190565b60208082526012908201527124a72b20a624a22fa2ac2824a920aa24a7a760711b604082015260600190565b6020808252600d908201526c494e56414c49445f4e4f4e434560981b604082015260600190565b60208082526015908201527427a7262cafa2a6a4a9a9a4a7a72fa6a0a720a3a2a960591b604082015260600190565b6020808252600d908201526c24a72b20a624a22fa7aba722a960991b604082015260600190565b60208082526017908201527f554e5354414b455f57494e444f575f46494e4953484544000000000000000000604082015260600190565b60208082526021908201527f5472757374466f7277617264657220616464726573732063616e2774206265206040820152600360fc1b606082015260800190565b6020808252601b908201527f494e56414c49445f42414c414e43455f4f4e5f434f4f4c444f574e0000000000604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b039384168152919092166020820152604081019190915260600190565b60ff9190911681526020019056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220e49629af1a53054adaaf37b1ac31875a48cb942fa6646fb3d71c81959be8490664736f6c63430007050033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000016f8383e99c22fb33144ee9808b4ab25b06c5bb5000000000000000000000000f17e65822b568b3903685a7c9f496cf7656cc6c200000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000003f480000000000000000000000000a6737d7fdf4dd5307ab632d401df7f8a42ea258800000000000000000000000012eea3f557e8537b05a5d2ec5ebb3c7d2f7f1a0800000000000000000000000000000000000000000000000000000000bbf81e00000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000155374616b6564204269636f2042505420546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000773746b4242505400000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : stakedToken (address): 0x16F8383E99c22Fb33144ee9808B4Ab25b06C5bb5
Arg [1] : rewardToken (address): 0xF17e65822b568B3903685a7c9F496CF7656Cc6C2
Arg [2] : cooldownSeconds (uint256): 1814400
Arg [3] : unstakeWindow (uint256): 259200
Arg [4] : rewardsVault (address): 0xa6737D7fdF4DD5307Ab632D401DF7F8A42EA2588
Arg [5] : emissionManager (address): 0x12eEa3f557E8537b05A5d2EC5eBb3c7D2f7f1a08
Arg [6] : distributionDuration (uint128): 3153600000
Arg [7] : name (string): Staked Bico BPT Token
Arg [8] : symbol (string): stkBBPT
Arg [9] : decimals (uint8): 18
Arg [10] : governance (address): 0x0000000000000000000000000000000000000000
-----Encoded View---------------
15 Constructor Arguments found :
Arg [0] : 00000000000000000000000016f8383e99c22fb33144ee9808b4ab25b06c5bb5
Arg [1] : 000000000000000000000000f17e65822b568b3903685a7c9f496cf7656cc6c2
Arg [2] : 00000000000000000000000000000000000000000000000000000000001baf80
Arg [3] : 000000000000000000000000000000000000000000000000000000000003f480
Arg [4] : 000000000000000000000000a6737d7fdf4dd5307ab632d401df7f8a42ea2588
Arg [5] : 00000000000000000000000012eea3f557e8537b05a5d2ec5ebb3c7d2f7f1a08
Arg [6] : 00000000000000000000000000000000000000000000000000000000bbf81e00
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [8] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000015
Arg [12] : 5374616b6564204269636f2042505420546f6b656e0000000000000000000000
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [14] : 73746b4242505400000000000000000000000000000000000000000000000000
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.