Source Code
Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer Ownersh... | 3955461 | 633 days ago | IN | 0 FRAX | 0.00000087 |
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers.
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 29506627 | 42 days ago | 0 FRAX | |||||
| 26782345 | 105 days ago | 0 FRAX | |||||
| 26782345 | 105 days ago | 0 FRAX | |||||
| 26661793 | 108 days ago | 0 FRAX | |||||
| 26660849 | 108 days ago | 0 FRAX | |||||
| 26660849 | 108 days ago | 0 FRAX | |||||
| 26660849 | 108 days ago | 0 FRAX | |||||
| 26660849 | 108 days ago | 0 FRAX | |||||
| 26660847 | 108 days ago | 0 FRAX | |||||
| 26660847 | 108 days ago | 0 FRAX | |||||
| 26660847 | 108 days ago | 0 FRAX | |||||
| 26660847 | 108 days ago | 0 FRAX | |||||
| 26660489 | 108 days ago | 0 FRAX | |||||
| 26660489 | 108 days ago | 0 FRAX | |||||
| 26660384 | 108 days ago | 0 FRAX | |||||
| 26660384 | 108 days ago | 0 FRAX | |||||
| 26660354 | 108 days ago | 0 FRAX | |||||
| 26660354 | 108 days ago | 0 FRAX | |||||
| 26660354 | 108 days ago | 0 FRAX | |||||
| 26660354 | 108 days ago | 0 FRAX | |||||
| 26660216 | 108 days ago | 0 FRAX | |||||
| 26660216 | 108 days ago | 0 FRAX | |||||
| 26660216 | 108 days ago | 0 FRAX | |||||
| 26660216 | 108 days ago | 0 FRAX | |||||
| 26660206 | 108 days ago | 0 FRAX |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Rewarder
Compiler Version
v0.7.5+commit.eb77ed08
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.7.5;
pragma experimental ABIEncoderV2;
import {IERC20} from './interfaces/IERC20.sol';
import {SafeERC20} from './libraries/SafeERC20.sol';
import {RewardsController} from './RewardsController.sol';
contract Rewarder is RewardsController {
using SafeERC20 for IERC20;
// reward => reward vault
mapping(address => address) internal _rewardsVault;
event RewardsVaultUpdated(address indexed vault);
function setRewardsVault(address vault, address reward) external onlyOwner {
_rewardsVault[reward] = vault;
emit RewardsVaultUpdated(vault);
}
function getRewardsVault(address reward) external view returns (address) {
return _rewardsVault[reward];
}
function transferRewards(address to, address reward, uint256 amount) internal override returns (bool) {
IERC20(reward).safeTransferFrom(_rewardsVault[reward], to, amount);
return true;
}
}// 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: agpl-3.0
pragma solidity 0.7.5;
import {IERC20} from './IERC20.sol';
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: MIT
pragma solidity 0.7.5;
pragma experimental ABIEncoderV2;
import {IRewardsDistributor} from './IRewardsDistributor.sol';
import {DistributionTypes} from '../libraries/DistributionTypes.sol';
interface IRewardsController is IRewardsDistributor {
event RewardsClaimed(
address indexed user,
address indexed reward,
address indexed to,
address claimer,
uint256 amount
);
event ClaimerSet(address indexed user, address indexed claimer);
function setClaimer(address user, address claimer) external;
function getClaimer(address user) external view returns (address);
function configureAssets(DistributionTypes.RewardsConfigInput[] memory config) external;
function handleAction(
address asset,
uint256 userBalance,
uint256 totalSupply
) external;
function claimRewards(
address[] calldata assets,
uint256 amount,
address to,
address reward
) external returns (uint256);
function claimRewardsOnBehalf(
address[] calldata assets,
uint256 amount,
address user,
address to,
address reward
) external returns (uint256);
function claimRewardsToSelf(
address[] calldata assets,
uint256 amount,
address reward
) external returns (uint256);
function claimAllRewards(address[] calldata assets, address to)
external
returns (address[] memory rewardsList, uint256[] memory claimedAmounts);
function claimAllRewardsOnBehalf(
address[] calldata assets,
address user,
address to
) external returns (address[] memory rewardsList, uint256[] memory claimedAmounts);
function claimAllRewardsToSelf(address[] calldata assets)
external
returns (address[] memory rewardsList, uint256[] memory claimedAmounts);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.5;
pragma experimental ABIEncoderV2;
import {DistributionTypes} from '../libraries/DistributionTypes.sol';
interface IRewardsDistributor {
event AssetConfigUpdated(
address indexed asset,
address indexed reward,
uint256 emission,
uint256 distributionEnd
);
event AssetIndexUpdated(address indexed asset, address indexed reward, uint256 index);
event UserIndexUpdated(
address indexed user,
address indexed asset,
address indexed reward,
uint256 index
);
event RewardsAccrued(address indexed user, address indexed reward, uint256 amount);
function setDistributionEnd(
address asset,
address reward,
uint32 distributionEnd
) external;
function getDistributionEnd(address asset, address reward) external view returns (uint256);
function getUserAssetData(
address user,
address asset,
address reward
) external view returns (uint256);
function getRewardsData(address asset, address reward)
external
view
returns (
uint256,
uint256,
uint256,
uint256
);
function getRewardsByAsset(address asset) external view returns (address[] memory);
function getRewardTokens() external view returns (address[] memory);
function getUserUnclaimedRewardsFromStorage(address user, address reward)
external
view
returns (uint256);
function getUserRewardsBalance(
address[] calldata assets,
address user,
address reward
) external view returns (uint256);
function getAllUserRewardsBalance(address[] calldata assets, address user)
external
view
returns (address[] memory, uint256[] memory);
function getAssetDecimals(address asset) external view returns (uint8);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.5;
interface IScaledBalanceToken {
/**
* @dev Returns the scaled balance of the user. The scaled balance is the sum of all the
* updated stored balance divided by the reserve's liquidity index at the moment of the update
* @param user The user whose balance is calculated
* @return The scaled balance of the user
**/
function scaledBalanceOf(address user) external view returns (uint256);
/**
* @dev Returns the scaled balance of the user and the scaled total supply.
* @param user The address of the user
* @return The scaled balance of the user
* @return The scaled balance and the scaled total supply
**/
function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);
/**
* @dev Returns the scaled total supply of the token. Represents sum(debt/index)
* @return The scaled total supply
**/
function scaledTotalSupply() external view returns (uint256);
}// 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: 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: MIT
pragma solidity 0.7.5;
pragma experimental ABIEncoderV2;
library DistributionTypes {
struct RewardsConfigInput {
uint88 emissionPerSecond;
uint256 totalSupply;
uint32 distributionEnd;
address asset;
address reward;
}
struct UserAssetInput {
address underlyingAsset;
uint256 userBalance;
uint256 totalSupply;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.5;
import './Context.sol';
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), 'Ownable: caller is not the owner');
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), 'Ownable: new owner is the zero address');
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}// 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;
/**
* @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;
pragma experimental ABIEncoderV2;
import {IRewardsController} from './interfaces/IRewardsController.sol';
import {RewardsDistributor} from './RewardsDistributor.sol';
import {IScaledBalanceToken} from './interfaces/IScaledBalanceToken.sol';
import {DistributionTypes} from './libraries/DistributionTypes.sol';
abstract contract RewardsController is RewardsDistributor, IRewardsController {
// user => authorized claimer
mapping(address => address) internal _authorizedClaimers;
modifier onlyAuthorizedClaimers(address claimer, address user) {
require(_authorizedClaimers[user] == claimer, 'CLAIMER_UNAUTHORIZED');
_;
}
function getClaimer(address user) external view override returns (address) {
return _authorizedClaimers[user];
}
function setClaimer(address user, address caller) external override onlyOwner {
_authorizedClaimers[user] = caller;
emit ClaimerSet(user, caller);
}
function configureAssets(DistributionTypes.RewardsConfigInput[] memory config)
external
override
onlyOwner
{
for (uint256 i = 0; i < config.length; i++) {
config[i].totalSupply = IScaledBalanceToken(config[i].asset).scaledTotalSupply();
}
_configureAssets(config);
}
function handleAction(
address user,
uint256 totalSupply,
uint256 userBalance
) external override {
_updateUserRewardsPerAssetInternal(msg.sender, user, userBalance, totalSupply);
}
function claimRewards(
address[] calldata assets,
uint256 amount,
address to,
address reward
) external override returns (uint256) {
require(to != address(0), 'INVALID_TO_ADDRESS');
return _claimRewards(assets, amount, msg.sender, msg.sender, to, reward);
}
function claimRewardsOnBehalf(
address[] calldata assets,
uint256 amount,
address user,
address to,
address reward
) external override onlyAuthorizedClaimers(msg.sender, user) returns (uint256) {
require(user != address(0), 'INVALID_USER_ADDRESS');
require(to != address(0), 'INVALID_TO_ADDRESS');
return _claimRewards(assets, amount, msg.sender, user, to, reward);
}
function claimRewardsToSelf(
address[] calldata assets,
uint256 amount,
address reward
) external override returns (uint256) {
return _claimRewards(assets, amount, msg.sender, msg.sender, msg.sender, reward);
}
function claimAllRewards(address[] calldata assets, address to)
external
override
returns (address[] memory rewardTokens, uint256[] memory claimedAmounts)
{
require(to != address(0), 'INVALID_TO_ADDRESS');
return _claimAllRewards(assets, msg.sender, msg.sender, to);
}
function claimAllRewardsOnBehalf(
address[] calldata assets,
address user,
address to
)
external
override
onlyAuthorizedClaimers(msg.sender, user)
returns (address[] memory rewardTokens, uint256[] memory claimedAmounts)
{
require(user != address(0), 'INVALID_USER_ADDRESS');
require(to != address(0), 'INVALID_TO_ADDRESS');
return _claimAllRewards(assets, msg.sender, user, to);
}
function claimAllRewardsToSelf(address[] calldata assets)
external
override
returns (address[] memory rewardTokens, uint256[] memory claimedAmounts)
{
return _claimAllRewards(assets, msg.sender, msg.sender, msg.sender);
}
function _getUserStake(address[] calldata assets, address user)
internal
view
override
returns (DistributionTypes.UserAssetInput[] memory userState)
{
userState = new DistributionTypes.UserAssetInput[](assets.length);
for (uint256 i = 0; i < assets.length; i++) {
userState[i].underlyingAsset = assets[i];
(userState[i].userBalance, userState[i].totalSupply) = IScaledBalanceToken(assets[i])
.getScaledUserBalanceAndSupply(user);
}
return userState;
}
function _claimRewards(
address[] calldata assets,
uint256 amount,
address claimer,
address user,
address to,
address reward
) internal returns (uint256) {
if (amount == 0) {
return 0;
}
uint256 unclaimedRewards = _usersUnclaimedRewards[user][reward];
if (amount > unclaimedRewards) {
_distributeRewards(user, _getUserStake(assets, user));
unclaimedRewards = _usersUnclaimedRewards[user][reward];
}
if (unclaimedRewards == 0) {
return 0;
}
uint256 amountToClaim = amount > unclaimedRewards ? unclaimedRewards : amount;
_usersUnclaimedRewards[user][reward] = unclaimedRewards - amountToClaim; // Safe due to the previous line
_transferRewards(to, reward, amountToClaim);
emit RewardsClaimed(user, reward, to, claimer, amountToClaim);
return amountToClaim;
}
function _claimAllRewards(
address[] calldata assets,
address claimer,
address user,
address to
) internal returns (address[] memory rewardTokens, uint256[] memory claimedAmounts) {
_distributeRewards(user, _getUserStake(assets, user));
rewardTokens = new address[](_rewardTokens.length);
claimedAmounts = new uint256[](_rewardTokens.length);
for (uint256 i = 0; i < _rewardTokens.length; i++) {
address reward = _rewardTokens[i];
uint256 rewardAmount = _usersUnclaimedRewards[user][reward];
rewardTokens[i] = reward;
claimedAmounts[i] = rewardAmount;
if (rewardAmount != 0) {
_usersUnclaimedRewards[user][reward] = 0;
_transferRewards(to, reward, rewardAmount);
emit RewardsClaimed(user, reward, to, claimer, rewardAmount);
}
}
return (rewardTokens, claimedAmounts);
}
function _transferRewards(
address to,
address reward,
uint256 amount
) internal {
bool success = transferRewards(to, reward, amount);
require(success == true, 'TRANSFER_ERROR');
}
function transferRewards(address to, address reward, uint256 amount) internal virtual returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.5;
pragma experimental ABIEncoderV2;
import {IRewardsDistributor} from './interfaces/IRewardsDistributor.sol';
import {IERC20Detailed} from './interfaces/IERC20Detailed.sol';
import {DistributionTypes} from './libraries/DistributionTypes.sol';
import {Ownable} from './libraries/Ownable.sol';
abstract contract RewardsDistributor is IRewardsDistributor, Ownable {
struct RewardData {
uint88 emissionPerSecond;
uint104 index;
uint32 lastUpdateTimestamp;
uint32 distributionEnd;
mapping(address => uint256) usersIndex;
}
struct AssetData {
// reward => rewardData
mapping(address => RewardData) rewards;
address[] availableRewards;
uint8 decimals;
}
// incentivized asset => AssetData
mapping(address => AssetData) internal _assets;
// user => reward => unclaimed rewards
mapping(address => mapping(address => uint256)) internal _usersUnclaimedRewards;
// reward => isEnabled
mapping(address => bool) internal _isRewardEnabled;
address[] internal _rewardTokens;
function getRewardsData(address asset, address reward)
public
view
override
returns (
uint256,
uint256,
uint256,
uint256
)
{
return (
_assets[asset].rewards[reward].index,
_assets[asset].rewards[reward].emissionPerSecond,
_assets[asset].rewards[reward].lastUpdateTimestamp,
_assets[asset].rewards[reward].distributionEnd
);
}
function getDistributionEnd(address asset, address reward)
external
view
override
returns (uint256)
{
return _assets[asset].rewards[reward].distributionEnd;
}
function getRewardsByAsset(address asset) external view override returns (address[] memory) {
return _assets[asset].availableRewards;
}
function getRewardTokens() external view override returns (address[] memory) {
return _rewardTokens;
}
function getUserAssetData(
address user,
address asset,
address reward
) public view override returns (uint256) {
return _assets[asset].rewards[reward].usersIndex[user];
}
function getUserUnclaimedRewardsFromStorage(address user, address reward)
external
view
override
returns (uint256)
{
return _usersUnclaimedRewards[user][reward];
}
function getUserRewardsBalance(
address[] calldata assets,
address user,
address reward
) external view override returns (uint256) {
return _getUserReward(user, reward, _getUserStake(assets, user));
}
function getAllUserRewardsBalance(address[] calldata assets, address user)
external
view
override
returns (address[] memory rewardTokens, uint256[] memory unclaimedAmounts)
{
return _getAllUserRewards(user, _getUserStake(assets, user));
}
function setDistributionEnd(
address asset,
address reward,
uint32 distributionEnd
) external override onlyOwner {
_assets[asset].rewards[reward].distributionEnd = distributionEnd;
emit AssetConfigUpdated(
asset,
reward,
_assets[asset].rewards[reward].emissionPerSecond,
distributionEnd
);
}
function _configureAssets(DistributionTypes.RewardsConfigInput[] memory rewardsInput)
internal
{
for (uint256 i = 0; i < rewardsInput.length; i++) {
_assets[rewardsInput[i].asset].decimals = IERC20Detailed(rewardsInput[i].asset).decimals();
RewardData storage rewardConfig = _assets[rewardsInput[i].asset].rewards[
rewardsInput[i].reward
];
// Add reward address to asset available rewards if latestUpdateTimestamp is zero
if (rewardConfig.lastUpdateTimestamp == 0) {
_assets[rewardsInput[i].asset].availableRewards.push(rewardsInput[i].reward);
}
// Add reward address to global rewards list if still not enabled
if (_isRewardEnabled[rewardsInput[i].reward] == false) {
_isRewardEnabled[rewardsInput[i].reward] = true;
_rewardTokens.push(rewardsInput[i].reward);
}
// Due emissions is still zero, updates only latestUpdateTimestamp
_updateAssetStateInternal(
rewardsInput[i].asset,
rewardsInput[i].reward,
rewardConfig,
rewardsInput[i].totalSupply,
_assets[rewardsInput[i].asset].decimals
);
// Configure emission and distribution end of the reward per asset
rewardConfig.emissionPerSecond = rewardsInput[i].emissionPerSecond;
rewardConfig.distributionEnd = rewardsInput[i].distributionEnd;
emit AssetConfigUpdated(
rewardsInput[i].asset,
rewardsInput[i].reward,
rewardsInput[i].emissionPerSecond,
rewardsInput[i].distributionEnd
);
}
}
function _updateAssetStateInternal(
address asset,
address reward,
RewardData storage rewardConfig,
uint256 totalSupply,
uint8 decimals
) internal returns (uint256) {
uint256 oldIndex = rewardConfig.index;
if (block.timestamp == rewardConfig.lastUpdateTimestamp) {
return oldIndex;
}
uint256 newIndex = _getAssetIndex(
oldIndex,
rewardConfig.emissionPerSecond,
rewardConfig.lastUpdateTimestamp,
rewardConfig.distributionEnd,
totalSupply,
decimals
);
if (newIndex != oldIndex) {
require(newIndex <= type(uint104).max, 'Index overflow');
//optimization: storing one after another saves one SSTORE
rewardConfig.index = uint104(newIndex);
rewardConfig.lastUpdateTimestamp = uint32(block.timestamp);
emit AssetIndexUpdated(asset, reward, newIndex);
} else {
rewardConfig.lastUpdateTimestamp = uint32(block.timestamp);
}
return newIndex;
}
function _updateUserRewardsInternal(
address user,
address asset,
address reward,
uint256 userBalance,
uint256 totalSupply
) internal returns (uint256) {
RewardData storage rewardData = _assets[asset].rewards[reward];
uint256 userIndex = rewardData.usersIndex[user];
uint256 accruedRewards = 0;
uint256 newIndex = _updateAssetStateInternal(
asset,
reward,
rewardData,
totalSupply,
_assets[asset].decimals
);
if (userIndex != newIndex) {
if (userBalance != 0) {
accruedRewards = _getRewards(userBalance, newIndex, userIndex, _assets[asset].decimals);
}
rewardData.usersIndex[user] = newIndex;
emit UserIndexUpdated(user, asset, reward, newIndex);
}
return accruedRewards;
}
function _updateUserRewardsPerAssetInternal(
address asset,
address user,
uint256 userBalance,
uint256 totalSupply
) internal {
for (uint256 r = 0; r < _assets[asset].availableRewards.length; r++) {
address reward = _assets[asset].availableRewards[r];
uint256 accruedRewards = _updateUserRewardsInternal(
user,
asset,
reward,
userBalance,
totalSupply
);
if (accruedRewards != 0) {
_usersUnclaimedRewards[user][reward] += accruedRewards;
emit RewardsAccrued(user, reward, accruedRewards);
}
}
}
function _distributeRewards(
address user,
DistributionTypes.UserAssetInput[] memory userState
) internal {
for (uint256 i = 0; i < userState.length; i++) {
_updateUserRewardsPerAssetInternal(
userState[i].underlyingAsset,
user,
userState[i].userBalance,
userState[i].totalSupply
);
}
}
function _getUserReward(
address user,
address reward,
DistributionTypes.UserAssetInput[] memory userState
) internal view returns (uint256 unclaimedRewards) {
// Add unrealized rewards
for (uint256 i = 0; i < userState.length; i++) {
if (userState[i].userBalance == 0) {
continue;
}
unclaimedRewards += _getUnrealizedRewardsFromStake(user, reward, userState[i]);
}
// Return unrealized rewards plus stored unclaimed rewardss
return unclaimedRewards + _usersUnclaimedRewards[user][reward];
}
function _getAllUserRewards(
address user,
DistributionTypes.UserAssetInput[] memory userState
) internal view returns (address[] memory rewardTokens, uint256[] memory unclaimedRewards) {
rewardTokens = new address[](_rewardTokens.length);
unclaimedRewards = new uint256[](rewardTokens.length);
// Add stored rewards from user to unclaimedRewards
for (uint256 y = 0; y < rewardTokens.length; y++) {
rewardTokens[y] = _rewardTokens[y];
unclaimedRewards[y] = _usersUnclaimedRewards[user][rewardTokens[y]];
}
// Add unrealized rewards from user to unclaimedRewards
for (uint256 i = 0; i < userState.length; i++) {
if (userState[i].userBalance == 0) {
continue;
}
for (uint256 r = 0; r < rewardTokens.length; r++) {
unclaimedRewards[r] += _getUnrealizedRewardsFromStake(user, rewardTokens[r], userState[i]);
}
}
return (rewardTokens, unclaimedRewards);
}
function _getUnrealizedRewardsFromStake(
address user,
address reward,
DistributionTypes.UserAssetInput memory stake
) internal view returns (uint256) {
RewardData storage rewardData = _assets[stake.underlyingAsset].rewards[reward];
uint8 assetDecimals = _assets[stake.underlyingAsset].decimals;
uint256 assetIndex = _getAssetIndex(
rewardData.index,
rewardData.emissionPerSecond,
rewardData.lastUpdateTimestamp,
rewardData.distributionEnd,
stake.totalSupply,
assetDecimals
);
return _getRewards(stake.userBalance, assetIndex, rewardData.usersIndex[user], assetDecimals);
}
function _getRewards(
uint256 principalUserBalance,
uint256 reserveIndex,
uint256 userIndex,
uint8 decimals
) internal pure returns (uint256) {
return (principalUserBalance * (reserveIndex - userIndex)) / 10**decimals;
}
function _getAssetIndex(
uint256 currentIndex,
uint256 emissionPerSecond,
uint128 lastUpdateTimestamp,
uint256 distributionEnd,
uint256 totalBalance,
uint8 decimals
) internal view returns (uint256) {
if (
emissionPerSecond == 0 ||
totalBalance == 0 ||
lastUpdateTimestamp == block.timestamp ||
lastUpdateTimestamp >= distributionEnd
) {
return currentIndex;
}
uint256 currentTimestamp = block.timestamp > distributionEnd
? distributionEnd
: block.timestamp;
uint256 timeDelta = currentTimestamp - lastUpdateTimestamp;
return (emissionPerSecond * timeDelta * (10**decimals)) / totalBalance + currentIndex;
}
function _getUserStake(address[] calldata assets, address user)
internal
view
virtual
returns (DistributionTypes.UserAssetInput[] memory userState);
function getAssetDecimals(address asset) external view override returns (uint8) {
return _assets[asset].decimals;
}
}{
"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
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"emission","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"distributionEnd","type":"uint256"}],"name":"AssetConfigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"AssetIndexUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"claimer","type":"address"}],"name":"ClaimerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsAccrued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"claimer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"}],"name":"RewardsVaultUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"UserIndexUpdated","type":"event"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"address","name":"to","type":"address"}],"name":"claimAllRewards","outputs":[{"internalType":"address[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"claimedAmounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"claimAllRewardsOnBehalf","outputs":[{"internalType":"address[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"claimedAmounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"}],"name":"claimAllRewardsToSelf","outputs":[{"internalType":"address[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"claimedAmounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"name":"claimRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"name":"claimRewardsOnBehalf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"reward","type":"address"}],"name":"claimRewardsToSelf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint88","name":"emissionPerSecond","type":"uint88"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint32","name":"distributionEnd","type":"uint32"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"internalType":"struct DistributionTypes.RewardsConfigInput[]","name":"config","type":"tuple[]"}],"name":"configureAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"address","name":"user","type":"address"}],"name":"getAllUserRewardsBalance","outputs":[{"internalType":"address[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"unclaimedAmounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getAssetDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getClaimer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"name":"getDistributionEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getRewardsByAsset","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"name":"getRewardsData","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"reward","type":"address"}],"name":"getRewardsVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"name":"getUserAssetData","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"name":"getUserRewardsBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"name":"getUserUnclaimedRewardsFromStorage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"userBalance","type":"uint256"}],"name":"handleAction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"caller","type":"address"}],"name":"setClaimer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"reward","type":"address"},{"internalType":"uint32","name":"distributionEnd","type":"uint32"}],"name":"setDistributionEnd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"name":"setRewardsVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50600061001b61006a565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061006e565b3390565b6128b78061007d6000396000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80637eff4ba8116100de578063bb492bf511610097578063c5a7b53811610071578063c5a7b53814610343578063c664493a14610356578063f2fde38b14610369578063f5cf673b1461037c57610173565b8063bb492bf514610315578063bf90f63a14610328578063c4f59f9b1461033b57610173565b80637eff4ba814610283578063866bc096146102a65780638da5cb5b146102b95780639efd6f72146102c15780639ff55db9146102e1578063af15ec5a1461030257610173565b80635077215511610130578063507721551461020257806357b89883146102155780636657732f1461022857806367eabbc914610248578063715018a61461026857806374d945ec1461027057610173565b80630b0db655146101785780631b839c771461018d578063236300dc146101b657806331873e2e146101c957806333028b99146101dc57806344fd1400146101ef575b600080fd5b61018b6101863660046124e3565b61038f565b005b6101a061019b3660046121e7565b6104aa565b6040516101ad919061279d565b60405180910390f35b6101a06101c43660046123fe565b6104e2565b61018b6101d7366004612294565b61052e565b6101a06101ea366004612469565b61053f565b61018b6101fd3660046121e7565b6105e6565b6101a0610210366004612219565b610695565b6101a06102233660046123af565b6106cf565b61023b6102363660046121c6565b6106e0565b6040516101ad919061265c565b61025b6102563660046121c6565b61075a565b6040516101ad919061262f565b61018b610778565b61025b61027e3660046121c6565b61081a565b6102966102913660046121e7565b610838565b6040516101ad94939291906127a6565b6101a06102b43660046121e7565b610897565b61025b6108c2565b6102d46102cf3660046121c6565b6108d1565b6040516101ad91906127e0565b6102f46102ef36600461234d565b6108f2565b6040516101ad92919061266f565b6101a061031036600461234d565b61099c565b6102f4610323366004612305565b6109b3565b6102f46103363660046122c6565b6109f5565b61023b610a11565b61018b61035136600461225b565b610a73565b6102f4610364366004612305565b610b5a565b61018b6103773660046121c6565b610b71565b61018b61038a3660046121e7565b610c69565b610397610d18565b6000546001600160a01b039081169116146103e7576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b60005b815181101561049d578181815181106103ff57fe5b6020026020010151606001516001600160a01b031663b1bf962d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561044357600080fd5b505afa158015610457573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047b9190612590565b82828151811061048757fe5b60209081029190910181015101526001016103ea565b506104a781610d1c565b50565b6001600160a01b039182166000908152600160209081526040808320939094168252919091522054600160e01b900463ffffffff1690565b60006001600160a01b0383166105135760405162461bcd60e51b815260040161050a9061271b565b60405180910390fd5b610522868686333388886111b9565b90505b95945050505050565b61053a338483856112ef565b505050565b6001600160a01b0380841660009081526005602052604081205490913391869116821461057e5760405162461bcd60e51b815260040161050a9061276f565b6001600160a01b0386166105a45760405162461bcd60e51b815260040161050a906126c5565b6001600160a01b0385166105ca5760405162461bcd60e51b815260040161050a9061271b565b6105d9898989338a8a8a6111b9565b9998505050505050505050565b6105ee610d18565b6000546001600160a01b0390811691161461063e576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b6001600160a01b0381811660009081526006602052604080822080546001600160a01b0319169386169384179055517f28a48cbce43190d77247f342cf319b1607bff4ef716cf26b76cf7bb71baebaa59190a25050565b6001600160a01b03808316600090815260016020818152604080842086861685528252808420948816845293909101905220549392505050565b6000610525858585333333886111b9565b6001600160a01b03811660009081526001602081815260409283902090910180548351818402810184019094528084526060939283018282801561074d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161072f575b505050505090505b919050565b6001600160a01b039081166000908152600660205260409020541690565b610780610d18565b6000546001600160a01b039081169116146107d0576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6001600160a01b039081166000908152600560205260409020541690565b6001600160a01b0391821660009081526001602090815260408083209390941682529190915220546001600160681b03600160581b820416916001600160581b0382169163ffffffff600160c01b8204811692600160e01b9092041690565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6000546001600160a01b031690565b6001600160a01b031660009081526001602052604090206002015460ff1690565b6001600160a01b038083166000908152600560205260409020546060918291339186911682146109345760405162461bcd60e51b815260040161050a9061276f565b6001600160a01b03861661095a5760405162461bcd60e51b815260040161050a906126c5565b6001600160a01b0385166109805760405162461bcd60e51b815260040161050a9061271b565b61098d88883389896113e0565b93509350505094509492505050565b600061052583836109ae8888886115bc565b611742565b6060806001600160a01b0383166109dc5760405162461bcd60e51b815260040161050a9061271b565b6109e985853333876113e0565b91509150935093915050565b606080610a0584843333336113e0565b915091505b9250929050565b60606004805480602002602001604051908101604052809291908181526020018280548015610a6957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a4b575b5050505050905090565b610a7b610d18565b6000546001600160a01b03908116911614610acb576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b6001600160a01b038381166000818152600160209081526040808320948716808452949091529081902080546001600160e01b0316600160e01b63ffffffff871602179081905590517fec44514a2743afadd78647150195ef92fec31e96087fa5cbbcd72e8d131d9a1c91610b4d916001600160581b039091169086906127c1565b60405180910390a3505050565b6060806109e983610b6c8787876115bc565b6117ce565b610b79610d18565b6000546001600160a01b03908116911614610bc9576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b6001600160a01b038116610c0e5760405162461bcd60e51b81526004018080602001828103825260268152602001806128126026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b610c71610d18565b6000546001600160a01b03908116911614610cc1576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b6001600160a01b0382811660008181526005602052604080822080546001600160a01b0319169486169485179055517f4925eafc82d0c4d67889898eeed64b18488ab19811e61620f387026dec126a289190a35050565b3390565b60005b81518110156111b557818181518110610d3457fe5b6020026020010151606001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7857600080fd5b505afa158015610d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db091906125cb565b60016000848481518110610dc057fe5b6020026020010151606001516001600160a01b03166001600160a01b0316815260200190815260200160002060020160006101000a81548160ff021916908360ff160217905550600060016000848481518110610e1957fe5b6020026020010151606001516001600160a01b03166001600160a01b031681526020019081526020016000206000016000848481518110610e5657fe5b602090810291909101810151608001516001600160a01b031682528101919091526040016000208054909150600160c01b900463ffffffff16610f1e5760016000848481518110610ea357fe5b6020026020010151606001516001600160a01b03166001600160a01b03168152602001908152602001600020600101838381518110610ede57fe5b6020908102919091018101516080015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b60036000848481518110610f2e57fe5b602090810291909101810151608001516001600160a01b031682528101919091526040016000205460ff1661100057600160036000858581518110610f6f57fe5b6020026020010151608001516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055506004838381518110610fc057fe5b6020908102919091018101516080015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b61108f83838151811061100f57fe5b60200260200101516060015184848151811061102757fe5b6020026020010151608001518386868151811061104057fe5b6020026020010151602001516001600089898151811061105c57fe5b602090810291909101810151606001516001600160a01b031682528101919091526040016000206002015460ff166119d3565b5082828151811061109c57fe5b60209081029190910101515181546affffffffffffffffffffff19166001600160581b0390911617815582518390839081106110d457fe5b602090810291909101015160400151815463ffffffff909116600160e01b026001600160e01b03909116178155825183908390811061110f57fe5b6020026020010151608001516001600160a01b031683838151811061113057fe5b6020026020010151606001516001600160a01b03167fec44514a2743afadd78647150195ef92fec31e96087fa5cbbcd72e8d131d9a1c85858151811061117257fe5b60200260200101516000015186868151811061118a57fe5b6020026020010151604001516040516111a49291906127c1565b60405180910390a350600101610d1f565b5050565b6000856111c8575060006112e4565b6001600160a01b03808516600090815260026020908152604080832093861683529290522054808711156112325761120a856112058b8b896115bc565b611b1c565b506001600160a01b038085166000908152600260209081526040808320938616835292905220545b806112415760009150506112e4565b60008188116112505787611252565b815b6001600160a01b03808816600090815260026020908152604080832093891683529290522081840390559050611289858583611b81565b846001600160a01b0316846001600160a01b0316876001600160a01b03167fc052130bc4ef84580db505783484b067ea8b71b3bca78a7e12db7aea8658f0048a856040516112d8929190612643565b60405180910390a49150505b979650505050505050565b60005b6001600160a01b038516600090815260016020819052604090912001548110156113d9576001600160a01b038516600090815260016020819052604082200180548390811061133d57fe5b60009182526020822001546001600160a01b031691506113608688848888611bb8565b905080156113cf576001600160a01b0380871660008181526002602090815260408083209487168084529490915290819020805485019055517f68ac6b4d0eeedccf3df154188dfac62d18d2ac5eaac52ecd6e728e33ce75a1d4906113c690859061279d565b60405180910390a35b50506001016112f2565b5050505050565b6060806113f2846112058989886115bc565b6004546001600160401b038111801561140a57600080fd5b50604051908082528060200260200182016040528015611434578160200160208202803683370190505b506004549092506001600160401b038111801561145057600080fd5b5060405190808252806020026020018201604052801561147a578160200160208202803683370190505b50905060005b6004548110156115b15760006004828154811061149957fe5b60009182526020808320909101546001600160a01b0389811684526002835260408085209190921680855292529091205485519192509082908690859081106114de57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508084848151811061150b57fe5b602090810291909101015280156115a7576001600160a01b03808816600090815260026020908152604080832093861683529290529081205561154f868383611b81565b856001600160a01b0316826001600160a01b0316886001600160a01b03167fc052130bc4ef84580db505783484b067ea8b71b3bca78a7e12db7aea8658f0048b8560405161159e929190612643565b60405180910390a45b5050600101611480565b509550959350505050565b6060826001600160401b03811180156115d457600080fd5b5060405190808252806020026020018201604052801561160e57816020015b6115fb6120a0565b8152602001906001900390816115f35790505b50905060005b8381101561173a5784848281811061162857fe5b905060200201602081019061163d91906121c6565b82828151811061164957fe5b60209081029190910101516001600160a01b03909116905284848281811061166d57fe5b905060200201602081019061168291906121c6565b6001600160a01b0316630afbcdc9846040518263ffffffff1660e01b81526004016116ad919061262f565b604080518083038186803b1580156116c457600080fd5b505afa1580156116d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fc91906125a8565b83838151811061170857fe5b602002602001015160200184848151811061171f57fe5b60209081029190910101516040019190915252600101611614565b509392505050565b6000805b825181101561179f5782818151811061175b57fe5b6020026020010151602001516000141561177457611797565b611792858585848151811061178557fe5b6020026020010151611cbf565b820191505b600101611746565b506001600160a01b03808516600090815260026020908152604080832093871683529290522054019392505050565b60045460609081906001600160401b03811180156117eb57600080fd5b50604051908082528060200260200182016040528015611815578160200160208202803683370190505b50915081516001600160401b038111801561182f57600080fd5b50604051908082528060200260200182016040528015611859578160200160208202803683370190505b50905060005b825181101561193a576004818154811061187557fe5b9060005260206000200160009054906101000a90046001600160a01b031683828151811061189f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060026000866001600160a01b03166001600160a01b0316815260200190815260200160002060008483815181106118f257fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205482828151811061192757fe5b602090810291909101015260010161185f565b5060005b83518110156119cb5783818151811061195357fe5b6020026020010151602001516000141561196c576119c3565b60005b83518110156119c15761199c8685838151811061198857fe5b602002602001015187858151811061178557fe5b8382815181106119a857fe5b602090810291909101018051909101905260010161196f565b505b60010161193e565b509250929050565b8254600090600160581b81046001600160681b031690600160c01b900463ffffffff16421415611a04579050610525565b8454600090611a389083906001600160581b0381169063ffffffff600160c01b8204811691600160e01b9004168989611d81565b9050818114611af5576001600160681b03811115611a685760405162461bcd60e51b815260040161050a90612747565b85546cffffffffffffffffffffffffff60581b1916600160581b6001600160681b038316021763ffffffff60c01b1916600160c01b4263ffffffff16021786556040516001600160a01b0388811691908a16907f7ecfb468c92138c74e6034d3e9d76f99150e483bd53bcc43524ce7056698751f90611ae890859061279d565b60405180910390a36112e4565b855463ffffffff60c01b1916600160c01b4263ffffffff1602178655979650505050505050565b60005b815181101561053a57611b79828281518110611b3757fe5b60200260200101516000015184848481518110611b5057fe5b602002602001015160200151858581518110611b6857fe5b6020026020010151604001516112ef565b600101611b1f565b6000611b8e848484611e05565b9050600181151514611bb25760405162461bcd60e51b815260040161050a906126f3565b50505050565b6001600160a01b0380851660008181526001602081815260408084208987168552808352818520968c168552868401835290842054948452919052600201549092919083908190611c13908a908a9087908a9060ff166119d3565b9050808314611cb2578615611c53576001600160a01b038916600090815260016020526040902060020154611c509088908390869060ff16611e38565b91505b6001600160a01b03808b16600081815260018701602052604090819020849055518a8316928c1691907ff5674975ec2736b27b8d52ea7cafb8bc2761685f31f109e028e1498aa2b2f3e590611ca990869061279d565b60405180910390a45b5098975050505050505050565b80516001600160a01b03908116600090815260016020818152604080842087861685528252808420865190951684529190528082206002015483549185015192939260ff909116918491611d48916001600160681b03600160581b820416916001600160581b0382169163ffffffff600160c01b8204811692600160e01b909204169087611d81565b90506112e48560200151828560010160008b6001600160a01b03166001600160a01b031681526020019081526020016000205485611e38565b6000851580611d8e575082155b80611da1575042856001600160801b0316145b80611db5575083856001600160801b031610155b15611dc1575085611dfb565b6000844211611dd05742611dd2565b845b90506001600160801b0386168103888589830260ff8716600a0a0281611df457fe5b0401925050505b9695505050505050565b6001600160a01b038083166000818152600660205260408120549092611e2e9291168685611e57565b5060019392505050565b60008160ff16600a0a838503860281611e4d57fe5b0495945050505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611bb2908590611ebe826001600160a01b0316612064565b611f0f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310611f4d5780518252601f199092019160209182019101611f2e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611faf576040519150601f19603f3d011682016040523d82523d6000602084013e611fb4565b606091505b50915091508161200b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611bb25780806020019051602081101561202757600080fd5b5051611bb25760405162461bcd60e51b815260040180806020018281038252602a815260200180612858602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061209857508115155b949350505050565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b80356001600160a01b038116811461075557600080fd5b60008083601f8401126120f2578182fd5b5081356001600160401b03811115612108578182fd5b6020830191508360208083028501011115610a0a57600080fd5b600060a08284031215612133578081fd5b60405160a081018181106001600160401b038211171561214f57fe5b60405290508082356001600160581b038116811461216c57600080fd5b815260208381013590820152612184604084016121b2565b6040820152612195606084016120ca565b60608201526121a6608084016120ca565b60808201525092915050565b803563ffffffff8116811461075557600080fd5b6000602082840312156121d7578081fd5b6121e0826120ca565b9392505050565b600080604083850312156121f9578081fd5b612202836120ca565b9150612210602084016120ca565b90509250929050565b60008060006060848603121561222d578081fd5b612236846120ca565b9250612244602085016120ca565b9150612252604085016120ca565b90509250925092565b60008060006060848603121561226f578283fd5b612278846120ca565b9250612286602085016120ca565b9150612252604085016121b2565b6000806000606084860312156122a8578283fd5b6122b1846120ca565b95602085013595506040909401359392505050565b600080602083850312156122d8578182fd5b82356001600160401b038111156122ed578283fd5b6122f9858286016120e1565b90969095509350505050565b600080600060408486031215612319578283fd5b83356001600160401b0381111561232e578384fd5b61233a868287016120e1565b90945092506122529050602085016120ca565b60008060008060608587031215612362578081fd5b84356001600160401b03811115612377578182fd5b612383878288016120e1565b90955093506123969050602086016120ca565b91506123a4604086016120ca565b905092959194509250565b600080600080606085870312156123c4578384fd5b84356001600160401b038111156123d9578485fd5b6123e5878288016120e1565b909550935050602085013591506123a4604086016120ca565b600080600080600060808688031215612415578081fd5b85356001600160401b0381111561242a578182fd5b612436888289016120e1565b9096509450506020860135925061244f604087016120ca565b915061245d606087016120ca565b90509295509295909350565b60008060008060008060a08789031215612481578384fd5b86356001600160401b03811115612496578485fd5b6124a289828a016120e1565b909750955050602087013593506124bb604088016120ca565b92506124c9606088016120ca565b91506124d7608088016120ca565b90509295509295509295565b600060208083850312156124f5578182fd5b82356001600160401b038082111561250b578384fd5b818501915085601f83011261251e578384fd5b81358181111561252a57fe5b61253784858302016127ee565b818152848101925083850160a0808402860187018a1015612556578788fd5b8795505b838610156125825761256c8a83612122565b855260019590950194938601939081019061255a565b509098975050505050505050565b6000602082840312156125a1578081fd5b5051919050565b600080604083850312156125ba578182fd5b505080516020909101519092909150565b6000602082840312156125dc578081fd5b815160ff811681146121e0578182fd5b6000815180845260208085019450808401835b838110156126245781516001600160a01b0316875295820195908201906001016125ff565b509495945050505050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6000602082526121e060208301846125ec565b60006040825261268260408301856125ec565b828103602084810191909152845180835285820192820190845b818110156126b85784518352938301939183019160010161269c565b5090979650505050505050565b602080825260149082015273494e56414c49445f555345525f4144445245535360601b604082015260600190565b6020808252600e908201526d2a2920a729a322a92fa2a92927a960911b604082015260600190565b602080825260129082015271494e56414c49445f544f5f4144445245535360701b604082015260600190565b6020808252600e908201526d496e646578206f766572666c6f7760901b604082015260600190565b60208082526014908201527310d3105253515497d5539055551213d49256915160621b604082015260600190565b90815260200190565b93845260208401929092526040830152606082015260800190565b6001600160581b0392909216825263ffffffff16602082015260400190565b60ff91909116815260200190565b6040518181016001600160401b038111828210171561280957fe5b60405291905056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220ec125919d2e26d0c53b9727952496a47da726b6381dfb9da84ec16851746a87364736f6c63430007050033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101735760003560e01c80637eff4ba8116100de578063bb492bf511610097578063c5a7b53811610071578063c5a7b53814610343578063c664493a14610356578063f2fde38b14610369578063f5cf673b1461037c57610173565b8063bb492bf514610315578063bf90f63a14610328578063c4f59f9b1461033b57610173565b80637eff4ba814610283578063866bc096146102a65780638da5cb5b146102b95780639efd6f72146102c15780639ff55db9146102e1578063af15ec5a1461030257610173565b80635077215511610130578063507721551461020257806357b89883146102155780636657732f1461022857806367eabbc914610248578063715018a61461026857806374d945ec1461027057610173565b80630b0db655146101785780631b839c771461018d578063236300dc146101b657806331873e2e146101c957806333028b99146101dc57806344fd1400146101ef575b600080fd5b61018b6101863660046124e3565b61038f565b005b6101a061019b3660046121e7565b6104aa565b6040516101ad919061279d565b60405180910390f35b6101a06101c43660046123fe565b6104e2565b61018b6101d7366004612294565b61052e565b6101a06101ea366004612469565b61053f565b61018b6101fd3660046121e7565b6105e6565b6101a0610210366004612219565b610695565b6101a06102233660046123af565b6106cf565b61023b6102363660046121c6565b6106e0565b6040516101ad919061265c565b61025b6102563660046121c6565b61075a565b6040516101ad919061262f565b61018b610778565b61025b61027e3660046121c6565b61081a565b6102966102913660046121e7565b610838565b6040516101ad94939291906127a6565b6101a06102b43660046121e7565b610897565b61025b6108c2565b6102d46102cf3660046121c6565b6108d1565b6040516101ad91906127e0565b6102f46102ef36600461234d565b6108f2565b6040516101ad92919061266f565b6101a061031036600461234d565b61099c565b6102f4610323366004612305565b6109b3565b6102f46103363660046122c6565b6109f5565b61023b610a11565b61018b61035136600461225b565b610a73565b6102f4610364366004612305565b610b5a565b61018b6103773660046121c6565b610b71565b61018b61038a3660046121e7565b610c69565b610397610d18565b6000546001600160a01b039081169116146103e7576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b60005b815181101561049d578181815181106103ff57fe5b6020026020010151606001516001600160a01b031663b1bf962d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561044357600080fd5b505afa158015610457573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047b9190612590565b82828151811061048757fe5b60209081029190910181015101526001016103ea565b506104a781610d1c565b50565b6001600160a01b039182166000908152600160209081526040808320939094168252919091522054600160e01b900463ffffffff1690565b60006001600160a01b0383166105135760405162461bcd60e51b815260040161050a9061271b565b60405180910390fd5b610522868686333388886111b9565b90505b95945050505050565b61053a338483856112ef565b505050565b6001600160a01b0380841660009081526005602052604081205490913391869116821461057e5760405162461bcd60e51b815260040161050a9061276f565b6001600160a01b0386166105a45760405162461bcd60e51b815260040161050a906126c5565b6001600160a01b0385166105ca5760405162461bcd60e51b815260040161050a9061271b565b6105d9898989338a8a8a6111b9565b9998505050505050505050565b6105ee610d18565b6000546001600160a01b0390811691161461063e576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b6001600160a01b0381811660009081526006602052604080822080546001600160a01b0319169386169384179055517f28a48cbce43190d77247f342cf319b1607bff4ef716cf26b76cf7bb71baebaa59190a25050565b6001600160a01b03808316600090815260016020818152604080842086861685528252808420948816845293909101905220549392505050565b6000610525858585333333886111b9565b6001600160a01b03811660009081526001602081815260409283902090910180548351818402810184019094528084526060939283018282801561074d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161072f575b505050505090505b919050565b6001600160a01b039081166000908152600660205260409020541690565b610780610d18565b6000546001600160a01b039081169116146107d0576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6001600160a01b039081166000908152600560205260409020541690565b6001600160a01b0391821660009081526001602090815260408083209390941682529190915220546001600160681b03600160581b820416916001600160581b0382169163ffffffff600160c01b8204811692600160e01b9092041690565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6000546001600160a01b031690565b6001600160a01b031660009081526001602052604090206002015460ff1690565b6001600160a01b038083166000908152600560205260409020546060918291339186911682146109345760405162461bcd60e51b815260040161050a9061276f565b6001600160a01b03861661095a5760405162461bcd60e51b815260040161050a906126c5565b6001600160a01b0385166109805760405162461bcd60e51b815260040161050a9061271b565b61098d88883389896113e0565b93509350505094509492505050565b600061052583836109ae8888886115bc565b611742565b6060806001600160a01b0383166109dc5760405162461bcd60e51b815260040161050a9061271b565b6109e985853333876113e0565b91509150935093915050565b606080610a0584843333336113e0565b915091505b9250929050565b60606004805480602002602001604051908101604052809291908181526020018280548015610a6957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a4b575b5050505050905090565b610a7b610d18565b6000546001600160a01b03908116911614610acb576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b6001600160a01b038381166000818152600160209081526040808320948716808452949091529081902080546001600160e01b0316600160e01b63ffffffff871602179081905590517fec44514a2743afadd78647150195ef92fec31e96087fa5cbbcd72e8d131d9a1c91610b4d916001600160581b039091169086906127c1565b60405180910390a3505050565b6060806109e983610b6c8787876115bc565b6117ce565b610b79610d18565b6000546001600160a01b03908116911614610bc9576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b6001600160a01b038116610c0e5760405162461bcd60e51b81526004018080602001828103825260268152602001806128126026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b610c71610d18565b6000546001600160a01b03908116911614610cc1576040805162461bcd60e51b81526020600482018190526024820152600080516020612838833981519152604482015290519081900360640190fd5b6001600160a01b0382811660008181526005602052604080822080546001600160a01b0319169486169485179055517f4925eafc82d0c4d67889898eeed64b18488ab19811e61620f387026dec126a289190a35050565b3390565b60005b81518110156111b557818181518110610d3457fe5b6020026020010151606001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7857600080fd5b505afa158015610d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db091906125cb565b60016000848481518110610dc057fe5b6020026020010151606001516001600160a01b03166001600160a01b0316815260200190815260200160002060020160006101000a81548160ff021916908360ff160217905550600060016000848481518110610e1957fe5b6020026020010151606001516001600160a01b03166001600160a01b031681526020019081526020016000206000016000848481518110610e5657fe5b602090810291909101810151608001516001600160a01b031682528101919091526040016000208054909150600160c01b900463ffffffff16610f1e5760016000848481518110610ea357fe5b6020026020010151606001516001600160a01b03166001600160a01b03168152602001908152602001600020600101838381518110610ede57fe5b6020908102919091018101516080015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b60036000848481518110610f2e57fe5b602090810291909101810151608001516001600160a01b031682528101919091526040016000205460ff1661100057600160036000858581518110610f6f57fe5b6020026020010151608001516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055506004838381518110610fc057fe5b6020908102919091018101516080015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b61108f83838151811061100f57fe5b60200260200101516060015184848151811061102757fe5b6020026020010151608001518386868151811061104057fe5b6020026020010151602001516001600089898151811061105c57fe5b602090810291909101810151606001516001600160a01b031682528101919091526040016000206002015460ff166119d3565b5082828151811061109c57fe5b60209081029190910101515181546affffffffffffffffffffff19166001600160581b0390911617815582518390839081106110d457fe5b602090810291909101015160400151815463ffffffff909116600160e01b026001600160e01b03909116178155825183908390811061110f57fe5b6020026020010151608001516001600160a01b031683838151811061113057fe5b6020026020010151606001516001600160a01b03167fec44514a2743afadd78647150195ef92fec31e96087fa5cbbcd72e8d131d9a1c85858151811061117257fe5b60200260200101516000015186868151811061118a57fe5b6020026020010151604001516040516111a49291906127c1565b60405180910390a350600101610d1f565b5050565b6000856111c8575060006112e4565b6001600160a01b03808516600090815260026020908152604080832093861683529290522054808711156112325761120a856112058b8b896115bc565b611b1c565b506001600160a01b038085166000908152600260209081526040808320938616835292905220545b806112415760009150506112e4565b60008188116112505787611252565b815b6001600160a01b03808816600090815260026020908152604080832093891683529290522081840390559050611289858583611b81565b846001600160a01b0316846001600160a01b0316876001600160a01b03167fc052130bc4ef84580db505783484b067ea8b71b3bca78a7e12db7aea8658f0048a856040516112d8929190612643565b60405180910390a49150505b979650505050505050565b60005b6001600160a01b038516600090815260016020819052604090912001548110156113d9576001600160a01b038516600090815260016020819052604082200180548390811061133d57fe5b60009182526020822001546001600160a01b031691506113608688848888611bb8565b905080156113cf576001600160a01b0380871660008181526002602090815260408083209487168084529490915290819020805485019055517f68ac6b4d0eeedccf3df154188dfac62d18d2ac5eaac52ecd6e728e33ce75a1d4906113c690859061279d565b60405180910390a35b50506001016112f2565b5050505050565b6060806113f2846112058989886115bc565b6004546001600160401b038111801561140a57600080fd5b50604051908082528060200260200182016040528015611434578160200160208202803683370190505b506004549092506001600160401b038111801561145057600080fd5b5060405190808252806020026020018201604052801561147a578160200160208202803683370190505b50905060005b6004548110156115b15760006004828154811061149957fe5b60009182526020808320909101546001600160a01b0389811684526002835260408085209190921680855292529091205485519192509082908690859081106114de57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508084848151811061150b57fe5b602090810291909101015280156115a7576001600160a01b03808816600090815260026020908152604080832093861683529290529081205561154f868383611b81565b856001600160a01b0316826001600160a01b0316886001600160a01b03167fc052130bc4ef84580db505783484b067ea8b71b3bca78a7e12db7aea8658f0048b8560405161159e929190612643565b60405180910390a45b5050600101611480565b509550959350505050565b6060826001600160401b03811180156115d457600080fd5b5060405190808252806020026020018201604052801561160e57816020015b6115fb6120a0565b8152602001906001900390816115f35790505b50905060005b8381101561173a5784848281811061162857fe5b905060200201602081019061163d91906121c6565b82828151811061164957fe5b60209081029190910101516001600160a01b03909116905284848281811061166d57fe5b905060200201602081019061168291906121c6565b6001600160a01b0316630afbcdc9846040518263ffffffff1660e01b81526004016116ad919061262f565b604080518083038186803b1580156116c457600080fd5b505afa1580156116d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fc91906125a8565b83838151811061170857fe5b602002602001015160200184848151811061171f57fe5b60209081029190910101516040019190915252600101611614565b509392505050565b6000805b825181101561179f5782818151811061175b57fe5b6020026020010151602001516000141561177457611797565b611792858585848151811061178557fe5b6020026020010151611cbf565b820191505b600101611746565b506001600160a01b03808516600090815260026020908152604080832093871683529290522054019392505050565b60045460609081906001600160401b03811180156117eb57600080fd5b50604051908082528060200260200182016040528015611815578160200160208202803683370190505b50915081516001600160401b038111801561182f57600080fd5b50604051908082528060200260200182016040528015611859578160200160208202803683370190505b50905060005b825181101561193a576004818154811061187557fe5b9060005260206000200160009054906101000a90046001600160a01b031683828151811061189f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060026000866001600160a01b03166001600160a01b0316815260200190815260200160002060008483815181106118f257fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205482828151811061192757fe5b602090810291909101015260010161185f565b5060005b83518110156119cb5783818151811061195357fe5b6020026020010151602001516000141561196c576119c3565b60005b83518110156119c15761199c8685838151811061198857fe5b602002602001015187858151811061178557fe5b8382815181106119a857fe5b602090810291909101018051909101905260010161196f565b505b60010161193e565b509250929050565b8254600090600160581b81046001600160681b031690600160c01b900463ffffffff16421415611a04579050610525565b8454600090611a389083906001600160581b0381169063ffffffff600160c01b8204811691600160e01b9004168989611d81565b9050818114611af5576001600160681b03811115611a685760405162461bcd60e51b815260040161050a90612747565b85546cffffffffffffffffffffffffff60581b1916600160581b6001600160681b038316021763ffffffff60c01b1916600160c01b4263ffffffff16021786556040516001600160a01b0388811691908a16907f7ecfb468c92138c74e6034d3e9d76f99150e483bd53bcc43524ce7056698751f90611ae890859061279d565b60405180910390a36112e4565b855463ffffffff60c01b1916600160c01b4263ffffffff1602178655979650505050505050565b60005b815181101561053a57611b79828281518110611b3757fe5b60200260200101516000015184848481518110611b5057fe5b602002602001015160200151858581518110611b6857fe5b6020026020010151604001516112ef565b600101611b1f565b6000611b8e848484611e05565b9050600181151514611bb25760405162461bcd60e51b815260040161050a906126f3565b50505050565b6001600160a01b0380851660008181526001602081815260408084208987168552808352818520968c168552868401835290842054948452919052600201549092919083908190611c13908a908a9087908a9060ff166119d3565b9050808314611cb2578615611c53576001600160a01b038916600090815260016020526040902060020154611c509088908390869060ff16611e38565b91505b6001600160a01b03808b16600081815260018701602052604090819020849055518a8316928c1691907ff5674975ec2736b27b8d52ea7cafb8bc2761685f31f109e028e1498aa2b2f3e590611ca990869061279d565b60405180910390a45b5098975050505050505050565b80516001600160a01b03908116600090815260016020818152604080842087861685528252808420865190951684529190528082206002015483549185015192939260ff909116918491611d48916001600160681b03600160581b820416916001600160581b0382169163ffffffff600160c01b8204811692600160e01b909204169087611d81565b90506112e48560200151828560010160008b6001600160a01b03166001600160a01b031681526020019081526020016000205485611e38565b6000851580611d8e575082155b80611da1575042856001600160801b0316145b80611db5575083856001600160801b031610155b15611dc1575085611dfb565b6000844211611dd05742611dd2565b845b90506001600160801b0386168103888589830260ff8716600a0a0281611df457fe5b0401925050505b9695505050505050565b6001600160a01b038083166000818152600660205260408120549092611e2e9291168685611e57565b5060019392505050565b60008160ff16600a0a838503860281611e4d57fe5b0495945050505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611bb2908590611ebe826001600160a01b0316612064565b611f0f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310611f4d5780518252601f199092019160209182019101611f2e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611faf576040519150601f19603f3d011682016040523d82523d6000602084013e611fb4565b606091505b50915091508161200b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611bb25780806020019051602081101561202757600080fd5b5051611bb25760405162461bcd60e51b815260040180806020018281038252602a815260200180612858602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061209857508115155b949350505050565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b80356001600160a01b038116811461075557600080fd5b60008083601f8401126120f2578182fd5b5081356001600160401b03811115612108578182fd5b6020830191508360208083028501011115610a0a57600080fd5b600060a08284031215612133578081fd5b60405160a081018181106001600160401b038211171561214f57fe5b60405290508082356001600160581b038116811461216c57600080fd5b815260208381013590820152612184604084016121b2565b6040820152612195606084016120ca565b60608201526121a6608084016120ca565b60808201525092915050565b803563ffffffff8116811461075557600080fd5b6000602082840312156121d7578081fd5b6121e0826120ca565b9392505050565b600080604083850312156121f9578081fd5b612202836120ca565b9150612210602084016120ca565b90509250929050565b60008060006060848603121561222d578081fd5b612236846120ca565b9250612244602085016120ca565b9150612252604085016120ca565b90509250925092565b60008060006060848603121561226f578283fd5b612278846120ca565b9250612286602085016120ca565b9150612252604085016121b2565b6000806000606084860312156122a8578283fd5b6122b1846120ca565b95602085013595506040909401359392505050565b600080602083850312156122d8578182fd5b82356001600160401b038111156122ed578283fd5b6122f9858286016120e1565b90969095509350505050565b600080600060408486031215612319578283fd5b83356001600160401b0381111561232e578384fd5b61233a868287016120e1565b90945092506122529050602085016120ca565b60008060008060608587031215612362578081fd5b84356001600160401b03811115612377578182fd5b612383878288016120e1565b90955093506123969050602086016120ca565b91506123a4604086016120ca565b905092959194509250565b600080600080606085870312156123c4578384fd5b84356001600160401b038111156123d9578485fd5b6123e5878288016120e1565b909550935050602085013591506123a4604086016120ca565b600080600080600060808688031215612415578081fd5b85356001600160401b0381111561242a578182fd5b612436888289016120e1565b9096509450506020860135925061244f604087016120ca565b915061245d606087016120ca565b90509295509295909350565b60008060008060008060a08789031215612481578384fd5b86356001600160401b03811115612496578485fd5b6124a289828a016120e1565b909750955050602087013593506124bb604088016120ca565b92506124c9606088016120ca565b91506124d7608088016120ca565b90509295509295509295565b600060208083850312156124f5578182fd5b82356001600160401b038082111561250b578384fd5b818501915085601f83011261251e578384fd5b81358181111561252a57fe5b61253784858302016127ee565b818152848101925083850160a0808402860187018a1015612556578788fd5b8795505b838610156125825761256c8a83612122565b855260019590950194938601939081019061255a565b509098975050505050505050565b6000602082840312156125a1578081fd5b5051919050565b600080604083850312156125ba578182fd5b505080516020909101519092909150565b6000602082840312156125dc578081fd5b815160ff811681146121e0578182fd5b6000815180845260208085019450808401835b838110156126245781516001600160a01b0316875295820195908201906001016125ff565b509495945050505050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6000602082526121e060208301846125ec565b60006040825261268260408301856125ec565b828103602084810191909152845180835285820192820190845b818110156126b85784518352938301939183019160010161269c565b5090979650505050505050565b602080825260149082015273494e56414c49445f555345525f4144445245535360601b604082015260600190565b6020808252600e908201526d2a2920a729a322a92fa2a92927a960911b604082015260600190565b602080825260129082015271494e56414c49445f544f5f4144445245535360701b604082015260600190565b6020808252600e908201526d496e646578206f766572666c6f7760901b604082015260600190565b60208082526014908201527310d3105253515497d5539055551213d49256915160621b604082015260600190565b90815260200190565b93845260208401929092526040830152606082015260800190565b6001600160581b0392909216825263ffffffff16602082015260400190565b60ff91909116815260200190565b6040518181016001600160401b038111828210171561280957fe5b60405291905056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220ec125919d2e26d0c53b9727952496a47da726b6381dfb9da84ec16851746a87364736f6c63430007050033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.