Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x61016060 | 13912303 | 921 days ago | IN | Create: LyraSafetyModule | 0 ETH | 0.5003337 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
LyraSafetyModule
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: agpl-3.0 pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import { StakedTokenV3 } from "@aave/aave-stake-v2/contracts/stake/StakedTokenV3.sol"; import { IERC20 } from "@aave/aave-stake-v2/contracts/interfaces/IERC20.sol"; /** * @title LyraSafetyModule * @notice Contract to stake Lyra token, tokenize the position and get rewards, inheriting from AAVE StakedTokenV3 * @author Lyra **/ contract LyraSafetyModule is StakedTokenV3 { string internal constant NAME = "Staked Lyra"; string internal constant SYMBOL = "stkLYRA"; uint8 internal constant DECIMALS = 18; constructor( IERC20 stakedToken, IERC20 rewardToken, uint256 cooldownSeconds, uint256 unstakeWindow, address rewardsVault, address emissionManager, uint128 distributionDuration ) public StakedTokenV3( stakedToken, rewardToken, cooldownSeconds, unstakeWindow, rewardsVault, emissionManager, distributionDuration, NAME, SYMBOL, DECIMALS, address(0) ) {} }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import {ERC20} from '@aave/aave-token/contracts/open-zeppelin/ERC20.sol'; import {IERC20} from '../interfaces/IERC20.sol'; import {IStakedAave} from '../interfaces/IStakedAave.sol'; import {ITransferHook} from '../interfaces/ITransferHook.sol'; import {DistributionTypes} from '../lib/DistributionTypes.sol'; import {SafeMath} from '../lib/SafeMath.sol'; import {SafeERC20} from '../lib/SafeERC20.sol'; import {VersionedInitializable} from '../utils/VersionedInitializable.sol'; import {AaveDistributionManager} from './AaveDistributionManager.sol'; import {GovernancePowerWithSnapshot} from '../lib/GovernancePowerWithSnapshot.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 { 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) { 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 ) external initializer { 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 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(msg.sender, address(this), amount); emit Staked(msg.sender, 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 { require(amount != 0, 'INVALID_ZERO_AMOUNT'); //solium-disable-next-line uint256 cooldownStartTimestamp = stakersCooldowns[msg.sender]; 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(msg.sender); uint256 amountToRedeem = (amount > balanceOfMessageSender) ? balanceOfMessageSender : amount; _updateCurrentUnclaimedRewards(msg.sender, balanceOfMessageSender, true); _burn(msg.sender, amountToRedeem); if (balanceOfMessageSender.sub(amountToRedeem) == 0) { stakersCooldowns[msg.sender] = 0; } IERC20(STAKED_TOKEN).safeTransfer(to, amountToRedeem); emit Redeem(msg.sender, 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(msg.sender) != 0, 'INVALID_BALANCE_ON_COOLDOWN'); //solium-disable-next-line stakersCooldowns[msg.sender] = block.timestamp; emit Cooldown(msg.sender); } /** * @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 { uint256 newTotalRewards = _updateCurrentUnclaimedRewards(msg.sender, balanceOf(msg.sender), false); uint256 amountToClaim = (amount == type(uint256).max) ? newTotalRewards : amount; stakerRewardsToClaim[msg.sender] = newTotalRewards.sub(amountToClaim, 'INVALID_AMOUNT'); REWARD_TOKEN.safeTransferFrom(REWARDS_VAULT, to, amountToClaim); emit RewardsClaimed(msg.sender, 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 ) public { 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; /** * @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 pragma solidity ^0.7.5; import "./Context.sol"; import "../interfaces/IERC20.sol"; import "./SafeMath.sol"; import "./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: agpl-3.0 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: agpl-3.0 pragma solidity 0.7.5; interface ITransferHook { function onTransfer( address from, address to, uint256 amount ) external; }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.7.5; pragma experimental ABIEncoderV2; library DistributionTypes { struct AssetConfigInput { uint128 emissionPerSecond; uint256 totalStaked; address underlyingAsset; } struct UserStakeInput { address underlyingAsset; uint256 stakedByUser; uint256 totalStaked; } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.7.5; /** * @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 pragma solidity 0.7.5; import {IERC20} from '../interfaces/IERC20.sol'; import {SafeMath} from './SafeMath.sol'; import {Address} from './Address.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: agpl-3.0 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: agpl-3.0 pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import {SafeMath} from '../lib/SafeMath.sol'; import {DistributionTypes} from '../lib/DistributionTypes.sol'; import {IAaveDistributionManager} from '../interfaces/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; uint8 public constant PRECISION = 18; mapping(address => AssetData) public assets; event AssetConfigUpdated(address indexed asset, uint256 emission); event AssetIndexUpdated(address indexed asset, uint256 index); event UserIndexUpdated(address indexed user, address indexed asset, uint256 index); constructor(address emissionManager, uint256 distributionDuration) public { 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(10**uint256(PRECISION)); } /** * @dev Calculates the next value of an specific distribution index, with validations * @param currentIndex Current index of the distribution * @param emissionPerSecond Representing the total rewards distributed per second per asset unit, on the distribution * @param lastUpdateTimestamp Last moment this distribution was updated * @param totalBalance of tokens considered for the distribution * @return The new index. **/ function _getAssetIndex( uint256 currentIndex, uint256 emissionPerSecond, uint128 lastUpdateTimestamp, uint256 totalBalance ) internal view returns (uint256) { if ( emissionPerSecond == 0 || totalBalance == 0 || lastUpdateTimestamp == block.timestamp || lastUpdateTimestamp >= DISTRIBUTION_END ) { return currentIndex; } uint256 currentTimestamp = block.timestamp > DISTRIBUTION_END ? DISTRIBUTION_END : block.timestamp; uint256 timeDelta = currentTimestamp.sub(lastUpdateTimestamp); return emissionPerSecond.mul(timeDelta).mul(10**uint256(PRECISION)).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) public view returns (uint256) { return assets[asset].users[user]; } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.7.5; import {ERC20} from '../lib/ERC20.sol'; import {ITransferHook} from '../interfaces/ITransferHook.sol'; import {SafeMath} from '../lib/SafeMath.sol'; import { GovernancePowerDelegationERC20 } from '@aave/aave-token/contracts/token/base/GovernancePowerDelegationERC20.sol'; /** * @title ERC20WithSnapshot * @notice ERC20 including snapshots of balances on transfer-related actions * @author Aave **/ 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 pragma solidity ^0.7.5; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with 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 memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.7.5; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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); }
pragma solidity ^0.7.5; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { 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; } }
pragma solidity ^0.7.5; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // 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"); } }
// SPDX-License-Identifier: MIT 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'); } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import {DistributionTypes} from '../lib/DistributionTypes.sol'; interface IAaveDistributionManager { function configureAssets(DistributionTypes.AssetConfigInput[] calldata assetsConfigInput) external; }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.7.5; import {Context} from './Context.sol'; import {IERC20} from '../interfaces/IERC20.sol'; import {IERC20Detailed} from '../interfaces/IERC20Detailed.sol'; import {SafeMath} from './SafeMath.sol'; /** * @title ERC20 * @notice Basic ERC20 implementation * @author Aave **/ contract ERC20 is Context, IERC20, IERC20Detailed { using SafeMath for uint256; mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; constructor( string memory name, string memory symbol, uint8 decimals ) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @return the name of the token **/ function name() public view override returns (string memory) { return _name; } /** * @return the symbol of the token **/ function symbol() public view override returns (string memory) { return _symbol; } /** * @return the decimals of the token **/ function decimals() public view override returns (uint8) { return _decimals; } /** * @return the total supply of the token **/ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @return the balance of the token **/ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev executes a transfer of tokens from msg.sender to recipient * @param recipient the recipient of the tokens * @param amount the amount of tokens being transferred * @return true if the transfer succeeds, false otherwise **/ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev returns the allowance of spender on the tokens owned by owner * @param owner the owner of the tokens * @param spender the user allowed to spend the owner's tokens * @return the amount of owner's tokens spender is allowed to spend **/ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev allows spender to spend the tokens owned by msg.sender * @param spender the user allowed to spend msg.sender tokens * @return true **/ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev executes a transfer of token from sender to recipient, if msg.sender is allowed to do so * @param sender the owner of the tokens * @param recipient the recipient of the tokens * @param amount the amount of tokens being transferred * @return true if the transfer succeeds, false otherwise **/ 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 increases the allowance of spender to spend msg.sender tokens * @param spender the user allowed to spend on behalf of msg.sender * @param addedValue the amount being added to the allowance * @return true **/ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev decreases the allowance of spender to spend msg.sender tokens * @param spender the user allowed to spend on behalf of msg.sender * @param subtractedValue the amount being subtracted to the allowance * @return true **/ 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; } 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); } 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); } 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); } function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), 'ERC20: approve from the zero address'); require(spender != address(0), 'ERC20: approve to the zero address'); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } function _setName(string memory newName) internal { _name = newName; } function _setSymbol(string memory newSymbol) internal { _symbol = newSymbol; } function _setDecimals(uint8 newDecimals) internal { _decimals = newDecimals; } function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.7.5; import {SafeMath} from '../../open-zeppelin/SafeMath.sol'; import {ERC20} from '../../open-zeppelin/ERC20.sol'; import { IGovernancePowerDelegationToken } from '../../interfaces/IGovernancePowerDelegationToken.sol'; /** * @notice implementation of the AAVE token contract * @author Aave */ 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 override view 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 override view 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 override view 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 override view 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 virtual view 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 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 memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.7.5; import {IERC20} from './IERC20.sol'; /** * @dev Interface for ERC20 including metadata **/ interface IERC20Detailed is IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); }
// SPDX-License-Identifier: agpl-3.0 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 virtual view 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 virtual view 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 virtual view returns (uint256); /** * @dev returns the total supply at a certain block number **/ function totalSupplyAt(uint256 blockNumber) external virtual view returns (uint256); }
{ "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"}],"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":"PRECISION","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"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
61016060405260006009553480156200001757600080fd5b5060405162003dce38038062003dce8339810160408190526200003a9162000299565b868686868686866040518060400160405280600b81526020016a5374616b6564204c79726160a81b8152506040518060400160405280600781526020016673746b4c59524160c81b8152506012600085856001600160801b031685858160039080519060200190620000ae929190620001ed565b508051620000c4906004906020840190620001ed565b505060058054601260ff1990911617905550620000ee428262000175602090811b6200199e17901c565b60805250606090811b6001600160601b031990811660a0528c821b811660c0528b821b811660e0526101008b90526101208a90529088901b1661014052600880546001600160a01b0319166001600160a01b0383161790556200015d82620001d7602090811b620019f817901c565b5050505050505050505050505050505050506200034f565b600082820183811015620001d0576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6005805460ff191660ff92909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928262000225576000855562000270565b82601f106200024057805160ff191683800117855562000270565b8280016001018555821562000270579182015b828111156200027057825182559160200191906001019062000253565b506200027e92915062000282565b5090565b5b808211156200027e576000815560010162000283565b600080600080600080600060e0888a031215620002b4578283fd5b8751620002c18162000336565b6020890151909750620002d48162000336565b8096505060408801519450606088015193506080880151620002f68162000336565b60a0890151909350620003098162000336565b60c08901519092506001600160801b038116811462000326578182fd5b8091505092959891949750929550565b6001600160a01b03811681146200034c57600080fd5b50565b60805160a05160601c60c05160601c60e05160601c61010051610120516101405160601c6139de620003f060003980610d945280610eec52508061087c5280610ad4528061175b52508061083852806108a45280610bfd5280611780525080610e235280610ec25250806109505280610a7752806111025250806111785280611510525080610d705280612ce45280612d205280612d4d52506139de6000f3fe608060405234801561001057600080fd5b50600436106102d65760003560e01c8063919cd40f11610182578063b2f4201d116100e9578063d505accf116100a2578063dde43cba1161007c578063dde43cba146105ce578063f11b8188146105d6578063f1cc432a146105f8578063f713d8a81461060b576102d6565b8063d505accf14610595578063dc937e1c146105a8578063dd62ed3e146105bb576102d6565b8063b2f4201d14610539578063b9844d8d1461054c578063c2ffbb911461055f578063c3863ada14610572578063c3cda5201461057a578063cbcbb5071461058d576102d6565b8063a457c2d71161013b578063a457c2d7146104dd578063a9059cbb146104f0578063aa9fbe0214610503578063aaf5eb681461050b578063adc9772e14610513578063b2a5dbfa14610526576102d6565b8063919cd40f14610497578063946776cd1461049f57806395d89b41146104a7578063981b24d0146104af57806399248ea7146104c25780639a99b4f0146104ca576102d6565b80633644e5151161024157806370a08231116101fa578063787a08a6116101d4578063787a08a6146104565780637bb73c971461045e5780637e90d7ef146104715780638dbefee214610484576102d6565b806370a082311461043357806372b49d6314610446578063781603761461044e576102d6565b80633644e515146103c957806339509351146103d157806341cbf54a146103e45780635b3cc0cf146103ec5780635c19a95c1461040d5780636f50458d14610420576102d6565b806323b872dd1161029357806323b872dd1461036957806330adf81f1461037c578063312f6b8314610384578063313ce567146103995780633373ee4c146103ae578063359c4a96146103c1576102d6565b806306fdde03146102db578063091030c3146102f9578063095ea7b3146103195780631624f6c61461033957806318160ddd1461034e5780631e9a695014610356575b600080fd5b6102e361061e565b6040516102f091906135da565b60405180910390f35b61030c6103073660046130d3565b6106b4565b6040516102f09190613503565b61032c61032736600461321d565b6106c6565b6040516102f091906134f8565b61034c610347366004613348565b6106e4565b005b61030c6107f6565b61034c61036436600461321d565b6107fc565b61032c61037736600461311f565b6109c9565b61030c610a51565b61038c610a75565b6040516102f091906134a7565b6103a1610a99565b6040516102f091906137dd565b61030c6103bc3660046130ed565b610aa2565b61030c610ad2565b61030c610af6565b61032c6103df36600461321d565b610afc565b61030c610b4a565b6103ff6103fa36600461321d565b610b6e565b6040516102f092919061379f565b61034c61041b3660046130d3565b610b9f565b61038c61042e3660046131c3565b610bba565b61030c6104413660046130d3565b610bdc565b61030c610bfb565b6102e3610c1f565b61034c610c3c565b61030c61046c3660046130d3565b610c9b565b61030c61047f3660046130d3565b610cad565b61030c6104923660046130d3565b610cbf565b61030c610d6e565b61038c610d92565b6102e3610db6565b61030c6104bd3660046133ed565b610e17565b61038c610e21565b61034c6104d836600461321d565b610e45565b61032c6104eb36600461321d565b610f63565b61032c6104fe36600461321d565b610fcb565b61030c610fdf565b6103a1611003565b61034c61052136600461321d565b611008565b61034c6105343660046132d8565b61116d565b61030c6105473660046131c3565b611320565b61030c61055a3660046130d3565b611348565b61030c61056d366004613246565b61135a565b61038c611383565b61034c610588366004613281565b611392565b61038c61150e565b61034c6105a336600461315a565b611532565b61034c6105b63660046131c3565b6116bf565b61030c6105c93660046130ed565b6116ce565b61030c6116f9565b6105e96105e43660046130d3565b6116fe565b6040516102f0939291906137b9565b61030c610606366004613405565b61172c565b61034c6106193660046131ec565b611821565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106aa5780601f1061067f576101008083540402835291602001916106aa565b820191906000526020600020905b81548152906001019060200180831161068d57829003601f168201915b5050505050905090565b603e6020526000908152604090205481565b60006106da6106d3611a0e565b8484611a12565b5060015b92915050565b60006106ee611afe565b905060095481116107305760405162461bcd60e51b815260040180806020018281038252602e8152602001806138c2602e913960400191505060405180910390fd5b6009819055467f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61075f61061e565b805160209182012060408051808201825260018152603160f81b90840152516107af93927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6918691309101613590565b60408051601f1981840301815291905280516020909101206043556107d660038888612f73565b506107e360048686612f73565b506107ed836119f8565b50505050505050565b60025490565b806108225760405162461bcd60e51b8152600401610819906135ed565b60405180910390fd5b336000908152603e602052604090205461085c817f000000000000000000000000000000000000000000000000000000000000000061199e565b421161087a5760405162461bcd60e51b815260040161081990613645565b7f00000000000000000000000000000000000000000000000000000000000000006108cf6108c8837f000000000000000000000000000000000000000000000000000000000000000061199e565b4290611b03565b11156108ed5760405162461bcd60e51b81526004016108199061371d565b60006108f833610bdc565b90506000818411610909578361090b565b815b905061091933836001611b45565b506109243382611be9565b61092e8282611b03565b61094357336000908152603e60205260408120555b6109776001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168683611ce5565b846001600160a01b0316336001600160a01b03167fd12200efa34901b99367694174c3b0d32c99585fdf37c7c26892136ddd0836d9836040516109ba9190613503565b60405180910390a35050505050565b60006109d6848484611d37565b610a46846109e2611a0e565b610a418560405180606001604052806028815260200161389a602891396001600160a01b038a16600090815260016020526040812090610a20611a0e565b6001600160a01b031681526020810191909152604001600020549190611e03565b611a12565b5060015b9392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055460ff1690565b6001600160a01b038082166000908152603c60209081526040808320938616835260029093019052205492915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60435481565b60006106da610b09611a0e565b84610a418560016000610b1a611a0e565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061199e565b7f9a9a49b990ba9bb39f8048c490a40ab25c18f55d208d5fbcf958261a9b48716d81565b60066020908152600092835260408084209091529082529020546001600160801b0380821691600160801b90041682565b610bab33826000611e9a565b610bb733826001611e9a565b50565b600080610bc683611fab565b92505050610bd48482611fe5565b949350505050565b6001600160a01b0381166000908152602081905260409020545b919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b604051806040016040528060018152602001603160f81b81525081565b610c4533610bdc565b610c615760405162461bcd60e51b815260040161081990613754565b336000818152603e6020526040808220429055517ff52f50426b32362d3e6bb8cb36b7074756b224622def6352a59eac7f66ebe6e89190a2565b60076020526000908152604090205481565b603d6020526000908152604090205481565b60408051600180825281830190925260009160609190816020015b610ce2612fff565b815260200190600190039081610cda5790505090506040518060600160405280306001600160a01b03168152602001610d1a85610bdc565b8152602001610d276107f6565b81525081600081518110610d3757fe5b6020026020010181905250610a4a610d4f8483612010565b6001600160a01b0385166000908152603d60205260409020549061199e565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106aa5780601f1061067f576101008083540402835291602001916106aa565b60006106de6107f6565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610e5b33610e5433610bdc565b6000611b45565b905060006000198314610e6e5782610e70565b815b9050610ead816040518060400160405280600e81526020016d1253959053125117d05353d5539560921b81525084611e039092919063ffffffff16565b336000908152603d6020526040902055610f127f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000008684612101565b836001600160a01b0316336001600160a01b03167f9310ccfcb8de723f578a9e4282ea9f521f05ae40dc08f3068dfad528a65ee3c783604051610f559190613503565b60405180910390a350505050565b60006106da610f70611a0e565b84610a41856040518060600160405280602581526020016139846025913960016000610f9a611a0e565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611e03565b60006106da610fd8611a0e565b8484611d37565b7f10d8d059343739efce7dad10d09f0806da52b252b3e6a7951920d2d6ec4102e581565b601281565b806110255760405162461bcd60e51b8152600401610819906135ed565b600061103083610bdc565b905060006110478430846110426107f6565b61215b565b905080156110c5577f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a7684826040516110809291906134df565b60405180910390a16001600160a01b0384166000908152603d60205260409020546110ab908261199e565b6001600160a01b0385166000908152603d60205260409020555b6110d2600084868561172c565b6001600160a01b0385166000908152603e60205260409020556110f5848461221a565b61112a6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086612101565b836001600160a01b0316336001600160a01b03167f5dac0c1b1112564a045ba943c9d50270893e8e826c49be8e7073adc713ab7bd785604051610f559190613503565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146111b55760405162461bcd60e51b8152600401610819906136c7565b60005b8181101561131b576000603c60008585858181106111d257fe5b90506060020160400160208101906111ea91906130d3565b6001600160a01b03166001600160a01b03168152602001908152602001600020905061124f84848481811061121b57fe5b905060600201604001602081019061123391906130d3565b8286868681811061124057fe5b9050606002016020013561230a565b5083838381811061125c57fe5b61127292602060609092020190810191506133c6565b81546001600160801b0319166001600160801b039190911617815583838381811061129957fe5b90506060020160400160208101906112b191906130d3565b6001600160a01b03167f87fa03892a0556cb6b8f97e6d533a150d4d55fcbf275fff5fa003fa636bcc7fa8585858181106112e757fe5b6112fd92602060609092020190810191506133c6565b60405161130a919061378b565b60405180910390a2506001016111b8565b505050565b600080600061132e84611fab565b509150915061133f828287436123c7565b95945050505050565b60446020526000908152604090205481565b600080600061136884611fab565b5091509150611379828288886123c7565b9695505050505050565b6008546001600160a01b031681565b60007f9a9a49b990ba9bb39f8048c490a40ab25c18f55d208d5fbcf958261a9b48716d8787876040516020016113cb9493929190613540565b6040516020818303038152906040528051906020012090506000604354826040516020016113fa92919061348c565b60405160208183030381529060405280519060200120905060006001828787876040516000815260200160405260405161143794939291906135bc565b6020604051602081039080840390855afa158015611459573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661148c5760405162461bcd60e51b81526004016108199061361a565b6001600160a01b038116600090815260446020526040902080546001810190915588146114cb5760405162461bcd60e51b8152600401610819906136a0565b864211156114eb5760405162461bcd60e51b815260040161081990613674565b6114f7818a6000611e9a565b611503818a6001611e9a565b505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b0387166115585760405162461bcd60e51b8152600401610819906136f6565b834211156115785760405162461bcd60e51b815260040161081990613674565b6001600160a01b03871660009081526044602090815260408083205460435491519093926115d2917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918d918d918d9189918e910161350c565b604051602081830303815290604052805190602001206040516020016115f992919061348c565b6040516020818303038152906040528051906020012090506001818686866040516000815260200160405260405161163494939291906135bc565b6020604051602081039080840390855afa158015611656573d6000803e3d6000fd5b505050602060405103516001600160a01b0316896001600160a01b0316146116905760405162461bcd60e51b81526004016108199061361a565b61169b82600161199e565b6001600160a01b038a16600090815260446020526040902055611503898989611a12565b6116ca338383611e9a565b5050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600181565b603c60205260009081526040902080546001909101546001600160801b0380831692600160801b9004169083565b6001600160a01b0382166000908152603e602052604081205480611754576000915050610bd4565b60006117aa7f00000000000000000000000000000000000000000000000000000000000000006117a4427f0000000000000000000000000000000000000000000000000000000000000000611b03565b90611b03565b9050818111156117bd5760009150611817565b60008782116117cc57876117ce565b425b9050828110156117e357829350505050610bd4565b6118136117f0888761199e565b61180d6117fd88876125e3565b6118078b866125e3565b9061199e565b9061263c565b9250505b5095945050505050565b60007f10d8d059343739efce7dad10d09f0806da52b252b3e6a7951920d2d6ec4102e58888600181111561185157fe5b8888604051602001611867959493929190613564565b60405160208183030381529060405280519060200120905060006043548260405160200161189692919061348c565b6040516020818303038152906040528051906020012090506000600182878787604051600081526020016040526040516118d394939291906135bc565b6020604051602081039080840390855afa1580156118f5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166119285760405162461bcd60e51b81526004016108199061361a565b6001600160a01b038116600090815260446020526040902080546001810190915588146119675760405162461bcd60e51b8152600401610819906136a0565b864211156119875760405162461bcd60e51b815260040161081990613674565b611992818b8b611e9a565b50505050505050505050565b600082820183811015610a4a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6005805460ff191660ff92909216919091179055565b3390565b6001600160a01b038316611a575760405162461bcd60e51b81526004018080602001828103825260248152602001806139366024913960400191505060405180910390fd5b6001600160a01b038216611a9c5760405162461bcd60e51b81526004018080602001828103825260228152602001806138316022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600190565b6000610a4a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611e03565b600080611b568530866110426107f6565b6001600160a01b0386166000908152603d602052604081205491925090611b7d908361199e565b9050811561133f578315611ba7576001600160a01b0386166000908152603d602052604090208190555b7f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a768683604051611bd89291906134df565b60405180910390a195945050505050565b6001600160a01b038216611c2e5760405162461bcd60e51b81526004018080602001828103825260218152602001806138f06021913960400191505060405180910390fd5b611c3a8260008361267e565b611c778160405180606001604052806022815260200161380f602291396001600160a01b0385166000908152602081905260409020549190611e03565b6001600160a01b038316600090815260208190526040902055600254611c9d9082611b03565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261131b90849061279b565b6000611d4284610bdc565b9050611d5084826001611b45565b50826001600160a01b0316846001600160a01b031614611df2576000611d7584610bdc565b9050611d8384826001611b45565b506001600160a01b0385166000908152603e6020526040902054611da98185878561172c565b6001600160a01b0386166000908152603e60205260409020558284148015611dd057508015155b15611def576001600160a01b0386166000908152603e60205260408120555b50505b611dfd848484612953565b50505050565b60008184841115611e925760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611e57578181015183820152602001611e3f565b50505050905090810190601f168015611e845780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038216611ee9576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f44454c45474154454560781b604482015290519081900360640190fd5b6000611ef482611fab565b925050506000611f0385610bdc565b90506000611f118684611fe5565b6001600160a01b03878116600090815260208690526040902080546001600160a01b0319169188169190911790559050611f4d81868487612aae565b846001600160a01b0316866001600160a01b03167fe8d51c8e11bd570db1734c8ec775785330e77007feed45c43b608ef33ff914bd8660405180826001811115611f9357fe5b815260200191505060405180910390a3505050505050565b6000808080846001811115611fbc57fe5b1415611fd257506006915060079050603f611fde565b50604091506041905060425b9193909250565b6001600160a01b0380831660009081526020839052604081205490911680610a4a57839150506106de565b600080805b83518110156120f9576000603c600086848151811061203057fe5b602090810291909101810151516001600160a01b031682528101919091526040016000908120600181015481548851929450612098926001600160801b0380831692600160801b900416908a908890811061208757fe5b602002602001015160400151612cbc565b90506120ed6120e68785815181106120ac57fe5b602002602001015160200151838560020160008c6001600160a01b03166001600160a01b0316815260200190815260200160002054612db5565b859061199e565b93505050600101612015565b509392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611dfd90859061279b565b6001600160a01b038084166000908152603c60209081526040808320938816835260028401909152812054909190828061219688858861230a565b905080831461220e5786156121b3576121b0878285612db5565b91505b6001600160a01b03808a1660008181526002870160205260409081902084905551918a16917fbb123b5c06d5408bbea3c4fef481578175cfb432e3b482c6186f02ed9086585b90612205908590613503565b60405180910390a35b50979650505050505050565b6001600160a01b038216612275576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6122816000838361267e565b60025461228e908261199e565b6002556001600160a01b0382166000908152602081905260409020546122b4908261199e565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001820154825460009190600160801b90046001600160801b03164281141561233557509050610a4a565b84546000906123509084906001600160801b03168488612cbc565b90508281146123a457808660010181905550866001600160a01b03167f5777ca300dfe5bead41006fbce4389794dbc0ed8d6cccebfaf94630aa04184bc8260405161239b9190613503565b60405180910390a25b85546001600160801b03428116600160801b029116178655925050509392505050565b600043821115612415576040805162461bcd60e51b815260206004820152601460248201527324a72b20a624a22fa12627a1a5afa72aa6a122a960611b604482015290519081900360640190fd5b6001600160a01b038316600090815260208590526040902054806124445761243c84610bdc565b915050610bd4565b6001600160a01b038416600090815260208781526040808320600019850184529091529020546001600160801b031683106124b7576001600160a01b038416600090815260208781526040808320600019909401835292905220546001600160801b03600160801b909104169050610bd4565b6001600160a01b0384166000908152602087815260408083208380529091529020546001600160801b03168310156124f3576000915050610bd4565b600060001982015b818111156125a5576002828203048103612513613029565b506001600160a01b038716600090815260208a815260408083208484528252918290208251808401909352546001600160801b03808216808552600160801b909204169183019190915287141561257d57602001516001600160801b03169450610bd49350505050565b80516001600160801b03168711156125975781935061259e565b6001820392505b50506124fb565b506001600160a01b03851660009081526020888152604080832093835292905220546001600160801b03600160801b90910416915050949350505050565b6000826125f2575060006106de565b828202828482816125ff57fe5b0414610a4a5760405162461bcd60e51b81526004018080602001828103825260218152602001806138796021913960400191505060405180910390fd5b6000610a4a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612dd7565b6001600160a01b038084166000908152603f60205260408082205485841683529120549082169116816126af578491505b6001600160a01b0381166126c05750825b6126cd8282856000612aae565b6001600160a01b038086166000908152604260205260408082205487841683529120549082169116816126fe578691505b6001600160a01b03811661270f5750845b61271c8282876001612aae565b6008546001600160a01b0316801561279157604051634a39314960e01b81526001600160a01b03821690634a3931499061275e908b908b908b906004016134bb565b600060405180830381600087803b15801561277857600080fd5b505af115801561278c573d6000803e3d6000fd5b505050505b5050505050505050565b6127ad826001600160a01b0316612e3c565b6127fe576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b6020831061283c5780518252601f19909201916020918201910161281d565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461289e576040519150601f19603f3d011682016040523d82523d6000602084013e6128a3565b606091505b5091509150816128fa576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611dfd5780806020019051602081101561291657600080fd5b5051611dfd5760405162461bcd60e51b815260040180806020018281038252602a81526020018061395a602a913960400191505060405180910390fd5b6001600160a01b0383166129985760405162461bcd60e51b81526004018080602001828103825260258152602001806139116025913960400191505060405180910390fd5b6001600160a01b0382166129dd5760405162461bcd60e51b81526004018080602001828103825260238152602001806137ec6023913960400191505060405180910390fd5b6129e883838361267e565b612a2581604051806060016040528060268152602001613853602691396001600160a01b0386166000908152602081905260409020549190611e03565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612a54908261199e565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b826001600160a01b0316846001600160a01b03161415612acd57611dfd565b600080612ad983611fab565b5090925090506001600160a01b03861615612bcc576001600160a01b0386166000908152602082905260408120548015612b4a576001600160a01b03881660009081526020858152604080832060001985018452909152902054600160801b90046001600160801b03169150612b56565b612b5388610bdc565b91505b612b6c84848a85612b67818c611b03565b612e75565b6001600160a01b0388167fa0a19463ee116110c9b282012d9b65cc5522dc38a9520340cbaf3142e550127f612ba18489611b03565b8760405180838152602001826001811115612bb857fe5b81526020019250505060405180910390a250505b6001600160a01b03851615612cb4576001600160a01b0385166000908152602082905260408120548015612c37576001600160a01b03871660009081526020858152604080832060001985018452909152902054600160801b90046001600160801b03169150612c43565b612c4087610bdc565b91505b612c5484848985612b67818c61199e565b6001600160a01b0387167fa0a19463ee116110c9b282012d9b65cc5522dc38a9520340cbaf3142e550127f612c89848961199e565b8760405180838152602001826001811115612ca057fe5b81526020019250505060405180910390a250505b505050505050565b6000831580612cc9575081155b80612cdc575042836001600160801b0316145b80612d1057507f0000000000000000000000000000000000000000000000000000000000000000836001600160801b031610155b15612d1c575083610bd4565b60007f00000000000000000000000000000000000000000000000000000000000000004211612d4b5742612d6d565b7f00000000000000000000000000000000000000000000000000000000000000005b90506000612d84826001600160801b038716611b03565b9050612daa876118078661180d670de0b6b3a7640000612da48c886125e3565b906125e3565b979650505050505050565b6000610bd4670de0b6b3a764000061180d612dd08686611b03565b87906125e3565b60008183612e265760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611e57578181015183820152602001611e3f565b506000838581612e3257fe5b0495945050505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610bd4575050151592915050565b6001600160a01b03831660009081526020858152604080832054918890529091204391908115801590612ec6575060001982016000908152602082905260409020546001600160801b038481169116145b15612efb576000198201600090815260208290526040902080546001600160801b03808716600160801b029116179055612791565b6040805180820182526001600160801b038086168252868116602080840191825260008781528682528581209451855493518516600160801b029085166001600160801b031990941693909317909316919091179092556001600160a01b038916815290899052206001830190555050505050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282612fa95760008555612fef565b82601f10612fc25782800160ff19823516178555612fef565b82800160010185558215612fef579182015b82811115612fef578235825591602001919060010190612fd4565b50612ffb929150613040565b5090565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b604080518082019091526000808252602082015290565b5b80821115612ffb5760008155600101613041565b80356001600160a01b0381168114610bf657600080fd5b803560028110610bf657600080fd5b60008083601f84011261308c578182fd5b50813567ffffffffffffffff8111156130a3578182fd5b6020830191508360208285010111156130bb57600080fd5b9250929050565b803560ff81168114610bf657600080fd5b6000602082840312156130e4578081fd5b610a4a82613055565b600080604083850312156130ff578081fd5b61310883613055565b915061311660208401613055565b90509250929050565b600080600060608486031215613133578081fd5b61313c84613055565b925061314a60208501613055565b9150604084013590509250925092565b600080600080600080600060e0888a031215613174578283fd5b61317d88613055565b965061318b60208901613055565b955060408801359450606088013593506131a7608089016130c2565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156131d5578182fd5b6131de83613055565b91506131166020840161306c565b600080600080600080600060e0888a031215613206578283fd5b61320f88613055565b965061318b6020890161306c565b6000806040838503121561322f578182fd5b61323883613055565b946020939093013593505050565b60008060006060848603121561325a578283fd5b61326384613055565b9250602084013591506132786040850161306c565b90509250925092565b60008060008060008060c08789031215613299578182fd5b6132a287613055565b955060208701359450604087013593506132be606088016130c2565b92506080870135915060a087013590509295509295509295565b600080602083850312156132ea578081fd5b823567ffffffffffffffff80821115613301578283fd5b818501915085601f830112613314578283fd5b813581811115613322578384fd5b866020606083028501011115613336578384fd5b60209290920196919550909350505050565b60008060008060006060868803121561335f578283fd5b853567ffffffffffffffff80821115613376578485fd5b61338289838a0161307b565b9097509550602088013591508082111561339a578485fd5b506133a78882890161307b565b90945092506133ba9050604087016130c2565b90509295509295909350565b6000602082840312156133d7578081fd5b81356001600160801b0381168114610a4a578182fd5b6000602082840312156133fe578081fd5b5035919050565b6000806000806080858703121561341a578182fd5b843593506020850135925061343160408601613055565b9396929550929360600135925050565b60008151808452815b818110156134665760208185018101518683018201520161344a565b818111156134775782602083870101525b50601f01601f19169290920160200192915050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b9485526001600160a01b0393909316602085015260408401919091526060830152608082015260a00190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b93845260ff9290921660208401526040830152606082015260800190565b600060208252610a4a6020830184613441565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260119082015270494e56414c49445f5349474e415455524560781b604082015260600190565b60208082526015908201527424a729aaa32324a1a4a2a72a2fa1a7a7a62227aba760591b604082015260600190565b60208082526012908201527124a72b20a624a22fa2ac2824a920aa24a7a760711b604082015260600190565b6020808252600d908201526c494e56414c49445f4e4f4e434560981b604082015260600190565b60208082526015908201527427a7262cafa2a6a4a9a9a4a7a72fa6a0a720a3a2a960591b604082015260600190565b6020808252600d908201526c24a72b20a624a22fa7aba722a960991b604082015260600190565b60208082526017908201527f554e5354414b455f57494e444f575f46494e4953484544000000000000000000604082015260600190565b6020808252601b908201527f494e56414c49445f42414c414e43455f4f4e5f434f4f4c444f574e0000000000604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b039384168152919092166020820152604081019190915260600190565b60ff9190911681526020019056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200c4f0888820d9e117b76e7a1a597eb3afa35dc8ba043094cd2cad6dfa1967c3f64736f6c6343000705003300000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf00000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000000002a3000000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a190000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a1900000000000000000000000000000000000000000000000000000000bbf81e00
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102d65760003560e01c8063919cd40f11610182578063b2f4201d116100e9578063d505accf116100a2578063dde43cba1161007c578063dde43cba146105ce578063f11b8188146105d6578063f1cc432a146105f8578063f713d8a81461060b576102d6565b8063d505accf14610595578063dc937e1c146105a8578063dd62ed3e146105bb576102d6565b8063b2f4201d14610539578063b9844d8d1461054c578063c2ffbb911461055f578063c3863ada14610572578063c3cda5201461057a578063cbcbb5071461058d576102d6565b8063a457c2d71161013b578063a457c2d7146104dd578063a9059cbb146104f0578063aa9fbe0214610503578063aaf5eb681461050b578063adc9772e14610513578063b2a5dbfa14610526576102d6565b8063919cd40f14610497578063946776cd1461049f57806395d89b41146104a7578063981b24d0146104af57806399248ea7146104c25780639a99b4f0146104ca576102d6565b80633644e5151161024157806370a08231116101fa578063787a08a6116101d4578063787a08a6146104565780637bb73c971461045e5780637e90d7ef146104715780638dbefee214610484576102d6565b806370a082311461043357806372b49d6314610446578063781603761461044e576102d6565b80633644e515146103c957806339509351146103d157806341cbf54a146103e45780635b3cc0cf146103ec5780635c19a95c1461040d5780636f50458d14610420576102d6565b806323b872dd1161029357806323b872dd1461036957806330adf81f1461037c578063312f6b8314610384578063313ce567146103995780633373ee4c146103ae578063359c4a96146103c1576102d6565b806306fdde03146102db578063091030c3146102f9578063095ea7b3146103195780631624f6c61461033957806318160ddd1461034e5780631e9a695014610356575b600080fd5b6102e361061e565b6040516102f091906135da565b60405180910390f35b61030c6103073660046130d3565b6106b4565b6040516102f09190613503565b61032c61032736600461321d565b6106c6565b6040516102f091906134f8565b61034c610347366004613348565b6106e4565b005b61030c6107f6565b61034c61036436600461321d565b6107fc565b61032c61037736600461311f565b6109c9565b61030c610a51565b61038c610a75565b6040516102f091906134a7565b6103a1610a99565b6040516102f091906137dd565b61030c6103bc3660046130ed565b610aa2565b61030c610ad2565b61030c610af6565b61032c6103df36600461321d565b610afc565b61030c610b4a565b6103ff6103fa36600461321d565b610b6e565b6040516102f092919061379f565b61034c61041b3660046130d3565b610b9f565b61038c61042e3660046131c3565b610bba565b61030c6104413660046130d3565b610bdc565b61030c610bfb565b6102e3610c1f565b61034c610c3c565b61030c61046c3660046130d3565b610c9b565b61030c61047f3660046130d3565b610cad565b61030c6104923660046130d3565b610cbf565b61030c610d6e565b61038c610d92565b6102e3610db6565b61030c6104bd3660046133ed565b610e17565b61038c610e21565b61034c6104d836600461321d565b610e45565b61032c6104eb36600461321d565b610f63565b61032c6104fe36600461321d565b610fcb565b61030c610fdf565b6103a1611003565b61034c61052136600461321d565b611008565b61034c6105343660046132d8565b61116d565b61030c6105473660046131c3565b611320565b61030c61055a3660046130d3565b611348565b61030c61056d366004613246565b61135a565b61038c611383565b61034c610588366004613281565b611392565b61038c61150e565b61034c6105a336600461315a565b611532565b61034c6105b63660046131c3565b6116bf565b61030c6105c93660046130ed565b6116ce565b61030c6116f9565b6105e96105e43660046130d3565b6116fe565b6040516102f0939291906137b9565b61030c610606366004613405565b61172c565b61034c6106193660046131ec565b611821565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106aa5780601f1061067f576101008083540402835291602001916106aa565b820191906000526020600020905b81548152906001019060200180831161068d57829003601f168201915b5050505050905090565b603e6020526000908152604090205481565b60006106da6106d3611a0e565b8484611a12565b5060015b92915050565b60006106ee611afe565b905060095481116107305760405162461bcd60e51b815260040180806020018281038252602e8152602001806138c2602e913960400191505060405180910390fd5b6009819055467f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61075f61061e565b805160209182012060408051808201825260018152603160f81b90840152516107af93927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6918691309101613590565b60408051601f1981840301815291905280516020909101206043556107d660038888612f73565b506107e360048686612f73565b506107ed836119f8565b50505050505050565b60025490565b806108225760405162461bcd60e51b8152600401610819906135ed565b60405180910390fd5b336000908152603e602052604090205461085c817f00000000000000000000000000000000000000000000000000000000000d2f0061199e565b421161087a5760405162461bcd60e51b815260040161081990613645565b7f000000000000000000000000000000000000000000000000000000000002a3006108cf6108c8837f00000000000000000000000000000000000000000000000000000000000d2f0061199e565b4290611b03565b11156108ed5760405162461bcd60e51b81526004016108199061371d565b60006108f833610bdc565b90506000818411610909578361090b565b815b905061091933836001611b45565b506109243382611be9565b61092e8282611b03565b61094357336000908152603e60205260408120555b6109776001600160a01b037f00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf168683611ce5565b846001600160a01b0316336001600160a01b03167fd12200efa34901b99367694174c3b0d32c99585fdf37c7c26892136ddd0836d9836040516109ba9190613503565b60405180910390a35050505050565b60006109d6848484611d37565b610a46846109e2611a0e565b610a418560405180606001604052806028815260200161389a602891396001600160a01b038a16600090815260016020526040812090610a20611a0e565b6001600160a01b031681526020810191909152604001600020549190611e03565b611a12565b5060015b9392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b7f00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf81565b60055460ff1690565b6001600160a01b038082166000908152603c60209081526040808320938616835260029093019052205492915050565b7f000000000000000000000000000000000000000000000000000000000002a30081565b60435481565b60006106da610b09611a0e565b84610a418560016000610b1a611a0e565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061199e565b7f9a9a49b990ba9bb39f8048c490a40ab25c18f55d208d5fbcf958261a9b48716d81565b60066020908152600092835260408084209091529082529020546001600160801b0380821691600160801b90041682565b610bab33826000611e9a565b610bb733826001611e9a565b50565b600080610bc683611fab565b92505050610bd48482611fe5565b949350505050565b6001600160a01b0381166000908152602081905260409020545b919050565b7f00000000000000000000000000000000000000000000000000000000000d2f0081565b604051806040016040528060018152602001603160f81b81525081565b610c4533610bdc565b610c615760405162461bcd60e51b815260040161081990613754565b336000818152603e6020526040808220429055517ff52f50426b32362d3e6bb8cb36b7074756b224622def6352a59eac7f66ebe6e89190a2565b60076020526000908152604090205481565b603d6020526000908152604090205481565b60408051600180825281830190925260009160609190816020015b610ce2612fff565b815260200190600190039081610cda5790505090506040518060600160405280306001600160a01b03168152602001610d1a85610bdc565b8152602001610d276107f6565b81525081600081518110610d3757fe5b6020026020010181905250610a4a610d4f8483612010565b6001600160a01b0385166000908152603d60205260409020549061199e565b7f000000000000000000000000000000000000000000000000000000011dc6e98e81565b7f0000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a1981565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106aa5780601f1061067f576101008083540402835291602001916106aa565b60006106de6107f6565b7f00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf81565b6000610e5b33610e5433610bdc565b6000611b45565b905060006000198314610e6e5782610e70565b815b9050610ead816040518060400160405280600e81526020016d1253959053125117d05353d5539560921b81525084611e039092919063ffffffff16565b336000908152603d6020526040902055610f127f00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf6001600160a01b03167f0000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a198684612101565b836001600160a01b0316336001600160a01b03167f9310ccfcb8de723f578a9e4282ea9f521f05ae40dc08f3068dfad528a65ee3c783604051610f559190613503565b60405180910390a350505050565b60006106da610f70611a0e565b84610a41856040518060600160405280602581526020016139846025913960016000610f9a611a0e565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611e03565b60006106da610fd8611a0e565b8484611d37565b7f10d8d059343739efce7dad10d09f0806da52b252b3e6a7951920d2d6ec4102e581565b601281565b806110255760405162461bcd60e51b8152600401610819906135ed565b600061103083610bdc565b905060006110478430846110426107f6565b61215b565b905080156110c5577f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a7684826040516110809291906134df565b60405180910390a16001600160a01b0384166000908152603d60205260409020546110ab908261199e565b6001600160a01b0385166000908152603d60205260409020555b6110d2600084868561172c565b6001600160a01b0385166000908152603e60205260409020556110f5848461221a565b61112a6001600160a01b037f00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf16333086612101565b836001600160a01b0316336001600160a01b03167f5dac0c1b1112564a045ba943c9d50270893e8e826c49be8e7073adc713ab7bd785604051610f559190613503565b336001600160a01b037f0000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a1916146111b55760405162461bcd60e51b8152600401610819906136c7565b60005b8181101561131b576000603c60008585858181106111d257fe5b90506060020160400160208101906111ea91906130d3565b6001600160a01b03166001600160a01b03168152602001908152602001600020905061124f84848481811061121b57fe5b905060600201604001602081019061123391906130d3565b8286868681811061124057fe5b9050606002016020013561230a565b5083838381811061125c57fe5b61127292602060609092020190810191506133c6565b81546001600160801b0319166001600160801b039190911617815583838381811061129957fe5b90506060020160400160208101906112b191906130d3565b6001600160a01b03167f87fa03892a0556cb6b8f97e6d533a150d4d55fcbf275fff5fa003fa636bcc7fa8585858181106112e757fe5b6112fd92602060609092020190810191506133c6565b60405161130a919061378b565b60405180910390a2506001016111b8565b505050565b600080600061132e84611fab565b509150915061133f828287436123c7565b95945050505050565b60446020526000908152604090205481565b600080600061136884611fab565b5091509150611379828288886123c7565b9695505050505050565b6008546001600160a01b031681565b60007f9a9a49b990ba9bb39f8048c490a40ab25c18f55d208d5fbcf958261a9b48716d8787876040516020016113cb9493929190613540565b6040516020818303038152906040528051906020012090506000604354826040516020016113fa92919061348c565b60405160208183030381529060405280519060200120905060006001828787876040516000815260200160405260405161143794939291906135bc565b6020604051602081039080840390855afa158015611459573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661148c5760405162461bcd60e51b81526004016108199061361a565b6001600160a01b038116600090815260446020526040902080546001810190915588146114cb5760405162461bcd60e51b8152600401610819906136a0565b864211156114eb5760405162461bcd60e51b815260040161081990613674565b6114f7818a6000611e9a565b611503818a6001611e9a565b505050505050505050565b7f0000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a1981565b6001600160a01b0387166115585760405162461bcd60e51b8152600401610819906136f6565b834211156115785760405162461bcd60e51b815260040161081990613674565b6001600160a01b03871660009081526044602090815260408083205460435491519093926115d2917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918d918d918d9189918e910161350c565b604051602081830303815290604052805190602001206040516020016115f992919061348c565b6040516020818303038152906040528051906020012090506001818686866040516000815260200160405260405161163494939291906135bc565b6020604051602081039080840390855afa158015611656573d6000803e3d6000fd5b505050602060405103516001600160a01b0316896001600160a01b0316146116905760405162461bcd60e51b81526004016108199061361a565b61169b82600161199e565b6001600160a01b038a16600090815260446020526040902055611503898989611a12565b6116ca338383611e9a565b5050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600181565b603c60205260009081526040902080546001909101546001600160801b0380831692600160801b9004169083565b6001600160a01b0382166000908152603e602052604081205480611754576000915050610bd4565b60006117aa7f000000000000000000000000000000000000000000000000000000000002a3006117a4427f00000000000000000000000000000000000000000000000000000000000d2f00611b03565b90611b03565b9050818111156117bd5760009150611817565b60008782116117cc57876117ce565b425b9050828110156117e357829350505050610bd4565b6118136117f0888761199e565b61180d6117fd88876125e3565b6118078b866125e3565b9061199e565b9061263c565b9250505b5095945050505050565b60007f10d8d059343739efce7dad10d09f0806da52b252b3e6a7951920d2d6ec4102e58888600181111561185157fe5b8888604051602001611867959493929190613564565b60405160208183030381529060405280519060200120905060006043548260405160200161189692919061348c565b6040516020818303038152906040528051906020012090506000600182878787604051600081526020016040526040516118d394939291906135bc565b6020604051602081039080840390855afa1580156118f5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166119285760405162461bcd60e51b81526004016108199061361a565b6001600160a01b038116600090815260446020526040902080546001810190915588146119675760405162461bcd60e51b8152600401610819906136a0565b864211156119875760405162461bcd60e51b815260040161081990613674565b611992818b8b611e9a565b50505050505050505050565b600082820183811015610a4a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6005805460ff191660ff92909216919091179055565b3390565b6001600160a01b038316611a575760405162461bcd60e51b81526004018080602001828103825260248152602001806139366024913960400191505060405180910390fd5b6001600160a01b038216611a9c5760405162461bcd60e51b81526004018080602001828103825260228152602001806138316022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600190565b6000610a4a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611e03565b600080611b568530866110426107f6565b6001600160a01b0386166000908152603d602052604081205491925090611b7d908361199e565b9050811561133f578315611ba7576001600160a01b0386166000908152603d602052604090208190555b7f2468f9268c60ad90e2d49edb0032c8a001e733ae888b3ab8e982edf535be1a768683604051611bd89291906134df565b60405180910390a195945050505050565b6001600160a01b038216611c2e5760405162461bcd60e51b81526004018080602001828103825260218152602001806138f06021913960400191505060405180910390fd5b611c3a8260008361267e565b611c778160405180606001604052806022815260200161380f602291396001600160a01b0385166000908152602081905260409020549190611e03565b6001600160a01b038316600090815260208190526040902055600254611c9d9082611b03565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261131b90849061279b565b6000611d4284610bdc565b9050611d5084826001611b45565b50826001600160a01b0316846001600160a01b031614611df2576000611d7584610bdc565b9050611d8384826001611b45565b506001600160a01b0385166000908152603e6020526040902054611da98185878561172c565b6001600160a01b0386166000908152603e60205260409020558284148015611dd057508015155b15611def576001600160a01b0386166000908152603e60205260408120555b50505b611dfd848484612953565b50505050565b60008184841115611e925760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611e57578181015183820152602001611e3f565b50505050905090810190601f168015611e845780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038216611ee9576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f44454c45474154454560781b604482015290519081900360640190fd5b6000611ef482611fab565b925050506000611f0385610bdc565b90506000611f118684611fe5565b6001600160a01b03878116600090815260208690526040902080546001600160a01b0319169188169190911790559050611f4d81868487612aae565b846001600160a01b0316866001600160a01b03167fe8d51c8e11bd570db1734c8ec775785330e77007feed45c43b608ef33ff914bd8660405180826001811115611f9357fe5b815260200191505060405180910390a3505050505050565b6000808080846001811115611fbc57fe5b1415611fd257506006915060079050603f611fde565b50604091506041905060425b9193909250565b6001600160a01b0380831660009081526020839052604081205490911680610a4a57839150506106de565b600080805b83518110156120f9576000603c600086848151811061203057fe5b602090810291909101810151516001600160a01b031682528101919091526040016000908120600181015481548851929450612098926001600160801b0380831692600160801b900416908a908890811061208757fe5b602002602001015160400151612cbc565b90506120ed6120e68785815181106120ac57fe5b602002602001015160200151838560020160008c6001600160a01b03166001600160a01b0316815260200190815260200160002054612db5565b859061199e565b93505050600101612015565b509392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611dfd90859061279b565b6001600160a01b038084166000908152603c60209081526040808320938816835260028401909152812054909190828061219688858861230a565b905080831461220e5786156121b3576121b0878285612db5565b91505b6001600160a01b03808a1660008181526002870160205260409081902084905551918a16917fbb123b5c06d5408bbea3c4fef481578175cfb432e3b482c6186f02ed9086585b90612205908590613503565b60405180910390a35b50979650505050505050565b6001600160a01b038216612275576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6122816000838361267e565b60025461228e908261199e565b6002556001600160a01b0382166000908152602081905260409020546122b4908261199e565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001820154825460009190600160801b90046001600160801b03164281141561233557509050610a4a565b84546000906123509084906001600160801b03168488612cbc565b90508281146123a457808660010181905550866001600160a01b03167f5777ca300dfe5bead41006fbce4389794dbc0ed8d6cccebfaf94630aa04184bc8260405161239b9190613503565b60405180910390a25b85546001600160801b03428116600160801b029116178655925050509392505050565b600043821115612415576040805162461bcd60e51b815260206004820152601460248201527324a72b20a624a22fa12627a1a5afa72aa6a122a960611b604482015290519081900360640190fd5b6001600160a01b038316600090815260208590526040902054806124445761243c84610bdc565b915050610bd4565b6001600160a01b038416600090815260208781526040808320600019850184529091529020546001600160801b031683106124b7576001600160a01b038416600090815260208781526040808320600019909401835292905220546001600160801b03600160801b909104169050610bd4565b6001600160a01b0384166000908152602087815260408083208380529091529020546001600160801b03168310156124f3576000915050610bd4565b600060001982015b818111156125a5576002828203048103612513613029565b506001600160a01b038716600090815260208a815260408083208484528252918290208251808401909352546001600160801b03808216808552600160801b909204169183019190915287141561257d57602001516001600160801b03169450610bd49350505050565b80516001600160801b03168711156125975781935061259e565b6001820392505b50506124fb565b506001600160a01b03851660009081526020888152604080832093835292905220546001600160801b03600160801b90910416915050949350505050565b6000826125f2575060006106de565b828202828482816125ff57fe5b0414610a4a5760405162461bcd60e51b81526004018080602001828103825260218152602001806138796021913960400191505060405180910390fd5b6000610a4a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612dd7565b6001600160a01b038084166000908152603f60205260408082205485841683529120549082169116816126af578491505b6001600160a01b0381166126c05750825b6126cd8282856000612aae565b6001600160a01b038086166000908152604260205260408082205487841683529120549082169116816126fe578691505b6001600160a01b03811661270f5750845b61271c8282876001612aae565b6008546001600160a01b0316801561279157604051634a39314960e01b81526001600160a01b03821690634a3931499061275e908b908b908b906004016134bb565b600060405180830381600087803b15801561277857600080fd5b505af115801561278c573d6000803e3d6000fd5b505050505b5050505050505050565b6127ad826001600160a01b0316612e3c565b6127fe576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b6020831061283c5780518252601f19909201916020918201910161281d565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461289e576040519150601f19603f3d011682016040523d82523d6000602084013e6128a3565b606091505b5091509150816128fa576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611dfd5780806020019051602081101561291657600080fd5b5051611dfd5760405162461bcd60e51b815260040180806020018281038252602a81526020018061395a602a913960400191505060405180910390fd5b6001600160a01b0383166129985760405162461bcd60e51b81526004018080602001828103825260258152602001806139116025913960400191505060405180910390fd5b6001600160a01b0382166129dd5760405162461bcd60e51b81526004018080602001828103825260238152602001806137ec6023913960400191505060405180910390fd5b6129e883838361267e565b612a2581604051806060016040528060268152602001613853602691396001600160a01b0386166000908152602081905260409020549190611e03565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612a54908261199e565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b826001600160a01b0316846001600160a01b03161415612acd57611dfd565b600080612ad983611fab565b5090925090506001600160a01b03861615612bcc576001600160a01b0386166000908152602082905260408120548015612b4a576001600160a01b03881660009081526020858152604080832060001985018452909152902054600160801b90046001600160801b03169150612b56565b612b5388610bdc565b91505b612b6c84848a85612b67818c611b03565b612e75565b6001600160a01b0388167fa0a19463ee116110c9b282012d9b65cc5522dc38a9520340cbaf3142e550127f612ba18489611b03565b8760405180838152602001826001811115612bb857fe5b81526020019250505060405180910390a250505b6001600160a01b03851615612cb4576001600160a01b0385166000908152602082905260408120548015612c37576001600160a01b03871660009081526020858152604080832060001985018452909152902054600160801b90046001600160801b03169150612c43565b612c4087610bdc565b91505b612c5484848985612b67818c61199e565b6001600160a01b0387167fa0a19463ee116110c9b282012d9b65cc5522dc38a9520340cbaf3142e550127f612c89848961199e565b8760405180838152602001826001811115612ca057fe5b81526020019250505060405180910390a250505b505050505050565b6000831580612cc9575081155b80612cdc575042836001600160801b0316145b80612d1057507f000000000000000000000000000000000000000000000000000000011dc6e98e836001600160801b031610155b15612d1c575083610bd4565b60007f000000000000000000000000000000000000000000000000000000011dc6e98e4211612d4b5742612d6d565b7f000000000000000000000000000000000000000000000000000000011dc6e98e5b90506000612d84826001600160801b038716611b03565b9050612daa876118078661180d670de0b6b3a7640000612da48c886125e3565b906125e3565b979650505050505050565b6000610bd4670de0b6b3a764000061180d612dd08686611b03565b87906125e3565b60008183612e265760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611e57578181015183820152602001611e3f565b506000838581612e3257fe5b0495945050505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610bd4575050151592915050565b6001600160a01b03831660009081526020858152604080832054918890529091204391908115801590612ec6575060001982016000908152602082905260409020546001600160801b038481169116145b15612efb576000198201600090815260208290526040902080546001600160801b03808716600160801b029116179055612791565b6040805180820182526001600160801b038086168252868116602080840191825260008781528682528581209451855493518516600160801b029085166001600160801b031990941693909317909316919091179092556001600160a01b038916815290899052206001830190555050505050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282612fa95760008555612fef565b82601f10612fc25782800160ff19823516178555612fef565b82800160010185558215612fef579182015b82811115612fef578235825591602001919060010190612fd4565b50612ffb929150613040565b5090565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b604080518082019091526000808252602082015290565b5b80821115612ffb5760008155600101613041565b80356001600160a01b0381168114610bf657600080fd5b803560028110610bf657600080fd5b60008083601f84011261308c578182fd5b50813567ffffffffffffffff8111156130a3578182fd5b6020830191508360208285010111156130bb57600080fd5b9250929050565b803560ff81168114610bf657600080fd5b6000602082840312156130e4578081fd5b610a4a82613055565b600080604083850312156130ff578081fd5b61310883613055565b915061311660208401613055565b90509250929050565b600080600060608486031215613133578081fd5b61313c84613055565b925061314a60208501613055565b9150604084013590509250925092565b600080600080600080600060e0888a031215613174578283fd5b61317d88613055565b965061318b60208901613055565b955060408801359450606088013593506131a7608089016130c2565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156131d5578182fd5b6131de83613055565b91506131166020840161306c565b600080600080600080600060e0888a031215613206578283fd5b61320f88613055565b965061318b6020890161306c565b6000806040838503121561322f578182fd5b61323883613055565b946020939093013593505050565b60008060006060848603121561325a578283fd5b61326384613055565b9250602084013591506132786040850161306c565b90509250925092565b60008060008060008060c08789031215613299578182fd5b6132a287613055565b955060208701359450604087013593506132be606088016130c2565b92506080870135915060a087013590509295509295509295565b600080602083850312156132ea578081fd5b823567ffffffffffffffff80821115613301578283fd5b818501915085601f830112613314578283fd5b813581811115613322578384fd5b866020606083028501011115613336578384fd5b60209290920196919550909350505050565b60008060008060006060868803121561335f578283fd5b853567ffffffffffffffff80821115613376578485fd5b61338289838a0161307b565b9097509550602088013591508082111561339a578485fd5b506133a78882890161307b565b90945092506133ba9050604087016130c2565b90509295509295909350565b6000602082840312156133d7578081fd5b81356001600160801b0381168114610a4a578182fd5b6000602082840312156133fe578081fd5b5035919050565b6000806000806080858703121561341a578182fd5b843593506020850135925061343160408601613055565b9396929550929360600135925050565b60008151808452815b818110156134665760208185018101518683018201520161344a565b818111156134775782602083870101525b50601f01601f19169290920160200192915050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b9485526001600160a01b0393909316602085015260408401919091526060830152608082015260a00190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b93845260ff9290921660208401526040830152606082015260800190565b600060208252610a4a6020830184613441565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260119082015270494e56414c49445f5349474e415455524560781b604082015260600190565b60208082526015908201527424a729aaa32324a1a4a2a72a2fa1a7a7a62227aba760591b604082015260600190565b60208082526012908201527124a72b20a624a22fa2ac2824a920aa24a7a760711b604082015260600190565b6020808252600d908201526c494e56414c49445f4e4f4e434560981b604082015260600190565b60208082526015908201527427a7262cafa2a6a4a9a9a4a7a72fa6a0a720a3a2a960591b604082015260600190565b6020808252600d908201526c24a72b20a624a22fa7aba722a960991b604082015260600190565b60208082526017908201527f554e5354414b455f57494e444f575f46494e4953484544000000000000000000604082015260600190565b6020808252601b908201527f494e56414c49445f42414c414e43455f4f4e5f434f4f4c444f574e0000000000604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b039384168152919092166020820152604081019190915260600190565b60ff9190911681526020019056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200c4f0888820d9e117b76e7a1a597eb3afa35dc8ba043094cd2cad6dfa1967c3f64736f6c63430007050033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf00000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000000002a3000000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a190000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a1900000000000000000000000000000000000000000000000000000000bbf81e00
-----Decoded View---------------
Arg [0] : stakedToken (address): 0x01BA67AAC7f75f647D94220Cc98FB30FCc5105Bf
Arg [1] : rewardToken (address): 0x01BA67AAC7f75f647D94220Cc98FB30FCc5105Bf
Arg [2] : cooldownSeconds (uint256): 864000
Arg [3] : unstakeWindow (uint256): 172800
Arg [4] : rewardsVault (address): 0x8ef8eEEB39b21ECdDE451e6C539017DF24D14a19
Arg [5] : emissionManager (address): 0x8ef8eEEB39b21ECdDE451e6C539017DF24D14a19
Arg [6] : distributionDuration (uint128): 3153600000
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf
Arg [1] : 00000000000000000000000001ba67aac7f75f647d94220cc98fb30fcc5105bf
Arg [2] : 00000000000000000000000000000000000000000000000000000000000d2f00
Arg [3] : 000000000000000000000000000000000000000000000000000000000002a300
Arg [4] : 0000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a19
Arg [5] : 0000000000000000000000008ef8eeeb39b21ecdde451e6c539017df24d14a19
Arg [6] : 00000000000000000000000000000000000000000000000000000000bbf81e00
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
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.