Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ButtonToken
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.4;
import {IOracle} from "./interfaces/IOracle.sol";
import "./interfaces/IButtonToken.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
/**
* @title The ButtonToken ERC20 wrapper.
*
* @dev The ButtonToken is a rebasing wrapper for fixed balance ERC-20 tokens.
*
* Users deposit the "underlying" (wrapped) tokens and are
* minted button (wrapper) tokens with elastic balances
* which change up or down when the value of the underlying token changes.
*
* For example: Manny “wraps” 1 Ether when the price of Ether is $1800.
* Manny receives 1800 ButtonEther tokens in return.
* The overall value of their ButtonEther is the same as their original Ether,
* however each unit is now priced at exactly $1. The next day,
* the price of Ether changes to $1900. The ButtonEther system detects
* this price change, and rebases such that Manny’s balance is
* now 1900 ButtonEther tokens, still priced at $1 each.
*
* The ButtonToken math is almost identical to Ampleforth's μFragments.
*
* For AMPL, internal balances are represented using `gons` and
* -> internal account balance `_gonBalances[account]`
* -> internal supply scalar `gonsPerFragment = TOTAL_GONS / _totalSupply`
* -> public balance `_gonBalances[account] * gonsPerFragment`
* -> public total supply `_totalSupply`
*
* In our case internal balances are stored as 'bits'.
* -> underlying token unit price `p_u = price / 10 ^ (PRICE_DECIMALS)`
* -> total underlying tokens `_totalUnderlying`
* -> internal account balance `_accountBits[account]`
* -> internal supply scalar `_bitsPerToken`
` = TOTAL_BITS / (MAX_UNDERLYING*p_u)`
* ` = BITS_PER_UNDERLYING*(10^PRICE_DECIMALS)/price`
* ` = PRICE_BITS / price`
* -> user's underlying balance `(_accountBits[account] / BITS_PER_UNDERLYING`
* -> public balance `_accountBits[account] * _bitsPerToken`
* -> public total supply `_totalUnderlying * p_u`
*
*
*/
contract ButtonToken is IButtonToken, Initializable, OwnableUpgradeable {
// PLEASE READ BEFORE CHANGING ANY ACCOUNTING OR MATH
// We make the following guarantees:
// - If address 'A' transfers x button tokens to address 'B'.
// A's resulting external balance will be decreased by "precisely" x button tokens,
// and B's external balance will be "precisely" increased by x button tokens.
// - If address 'A' deposits y underlying tokens,
// A's resulting underlying balance will increase by "precisely" y.
// - If address 'A' withdraws y underlying tokens,
// A's resulting underlying balance will decrease by "precisely" y.
//
using SafeERC20 for IERC20;
//--------------------------------------------------------------------------
// Constants
/// @dev Math constants.
uint256 private constant MAX_UINT256 = type(uint256).max;
/// @dev The maximum units of the underlying token that can be deposited into this contract
/// ie) for a underlying token with 18 decimals, MAX_UNDERLYING is 1B tokens.
uint256 public constant MAX_UNDERLYING = 1_000_000_000e18;
/// @dev TOTAL_BITS is a multiple of MAX_UNDERLYING so that {BITS_PER_UNDERLYING} is an integer.
/// Use the highest value that fits in a uint256 for max granularity.
uint256 private constant TOTAL_BITS = MAX_UINT256 - (MAX_UINT256 % MAX_UNDERLYING);
/// @dev Number of BITS per unit of deposit.
uint256 private constant BITS_PER_UNDERLYING = TOTAL_BITS / MAX_UNDERLYING;
//--------------------------------------------------------------------------
// Attributes
/// @inheritdoc IButtonWrapper
address public override underlying;
/// @inheritdoc IButtonToken
address public override oracle;
/// @inheritdoc IButtonToken
uint256 public override lastPrice;
/// @dev Rebase counter
uint256 _epoch;
/// @inheritdoc IERC20Metadata
string public override name;
/// @inheritdoc IERC20Metadata
string public override symbol;
/// @dev Number of BITS per unit of deposit * (1 USD).
uint256 private priceBits;
/// @dev trueMaxPrice = maximum integer < (sqrt(4*priceBits + 1) - 1) / 2
/// maxPrice is the closest power of two which is just under trueMaxPrice.
uint256 private maxPrice;
/// @dev internal balance, bits issued per account
mapping(address => uint256) private _accountBits;
/// @dev ERC20 allowances
mapping(address => mapping(address => uint256)) private _allowances;
//--------------------------------------------------------------------------
// Modifiers
modifier validRecipient(address to) {
require(to != address(0x0), "ButtonToken: recipient zero address");
require(to != address(this), "ButtonToken: recipient token address");
_;
}
modifier onAfterRebase() {
uint256 price;
bool valid;
(price, valid) = _queryPrice();
if (valid) {
_rebase(price);
}
_;
}
//--------------------------------------------------------------------------
/// @param underlying_ The underlying ERC20 token address.
/// @param name_ The ERC20 name.
/// @param symbol_ The ERC20 symbol.
/// @param oracle_ The oracle which provides the underlying token price.
function initialize(
address underlying_,
string memory name_,
string memory symbol_,
address oracle_
) public override initializer {
require(underlying_ != address(0), "ButtonToken: invalid underlying reference");
// Initializing ownership to `msg.sender`
__Ownable_init();
underlying = underlying_;
name = name_;
symbol = symbol_;
// MAX_UNDERLYING worth bits are 'pre-mined' to `address(0x)`
// at the time of construction.
//
// During mint, bits are transferred from `address(0x)`
// and during burn, bits are transferred back to `address(0x)`.
//
// No more than MAX_UNDERLYING can be deposited into the ButtonToken contract.
_accountBits[address(0)] = TOTAL_BITS;
updateOracle(oracle_);
}
//--------------------------------------------------------------------------
// Owner only actions
/// @inheritdoc IButtonToken
function updateOracle(address oracle_) public override onlyOwner {
uint256 price;
bool valid;
oracle = oracle_;
(price, valid) = _queryPrice();
require(valid, "ButtonToken: unable to fetch data from oracle");
uint256 priceDecimals = IOracle(oracle).priceDecimals();
priceBits = BITS_PER_UNDERLYING * (10 ** priceDecimals);
maxPrice = maxPriceFromPriceDecimals(priceDecimals);
emit OracleUpdated(oracle);
_rebase(price);
}
//--------------------------------------------------------------------------
// ERC20 description attributes
/// @inheritdoc IERC20Metadata
function decimals() external view override returns (uint8) {
return IERC20Metadata(underlying).decimals();
}
//--------------------------------------------------------------------------
// ERC-20 token view methods
/// @inheritdoc IERC20
function totalSupply() external view override returns (uint256) {
uint256 price;
(price, ) = _queryPrice();
return _bitsToAmount(_activeBits(), price);
}
/// @inheritdoc IERC20
function balanceOf(address account) external view override returns (uint256) {
if (account == address(0)) {
return 0;
}
uint256 price;
(price, ) = _queryPrice();
return _bitsToAmount(_accountBits[account], price);
}
/// @inheritdoc IRebasingERC20
function scaledTotalSupply() external view override returns (uint256) {
return _bitsToUAmount(_activeBits());
}
/// @inheritdoc IRebasingERC20
function scaledBalanceOf(address account) external view override returns (uint256) {
if (account == address(0)) {
return 0;
}
return _bitsToUAmount(_accountBits[account]);
}
/// @inheritdoc IERC20
function allowance(address owner_, address spender) external view override returns (uint256) {
return _allowances[owner_][spender];
}
//--------------------------------------------------------------------------
// ButtonWrapper view methods
/// @inheritdoc IButtonWrapper
function totalUnderlying() external view override returns (uint256) {
return _bitsToUAmount(_activeBits());
}
/// @inheritdoc IButtonWrapper
function balanceOfUnderlying(address who) external view override returns (uint256) {
if (who == address(0)) {
return 0;
}
return _bitsToUAmount(_accountBits[who]);
}
/// @inheritdoc IButtonWrapper
function underlyingToWrapper(uint256 uAmount) external view override returns (uint256) {
uint256 price;
(price, ) = _queryPrice();
return _bitsToAmount(_uAmountToBits(uAmount), price);
}
/// @inheritdoc IButtonWrapper
function wrapperToUnderlying(uint256 amount) external view override returns (uint256) {
uint256 price;
(price, ) = _queryPrice();
return _bitsToUAmount(_amountToBits(amount, price));
}
//--------------------------------------------------------------------------
// ERC-20 write methods
/// @inheritdoc IERC20
function transfer(
address to,
uint256 amount
) external override validRecipient(to) onAfterRebase returns (bool) {
_transfer(_msgSender(), to, _amountToBits(amount, lastPrice), amount);
return true;
}
/// @inheritdoc IRebasingERC20
function transferAll(
address to
) external override validRecipient(to) onAfterRebase returns (bool) {
uint256 bits = _accountBits[_msgSender()];
_transfer(_msgSender(), to, bits, _bitsToAmount(bits, lastPrice));
return true;
}
/// @inheritdoc IERC20
function transferFrom(
address from,
address to,
uint256 amount
) external override validRecipient(to) onAfterRebase returns (bool) {
if (_allowances[from][_msgSender()] != type(uint256).max) {
_allowances[from][_msgSender()] -= amount;
emit Approval(from, _msgSender(), _allowances[from][_msgSender()]);
}
_transfer(from, to, _amountToBits(amount, lastPrice), amount);
return true;
}
/// @inheritdoc IRebasingERC20
function transferAllFrom(
address from,
address to
) external override validRecipient(to) onAfterRebase returns (bool) {
uint256 bits = _accountBits[from];
uint256 amount = _bitsToAmount(bits, lastPrice);
if (_allowances[from][_msgSender()] != type(uint256).max) {
_allowances[from][_msgSender()] -= amount;
emit Approval(from, _msgSender(), _allowances[from][_msgSender()]);
}
_transfer(from, to, bits, amount);
return true;
}
/// @inheritdoc IERC20
function approve(address spender, uint256 amount) external override returns (bool) {
_allowances[_msgSender()][spender] = amount;
emit Approval(_msgSender(), spender, amount);
return true;
}
// @inheritdoc IERC20
function increaseAllowance(address spender, uint256 addedAmount) external returns (bool) {
_allowances[_msgSender()][spender] += addedAmount;
emit Approval(_msgSender(), spender, _allowances[_msgSender()][spender]);
return true;
}
// @inheritdoc IERC20
function decreaseAllowance(address spender, uint256 subtractedAmount) external returns (bool) {
if (subtractedAmount >= _allowances[_msgSender()][spender]) {
delete _allowances[_msgSender()][spender];
} else {
_allowances[_msgSender()][spender] -= subtractedAmount;
}
emit Approval(_msgSender(), spender, _allowances[_msgSender()][spender]);
return true;
}
//--------------------------------------------------------------------------
// RebasingERC20 write methods
/// @inheritdoc IRebasingERC20
function rebase() external override onAfterRebase {
return;
}
//--------------------------------------------------------------------------
// ButtonWrapper write methods
/// @inheritdoc IButtonWrapper
function mint(uint256 amount) external override onAfterRebase returns (uint256) {
uint256 bits = _amountToBits(amount, lastPrice);
uint256 uAmount = _bitsToUAmount(bits);
_deposit(_msgSender(), _msgSender(), uAmount, amount, bits);
return uAmount;
}
/// @inheritdoc IButtonWrapper
function mintFor(address to, uint256 amount) external override onAfterRebase returns (uint256) {
uint256 bits = _amountToBits(amount, lastPrice);
uint256 uAmount = _bitsToUAmount(bits);
_deposit(_msgSender(), to, uAmount, amount, bits);
return uAmount;
}
/// @inheritdoc IButtonWrapper
function burn(uint256 amount) external override onAfterRebase returns (uint256) {
uint256 bits = _amountToBits(amount, lastPrice);
uint256 uAmount = _bitsToUAmount(bits);
_withdraw(_msgSender(), _msgSender(), uAmount, amount, bits);
return uAmount;
}
/// @inheritdoc IButtonWrapper
function burnTo(address to, uint256 amount) external override onAfterRebase returns (uint256) {
uint256 bits = _amountToBits(amount, lastPrice);
uint256 uAmount = _bitsToUAmount(bits);
_withdraw(_msgSender(), to, uAmount, amount, bits);
return uAmount;
}
/// @inheritdoc IButtonWrapper
function burnAll() external override onAfterRebase returns (uint256) {
uint256 bits = _accountBits[_msgSender()];
uint256 uAmount = _bitsToUAmount(bits);
uint256 amount = _bitsToAmount(bits, lastPrice);
_withdraw(_msgSender(), _msgSender(), uAmount, amount, bits);
return uAmount;
}
/// @inheritdoc IButtonWrapper
function burnAllTo(address to) external override onAfterRebase returns (uint256) {
uint256 bits = _accountBits[_msgSender()];
uint256 uAmount = _bitsToUAmount(bits);
uint256 amount = _bitsToAmount(bits, lastPrice);
_withdraw(_msgSender(), to, uAmount, amount, bits);
return uAmount;
}
/// @inheritdoc IButtonWrapper
function deposit(uint256 uAmount) external override onAfterRebase returns (uint256) {
uint256 bits = _uAmountToBits(uAmount);
uint256 amount = _bitsToAmount(bits, lastPrice);
_deposit(_msgSender(), _msgSender(), uAmount, amount, bits);
return amount;
}
/// @inheritdoc IButtonWrapper
function depositFor(
address to,
uint256 uAmount
) external override onAfterRebase returns (uint256) {
uint256 bits = _uAmountToBits(uAmount);
uint256 amount = _bitsToAmount(bits, lastPrice);
_deposit(_msgSender(), to, uAmount, amount, bits);
return amount;
}
/// @inheritdoc IButtonWrapper
function withdraw(uint256 uAmount) external override onAfterRebase returns (uint256) {
uint256 bits = _uAmountToBits(uAmount);
uint256 amount = _bitsToAmount(bits, lastPrice);
_withdraw(_msgSender(), _msgSender(), uAmount, amount, bits);
return amount;
}
/// @inheritdoc IButtonWrapper
function withdrawTo(
address to,
uint256 uAmount
) external override onAfterRebase returns (uint256) {
uint256 bits = _uAmountToBits(uAmount);
uint256 amount = _bitsToAmount(bits, lastPrice);
_withdraw(_msgSender(), to, uAmount, amount, bits);
return amount;
}
/// @inheritdoc IButtonWrapper
function withdrawAll() external override onAfterRebase returns (uint256) {
uint256 bits = _accountBits[_msgSender()];
uint256 uAmount = _bitsToUAmount(bits);
uint256 amount = _bitsToAmount(bits, lastPrice);
_withdraw(_msgSender(), _msgSender(), uAmount, amount, bits);
return amount;
}
/// @inheritdoc IButtonWrapper
function withdrawAllTo(address to) external override onAfterRebase returns (uint256) {
uint256 bits = _accountBits[_msgSender()];
uint256 uAmount = _bitsToUAmount(bits);
uint256 amount = _bitsToAmount(bits, lastPrice);
_withdraw(_msgSender(), to, uAmount, amount, bits);
return amount;
}
//--------------------------------------------------------------------------
// Private methods
/// @dev Internal method to commit deposit state.
/// NOTE: Expects bits, uAmount, amount to be pre-calculated.
function _deposit(
address from,
address to,
uint256 uAmount,
uint256 amount,
uint256 bits
) private {
require(uAmount > 0, "ButtonToken: No tokens deposited");
require(amount > 0, "ButtonToken: too few button tokens to mint");
IERC20(underlying).safeTransferFrom(from, address(this), uAmount);
_transfer(address(0), to, bits, amount);
}
/// @dev Internal method to commit withdraw state.
/// NOTE: Expects bits, uAmount, amount to be pre-calculated.
function _withdraw(
address from,
address to,
uint256 uAmount,
uint256 amount,
uint256 bits
) private {
require(amount > 0, "ButtonToken: too few button tokens to burn");
_transfer(from, address(0), bits, amount);
IERC20(underlying).safeTransfer(to, uAmount);
}
/// @dev Internal method to commit transfer state.
/// NOTE: Expects bits/amounts to be pre-calculated.
function _transfer(address from, address to, uint256 bits, uint256 amount) private {
_accountBits[from] -= bits;
_accountBits[to] += bits;
emit Transfer(from, to, amount);
if (_accountBits[from] == 0) {
delete _accountBits[from];
}
}
/// @dev Updates the `lastPrice` and recomputes the internal scalar.
function _rebase(uint256 price) private {
uint256 _maxPrice = maxPrice;
if (price > _maxPrice) {
price = _maxPrice;
}
lastPrice = price;
_epoch++;
emit Rebase(_epoch, price);
}
/// @dev Returns the active "un-mined" bits
function _activeBits() private view returns (uint256) {
return TOTAL_BITS - _accountBits[address(0)];
}
/// @dev Queries the oracle for the latest price
/// If fetched oracle price isn't valid returns the last price,
/// else returns the new price from the oracle.
function _queryPrice() private view returns (uint256, bool) {
uint256 newPrice;
bool valid;
(newPrice, valid) = IOracle(oracle).getData();
// Note: we consider newPrice == 0 to be invalid because accounting fails with price == 0
// For example, _bitsPerToken needs to be able to divide by price so a div/0 is caused
return (valid && newPrice > 0 ? newPrice : lastPrice, valid && newPrice > 0);
}
/// @dev Convert button token amount to bits.
function _amountToBits(uint256 amount, uint256 price) private view returns (uint256) {
return amount * _bitsPerToken(price);
}
/// @dev Convert underlying token amount to bits.
function _uAmountToBits(uint256 uAmount) private pure returns (uint256) {
return uAmount * BITS_PER_UNDERLYING;
}
/// @dev Convert bits to button token amount.
function _bitsToAmount(uint256 bits, uint256 price) private view returns (uint256) {
return bits / _bitsPerToken(price);
}
/// @dev Convert bits to underlying token amount.
function _bitsToUAmount(uint256 bits) private pure returns (uint256) {
return bits / BITS_PER_UNDERLYING;
}
/// @dev Internal scalar to convert bits to button tokens.
function _bitsPerToken(uint256 price) private view returns (uint256) {
return priceBits / price;
}
/// @dev Derives max-price based on price-decimals
function maxPriceFromPriceDecimals(uint256 priceDecimals) private pure returns (uint256) {
require(priceDecimals <= 18, "ButtonToken: Price Decimals must be under 18");
// Given that 18,8,6 are the most common price decimals, we optimize for those cases
if (priceDecimals == 18) {
return 2 ** 113 - 1;
}
if (priceDecimals == 8) {
return 2 ** 96 - 1;
}
if (priceDecimals == 6) {
return 2 ** 93 - 1;
}
if (priceDecimals == 0) {
return 2 ** 83 - 1;
}
if (priceDecimals == 1) {
return 2 ** 84 - 1;
}
if (priceDecimals == 2) {
return 2 ** 86 - 1;
}
if (priceDecimals == 3) {
return 2 ** 88 - 1;
}
if (priceDecimals == 4) {
return 2 ** 89 - 1;
}
if (priceDecimals == 5) {
return 2 ** 91 - 1;
}
if (priceDecimals == 7) {
return 2 ** 94 - 1;
}
if (priceDecimals == 9) {
return 2 ** 98 - 1;
}
if (priceDecimals == 10) {
return 2 ** 99 - 1;
}
if (priceDecimals == 11) {
return 2 ** 101 - 1;
}
if (priceDecimals == 12) {
return 2 ** 103 - 1;
}
if (priceDecimals == 13) {
return 2 ** 104 - 1;
}
if (priceDecimals == 14) {
return 2 ** 106 - 1;
}
if (priceDecimals == 15) {
return 2 ** 108 - 1;
}
if (priceDecimals == 16) {
return 2 ** 109 - 1;
}
// priceDecimals == 17
return 2 ** 111 - 1;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.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.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual 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 {
_setOwner(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");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: GPL-3.0-or-later
import "./IRebasingERC20.sol";
import "./IButtonWrapper.sol";
// Interface definition for the ButtonToken ERC20 wrapper contract
interface IButtonToken is IButtonWrapper, IRebasingERC20 {
/// @dev The reference to the oracle which feeds in the
/// price of the underlying token.
function oracle() external view returns (address);
/// @dev Most recent price recorded from the oracle.
function lastPrice() external view returns (uint256);
/// @dev Update reference to the oracle contract and resets price.
/// @param oracle_ The address of the new oracle.
function updateOracle(address oracle_) external;
/// @dev Log to record changes to the oracle.
/// @param oracle The address of the new oracle.
event OracleUpdated(address oracle);
/// @dev Contract initializer
function initialize(
address underlying_,
string memory name_,
string memory symbol_,
address oracle_
) external;
}// SPDX-License-Identifier: GPL-3.0-or-later
// Interface definition for ButtonWrapper contract, which wraps an
// underlying ERC20 token into a new ERC20 with different characteristics.
// NOTE: "uAmount" => underlying token (wrapped) amount and
// "amount" => wrapper token amount
interface IButtonWrapper {
//--------------------------------------------------------------------------
// ButtonWrapper write methods
/// @notice Transfers underlying tokens from {msg.sender} to the contract and
/// mints wrapper tokens.
/// @param amount The amount of wrapper tokens to mint.
/// @return The amount of underlying tokens deposited.
function mint(uint256 amount) external returns (uint256);
/// @notice Transfers underlying tokens from {msg.sender} to the contract and
/// mints wrapper tokens to the specified beneficiary.
/// @param to The beneficiary account.
/// @param amount The amount of wrapper tokens to mint.
/// @return The amount of underlying tokens deposited.
function mintFor(address to, uint256 amount) external returns (uint256);
/// @notice Burns wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @param amount The amount of wrapper tokens to burn.
/// @return The amount of underlying tokens withdrawn.
function burn(uint256 amount) external returns (uint256);
/// @notice Burns wrapper tokens from {msg.sender} and transfers
/// the underlying tokens to the specified beneficiary.
/// @param to The beneficiary account.
/// @param amount The amount of wrapper tokens to burn.
/// @return The amount of underlying tokens withdrawn.
function burnTo(address to, uint256 amount) external returns (uint256);
/// @notice Burns all wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @return The amount of underlying tokens withdrawn.
function burnAll() external returns (uint256);
/// @notice Burns all wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @param to The beneficiary account.
/// @return The amount of underlying tokens withdrawn.
function burnAllTo(address to) external returns (uint256);
/// @notice Transfers underlying tokens from {msg.sender} to the contract and
/// mints wrapper tokens to the specified beneficiary.
/// @param uAmount The amount of underlying tokens to deposit.
/// @return The amount of wrapper tokens mint.
function deposit(uint256 uAmount) external returns (uint256);
/// @notice Transfers underlying tokens from {msg.sender} to the contract and
/// mints wrapper tokens to the specified beneficiary.
/// @param to The beneficiary account.
/// @param uAmount The amount of underlying tokens to deposit.
/// @return The amount of wrapper tokens mint.
function depositFor(address to, uint256 uAmount) external returns (uint256);
/// @notice Burns wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @param uAmount The amount of underlying tokens to withdraw.
/// @return The amount of wrapper tokens burnt.
function withdraw(uint256 uAmount) external returns (uint256);
/// @notice Burns wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back to the specified beneficiary.
/// @param to The beneficiary account.
/// @param uAmount The amount of underlying tokens to withdraw.
/// @return The amount of wrapper tokens burnt.
function withdrawTo(address to, uint256 uAmount) external returns (uint256);
/// @notice Burns all wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @return The amount of wrapper tokens burnt.
function withdrawAll() external returns (uint256);
/// @notice Burns all wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @param to The beneficiary account.
/// @return The amount of wrapper tokens burnt.
function withdrawAllTo(address to) external returns (uint256);
//--------------------------------------------------------------------------
// ButtonWrapper view methods
/// @return The address of the underlying token.
function underlying() external view returns (address);
/// @return The total underlying tokens held by the wrapper contract.
function totalUnderlying() external view returns (uint256);
/// @param who The account address.
/// @return The underlying token balance of the account.
function balanceOfUnderlying(address who) external view returns (uint256);
/// @param uAmount The amount of underlying tokens.
/// @return The amount of wrapper tokens exchangeable.
function underlyingToWrapper(uint256 uAmount) external view returns (uint256);
/// @param amount The amount of wrapper tokens.
/// @return The amount of underlying tokens exchangeable.
function wrapperToUnderlying(uint256 amount) external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0-or-later
interface IOracle {
function priceDecimals() external view returns (uint256);
function getData() external view returns (uint256, bool);
}// SPDX-License-Identifier: GPL-3.0-or-later
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
// Interface definition for Rebasing ERC20 tokens which have a "elastic" external
// balance and "fixed" internal balance. Each user's external balance is
// represented as a product of a "scalar" and the user's internal balance.
//
// From time to time the "Rebase" event updates scaler,
// which increases/decreases all user balances proportionally.
//
// The standard ERC-20 methods are denominated in the elastic balance
//
interface IRebasingERC20 is IERC20, IERC20Metadata {
/// @notice Returns the fixed balance of the specified address.
/// @param who The address to query.
function scaledBalanceOf(address who) external view returns (uint256);
/// @notice Returns the total fixed supply.
function scaledTotalSupply() external view returns (uint256);
/// @notice Transfer all of the sender's balance to a specified address.
/// @param to The address to transfer to.
/// @return True on success, false otherwise.
function transferAll(address to) external returns (bool);
/// @notice Transfer all balance tokens from one address to another.
/// @param from The address to send tokens from.
/// @param to The address to transfer to.
function transferAllFrom(address from, address to) external returns (bool);
/// @notice Triggers the next rebase, if applicable.
function rebase() external;
/// @notice Event emitted when the balance scalar is updated.
/// @param epoch The number of rebases since inception.
/// @param newScalar The new scalar.
event Rebase(uint256 indexed epoch, uint256 newScalar);
}{
"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":"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":false,"internalType":"address","name":"oracle","type":"address"}],"name":"OracleUpdated","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":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newScalar","type":"uint256"}],"name":"Rebase","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"},{"inputs":[],"name":"MAX_UNDERLYING","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":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"balanceOfUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnAll","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burnAllTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"subtractedAmount","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"uAmount","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"uAmount","type":"uint256"}],"name":"depositFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedAmount","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"underlying_","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"oracle_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"scaledBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scaledTotalSupply","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":[],"name":"totalUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"transferAllFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"uAmount","type":"uint256"}],"name":"underlyingToWrapper","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"oracle_","type":"address"}],"name":"updateOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"uAmount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"withdrawAllTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"uAmount","type":"uint256"}],"name":"withdrawTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"wrapperToUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5061274d806100206000396000f3fe608060405234801561001057600080fd5b50600436106102535760003560e01c8063853828b611610146578063aab3b7db116100c3578063ca9add8f11610087578063ca9add8f146104b8578063da1919b3146104cb578063dd62ed3e146104de578063ea785a5e14610517578063ed0287c01461052a578063f2fde38b1461053d57600080fd5b8063aab3b7db14610482578063af14052c14610495578063b1bf962d1461049d578063b6b55f25146104a5578063c70920bc1461049d57600080fd5b8063a0712d681161010a578063a0712d6814610423578063a3a7e7f314610436578063a457c2d714610449578063a4fa95681461045c578063a9059cbb1461046f57600080fd5b8063853828b6146103e75780638da5cb5b146103ef57806395d89b41146104005780639975038c146104085780639b543aab1461041057600080fd5b8063313ce567116101d45780636f307dc3116101985780636f307dc31461037b57806370a08231146103a6578063715018a6146103b95780637dc0d1d0146103c157806384d4b410146103d457600080fd5b8063313ce5671461032857806339509351146103425780633af9e669146102c957806342966c6814610355578063613d25bb1461036857600080fd5b80631da24f3e1161021b5780631da24f3e146102c9578063205c2878146102dc57806323b872dd146102ef5780632e1a7d4d146103025780632f4f21e21461031557600080fd5b8063053f14da1461025857806306fdde0314610274578063095ea7b31461028957806318160ddd146102ac5780631cb44dfc146102b4575b600080fd5b61026160675481565b6040519081526020015b60405180910390f35b61027c610550565b60405161026b9190612395565b61029c6102973660046122c3565b6105de565b604051901515815260200161026b565b610261610635565b6102c76102c23660046121ba565b61065a565b005b6102616102d73660046121ba565b61083b565b6102616102ea3660046122c3565b610875565b61029c6102fd366004612206565b6108ca565b610261610310366004612306565b610a0c565b6102616103233660046122c3565b610a60565b610330610aab565b60405160ff909116815260200161026b565b61029c6103503660046122c3565b610b2d565b610261610363366004612306565b610bba565b6102c7610376366004612241565b610c05565b60655461038e906001600160a01b031681565b6040516001600160a01b03909116815260200161026b565b6102616103b43660046121ba565b610d80565b6102c7610dd0565b60665461038e906001600160a01b031681565b61029c6103e23660046121d4565b610e06565b610261610f6b565b6033546001600160a01b031661038e565b61027c610fcf565b610261610fdc565b6102616b033b2e3c9fd0803ce800000081565b610261610431366004612306565b61103b565b61029c6104443660046121ba565b611086565b61029c6104573660046122c3565b611130565b61026161046a3660046121ba565b6111c6565b61029c61047d3660046122c3565b61122b565b610261610490366004612306565b6112ad565b6102c76112cd565b6102616112f0565b6102616104b3366004612306565b6112fd565b6102616104c63660046121ba565b611348565b6102616104d93660046122c3565b61139e565b6102616104ec3660046121d4565b6001600160a01b039182166000908152606e6020908152604080832093909416825291909152205490565b6102616105253660046122c3565b6113e9565b610261610538366004612306565b611434565b6102c761054b3660046121ba565b61144e565b6069805461055d9061264b565b80601f01602080910402602001604051908101604052809291908181526020018280546105899061264b565b80156105d65780601f106105ab576101008083540402835291602001916105d6565b820191906000526020600020905b8154815290600101906020018083116105b957829003601f168201915b505050505081565b336000818152606e602090815260408083206001600160a01b03871680855290835281842086905590518581529293909290916000805160206126f883398151915291015b60405180910390a35060015b92915050565b6000806106406114e9565b50905061065461064e6115ab565b82611605565b91505090565b6033546001600160a01b0316331461068d5760405162461bcd60e51b81526004016106849061245a565b60405180910390fd5b606680546001600160a01b0319166001600160a01b0383161790556000806106b36114e9565b90925090508061071b5760405162461bcd60e51b815260206004820152602d60248201527f427574746f6e546f6b656e3a20756e61626c6520746f2066657463682064617460448201526c612066726f6d206f7261636c6560981b6064820152608401610684565b6066546040805162a6016560e31b815290516000926001600160a01b0316916305300b28916004808301926020929190829003018186803b15801561075f57600080fd5b505afa158015610773573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610797919061231e565b90506107a481600a612541565b6b033b2e3c9fd0803ce80000006107bd816000196126a1565b6107c990600019612608565b6107d391906124ea565b6107dd91906125e9565b606b556107e98161161a565b606c556066546040516001600160a01b0390911681527f3df77beb5db05fcdd70a30fc8adf3f83f9501b68579455adbd100b81809403949060200160405180910390a161083583611895565b50505050565b60006001600160a01b03821661085357506000919050565b6001600160a01b0382166000908152606d602052604090205461062f906118f8565b60008060006108826114e9565b909250905080156108965761089682611895565b60006108a185611933565b905060006108b182606754611605565b90506108c0338888848661196e565b9695505050505050565b6000826001600160a01b0381166108f35760405162461bcd60e51b81526004016106849061248f565b6001600160a01b03811630141561091c5760405162461bcd60e51b8152600401610684906123c8565b6000806109276114e9565b9092509050801561093b5761093b82611895565b6001600160a01b0387166000908152606e60209081526040808320338452909152902054600019146109e8576001600160a01b0387166000908152606e602090815260408083203384529091528120805487929061099a908490612608565b90915550506001600160a01b0387166000818152606e6020908152604080832033808552908352928190205490519081529192916000805160206126f8833981519152910160405180910390a35b6109ff87876109f9886067546119f5565b88611a0a565b5060019695505050505050565b6000806000610a196114e9565b90925090508015610a2d57610a2d82611895565b6000610a3885611933565b90506000610a4882606754611605565b9050610a57333388848661196e565b95945050505050565b6000806000610a6d6114e9565b90925090508015610a8157610a8182611895565b6000610a8c85611933565b90506000610a9c82606754611605565b90506108c03388888486611aed565b6065546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b158015610af057600080fd5b505afa158015610b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b289190612358565b905090565b336000908152606e602090815260408083206001600160a01b0386168452909152812080548391908390610b629084906124d2565b90915550506001600160a01b038316335b336000908152606e602090815260408083206001600160a01b0389811685529083529281902054905190815292909116916000805160206126f88339815191529101610623565b6000806000610bc76114e9565b90925090508015610bdb57610bdb82611895565b6000610be9856067546119f5565b90506000610bf6826118f8565b9050610a57333383898661196e565b600054610100900460ff1680610c1e575060005460ff16155b610c3a5760405162461bcd60e51b81526004016106849061240c565b600054610100900460ff16158015610c5c576000805461ffff19166101011790555b6001600160a01b038516610cc45760405162461bcd60e51b815260206004820152602960248201527f427574746f6e546f6b656e3a20696e76616c696420756e6465726c79696e67206044820152687265666572656e636560b81b6064820152608401610684565b610ccc611bc5565b606580546001600160a01b0319166001600160a01b0387161790558351610cfa90606990602087019061206e565b508251610d0e90606a90602086019061206e565b50610d276b033b2e3c9fd0803ce80000006000196126a1565b610d3390600019612608565b60008052606d6020527fda90043ba5b4096ba14704bc227ab0d3167da15b887e62ab2e76e37daa71135655610d678261065a565b8015610d79576000805461ff00191690555b5050505050565b60006001600160a01b038216610d9857506000919050565b6000610da26114e9565b506001600160a01b0384166000908152606d6020526040902054909150610dc99082611605565b9392505050565b6033546001600160a01b03163314610dfa5760405162461bcd60e51b81526004016106849061245a565b610e046000611c40565b565b6000816001600160a01b038116610e2f5760405162461bcd60e51b81526004016106849061248f565b6001600160a01b038116301415610e585760405162461bcd60e51b8152600401610684906123c8565b600080610e636114e9565b90925090508015610e7757610e7782611895565b6001600160a01b0386166000908152606d6020526040812054606754909190610ea1908390611605565b6001600160a01b0389166000908152606e6020908152604080832033845290915290205490915060001914610f51576001600160a01b0388166000908152606e6020908152604080832033845290915281208054839290610f03908490612608565b90915550506001600160a01b0388166000818152606e6020908152604080832033808552908352928190205490519081529192916000805160206126f8833981519152910160405180910390a35b610f5d88888484611a0a565b506001979650505050505050565b6000806000610f786114e9565b90925090508015610f8c57610f8c82611895565b336000908152606d602052604081205490610fa6826118f8565b90506000610fb683606754611605565b9050610fc6335b3384848761196e565b94505050505090565b606a805461055d9061264b565b6000806000610fe96114e9565b90925090508015610ffd57610ffd82611895565b336000908152606d602052604081205490611017826118f8565b9050600061102783606754611605565b905061103233610fbd565b50935050505090565b60008060006110486114e9565b9092509050801561105c5761105c82611895565b600061106a856067546119f5565b90506000611077826118f8565b9050610a573333838986611aed565b6000816001600160a01b0381166110af5760405162461bcd60e51b81526004016106849061248f565b6001600160a01b0381163014156110d85760405162461bcd60e51b8152600401610684906123c8565b6000806110e36114e9565b909250905080156110f7576110f782611895565b336000818152606d60205260409020546067549091611124918890849061111f908290611605565b611a0a565b50600195945050505050565b336000908152606e602090815260408083206001600160a01b0386168452909152812054821061118357336000908152606e602090815260408083206001600160a01b03871684529091528120556111b6565b336000908152606e602090815260408083206001600160a01b038716845290915281208054849290610b62908490612608565b6001600160a01b03831633610b73565b60008060006111d36114e9565b909250905080156111e7576111e782611895565b336000908152606d602052604081205490611201826118f8565b9050600061121183606754611605565b9050611221335b8884848761196e565b5095945050505050565b6000826001600160a01b0381166112545760405162461bcd60e51b81526004016106849061248f565b6001600160a01b03811630141561127d5760405162461bcd60e51b8152600401610684906123c8565b6000806112886114e9565b9092509050801561129c5761129c82611895565b61112433876109f9886067546119f5565b6000806112b86114e9565b509050610dc96112c884836119f5565b6118f8565b6000806112d86114e9565b909250905080156112ec576112ec82611895565b5050565b6000610b286112c86115ab565b600080600061130a6114e9565b9092509050801561131e5761131e82611895565b600061132985611933565b9050600061133982606754611605565b9050610a573333888486611aed565b60008060006113556114e9565b909250905080156113695761136982611895565b336000908152606d602052604081205490611383826118f8565b9050600061139383606754611605565b90506108c033611218565b60008060006113ab6114e9565b909250905080156113bf576113bf82611895565b60006113cd856067546119f5565b905060006113da826118f8565b90506108c03388838986611aed565b60008060006113f66114e9565b9092509050801561140a5761140a82611895565b6000611418856067546119f5565b90506000611425826118f8565b90506108c0338883898661196e565b60008061143f6114e9565b509050610dc961064e84611933565b6033546001600160a01b031633146114785760405162461bcd60e51b81526004016106849061245a565b6001600160a01b0381166114dd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610684565b6114e681611c40565b50565b600080600080606660009054906101000a90046001600160a01b03166001600160a01b0316633bc5de306040518163ffffffff1660e01b8152600401604080518083038186803b15801561153c57600080fd5b505afa158015611550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115749190612336565b90925090508080156115865750600082115b61159257606754611594565b815b8180156115a15750600083115b9350935050509091565b6000808052606d6020527fda90043ba5b4096ba14704bc227ab0d3167da15b887e62ab2e76e37daa711356546115ef6b033b2e3c9fd0803ce80000006000196126a1565b6115fb90600019612608565b610b289190612608565b600061161082611c92565b610dc990846124ea565b600060128211156116825760405162461bcd60e51b815260206004820152602c60248201527f427574746f6e546f6b656e3a20507269636520446563696d616c73206d75737460448201526b040c4ca40eadcc8cae44062760a31b6064820152608401610684565b81601214156116a157506e01ffffffffffffffffffffffffffff919050565b81600814156116bd57506bffffffffffffffffffffffff919050565b81600614156116d957506b1fffffffffffffffffffffff919050565b816116f057506a07ffffffffffffffffffff919050565b816001141561170b57506a0fffffffffffffffffffff919050565b816002141561172657506a3fffffffffffffffffffff919050565b816003141561174157506affffffffffffffffffffff919050565b816004141561175d57506b01ffffffffffffffffffffff919050565b816005141561177957506b07ffffffffffffffffffffff919050565b816007141561179557506b3fffffffffffffffffffffff919050565b81600914156117b257506c03ffffffffffffffffffffffff919050565b81600a14156117cf57506c07ffffffffffffffffffffffff919050565b81600b14156117ec57506c1fffffffffffffffffffffffff919050565b81600c141561180957506c7fffffffffffffffffffffffff919050565b81600d141561182657506cffffffffffffffffffffffffff919050565b81600e141561184457506d03ffffffffffffffffffffffffff919050565b81600f141561186257506d0fffffffffffffffffffffffffff919050565b816010141561188057506d1fffffffffffffffffffffffffff919050565b506d7fffffffffffffffffffffffffff919050565b606c54808211156118a4578091505b6067829055606880549060006118b983612686565b90915550506068546040518381527f11c6bf55864ff83827df712625d7a80e5583eef0264921025e7cd22003a215119060200160405180910390a25050565b60006b033b2e3c9fd0803ce8000000611913816000196126a1565b61191f90600019612608565b61192991906124ea565b61062f90836124ea565b60006b033b2e3c9fd0803ce800000061194e816000196126a1565b61195a90600019612608565b61196491906124ea565b61062f90836125e9565b600082116119d15760405162461bcd60e51b815260206004820152602a60248201527f427574746f6e546f6b656e3a20746f6f2066657720627574746f6e20746f6b656044820152693739903a3790313ab93760b11b6064820152608401610684565b6119de8560008385611a0a565b606554610d79906001600160a01b03168585611ca2565b6000611a0082611c92565b610dc990846125e9565b6001600160a01b0384166000908152606d602052604081208054849290611a32908490612608565b90915550506001600160a01b0383166000908152606d602052604081208054849290611a5f9084906124d2565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611aab91815260200190565b60405180910390a36001600160a01b0384166000908152606d6020526040902054610835575050506001600160a01b03166000908152606d6020526040812055565b60008311611b3d5760405162461bcd60e51b815260206004820181905260248201527f427574746f6e546f6b656e3a204e6f20746f6b656e73206465706f73697465646044820152606401610684565b60008211611ba05760405162461bcd60e51b815260206004820152602a60248201527f427574746f6e546f6b656e3a20746f6f2066657720627574746f6e20746f6b656044820152691b9cc81d1bc81b5a5b9d60b21b6064820152608401610684565b606554611bb8906001600160a01b0316863086611d0a565b610d796000858385611a0a565b600054610100900460ff1680611bde575060005460ff16155b611bfa5760405162461bcd60e51b81526004016106849061240c565b600054610100900460ff16158015611c1c576000805461ffff19166101011790555b611c24611d42565b611c2c611dac565b80156114e6576000805461ff001916905550565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600081606b5461062f91906124ea565b6040516001600160a01b038316602482015260448101829052611d0590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611e0c565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526108359085906323b872dd60e01b90608401611cce565b600054610100900460ff1680611d5b575060005460ff16155b611d775760405162461bcd60e51b81526004016106849061240c565b600054610100900460ff16158015611c2c576000805461ffff191661010117905580156114e6576000805461ff001916905550565b600054610100900460ff1680611dc5575060005460ff16155b611de15760405162461bcd60e51b81526004016106849061240c565b600054610100900460ff16158015611e03576000805461ffff19166101011790555b611c2c33611c40565b6000611e61826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611ee19092919063ffffffff16565b9050805160001480611e82575080806020019051810190611e8291906122ec565b611d055760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610684565b6060611ef08484600085611ef8565b949350505050565b606082471015611f595760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610684565b600080866001600160a01b03168587604051611f759190612379565b60006040518083038185875af1925050503d8060008114611fb2576040519150601f19603f3d011682016040523d82523d6000602084013e611fb7565b606091505b5091509150611fc887838387611fd3565b979650505050505050565b6060831561203f578251612038576001600160a01b0385163b6120385760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610684565b5081611ef0565b611ef083838151156120545781518083602001fd5b8060405162461bcd60e51b81526004016106849190612395565b82805461207a9061264b565b90600052602060002090601f01602090048101928261209c57600085556120e2565b82601f106120b557805160ff19168380011785556120e2565b828001600101855582156120e2579182015b828111156120e25782518255916020019190600101906120c7565b506120ee9291506120f2565b5090565b5b808211156120ee57600081556001016120f3565b80356001600160a01b038116811461211e57600080fd5b919050565b8051801515811461211e57600080fd5b600082601f830112612143578081fd5b813567ffffffffffffffff8082111561215e5761215e6126e1565b604051601f8301601f19908116603f01168101908282118183101715612186576121866126e1565b8160405283815286602085880101111561219e578485fd5b8360208701602083013792830160200193909352509392505050565b6000602082840312156121cb578081fd5b610dc982612107565b600080604083850312156121e6578081fd5b6121ef83612107565b91506121fd60208401612107565b90509250929050565b60008060006060848603121561221a578081fd5b61222384612107565b925061223160208501612107565b9150604084013590509250925092565b60008060008060808587031215612256578081fd5b61225f85612107565b9350602085013567ffffffffffffffff8082111561227b578283fd5b61228788838901612133565b9450604087013591508082111561229c578283fd5b506122a987828801612133565b9250506122b860608601612107565b905092959194509250565b600080604083850312156122d5578182fd5b6122de83612107565b946020939093013593505050565b6000602082840312156122fd578081fd5b610dc982612123565b600060208284031215612317578081fd5b5035919050565b60006020828403121561232f578081fd5b5051919050565b60008060408385031215612348578182fd5b825191506121fd60208401612123565b600060208284031215612369578081fd5b815160ff81168114610dc9578182fd5b6000825161238b81846020870161261f565b9190910192915050565b60208152600082518060208401526123b481604085016020870161261f565b601f01601f19169190910160400192915050565b60208082526024908201527f427574746f6e546f6b656e3a20726563697069656e7420746f6b656e206164646040820152637265737360e01b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526023908201527f427574746f6e546f6b656e3a20726563697069656e74207a65726f206164647260408201526265737360e81b606082015260800190565b600082198211156124e5576124e56126b5565b500190565b6000826124f9576124f96126cb565b500490565b600181815b8085111561253957816000190482111561251f5761251f6126b5565b8085161561252c57918102915b93841c9390800290612503565b509250929050565b6000610dc983836000826125575750600161062f565b816125645750600061062f565b816001811461257a5760028114612584576125a0565b600191505061062f565b60ff841115612595576125956126b5565b50506001821b61062f565b5060208310610133831016604e8410600b84101617156125c3575081810a61062f565b6125cd83836124fe565b80600019048211156125e1576125e16126b5565b029392505050565b6000816000190483118215151615612603576126036126b5565b500290565b60008282101561261a5761261a6126b5565b500390565b60005b8381101561263a578181015183820152602001612622565b838111156108355750506000910152565b600181811c9082168061265f57607f821691505b6020821081141561268057634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561269a5761269a6126b5565b5060010190565b6000826126b0576126b06126cb565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fdfe8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a264697066735822122047fcebbfe29ef01c24ad40ccc355eb763e8635f64251e01fdc63ccb9cdbd501964736f6c63430008040033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102535760003560e01c8063853828b611610146578063aab3b7db116100c3578063ca9add8f11610087578063ca9add8f146104b8578063da1919b3146104cb578063dd62ed3e146104de578063ea785a5e14610517578063ed0287c01461052a578063f2fde38b1461053d57600080fd5b8063aab3b7db14610482578063af14052c14610495578063b1bf962d1461049d578063b6b55f25146104a5578063c70920bc1461049d57600080fd5b8063a0712d681161010a578063a0712d6814610423578063a3a7e7f314610436578063a457c2d714610449578063a4fa95681461045c578063a9059cbb1461046f57600080fd5b8063853828b6146103e75780638da5cb5b146103ef57806395d89b41146104005780639975038c146104085780639b543aab1461041057600080fd5b8063313ce567116101d45780636f307dc3116101985780636f307dc31461037b57806370a08231146103a6578063715018a6146103b95780637dc0d1d0146103c157806384d4b410146103d457600080fd5b8063313ce5671461032857806339509351146103425780633af9e669146102c957806342966c6814610355578063613d25bb1461036857600080fd5b80631da24f3e1161021b5780631da24f3e146102c9578063205c2878146102dc57806323b872dd146102ef5780632e1a7d4d146103025780632f4f21e21461031557600080fd5b8063053f14da1461025857806306fdde0314610274578063095ea7b31461028957806318160ddd146102ac5780631cb44dfc146102b4575b600080fd5b61026160675481565b6040519081526020015b60405180910390f35b61027c610550565b60405161026b9190612395565b61029c6102973660046122c3565b6105de565b604051901515815260200161026b565b610261610635565b6102c76102c23660046121ba565b61065a565b005b6102616102d73660046121ba565b61083b565b6102616102ea3660046122c3565b610875565b61029c6102fd366004612206565b6108ca565b610261610310366004612306565b610a0c565b6102616103233660046122c3565b610a60565b610330610aab565b60405160ff909116815260200161026b565b61029c6103503660046122c3565b610b2d565b610261610363366004612306565b610bba565b6102c7610376366004612241565b610c05565b60655461038e906001600160a01b031681565b6040516001600160a01b03909116815260200161026b565b6102616103b43660046121ba565b610d80565b6102c7610dd0565b60665461038e906001600160a01b031681565b61029c6103e23660046121d4565b610e06565b610261610f6b565b6033546001600160a01b031661038e565b61027c610fcf565b610261610fdc565b6102616b033b2e3c9fd0803ce800000081565b610261610431366004612306565b61103b565b61029c6104443660046121ba565b611086565b61029c6104573660046122c3565b611130565b61026161046a3660046121ba565b6111c6565b61029c61047d3660046122c3565b61122b565b610261610490366004612306565b6112ad565b6102c76112cd565b6102616112f0565b6102616104b3366004612306565b6112fd565b6102616104c63660046121ba565b611348565b6102616104d93660046122c3565b61139e565b6102616104ec3660046121d4565b6001600160a01b039182166000908152606e6020908152604080832093909416825291909152205490565b6102616105253660046122c3565b6113e9565b610261610538366004612306565b611434565b6102c761054b3660046121ba565b61144e565b6069805461055d9061264b565b80601f01602080910402602001604051908101604052809291908181526020018280546105899061264b565b80156105d65780601f106105ab576101008083540402835291602001916105d6565b820191906000526020600020905b8154815290600101906020018083116105b957829003601f168201915b505050505081565b336000818152606e602090815260408083206001600160a01b03871680855290835281842086905590518581529293909290916000805160206126f883398151915291015b60405180910390a35060015b92915050565b6000806106406114e9565b50905061065461064e6115ab565b82611605565b91505090565b6033546001600160a01b0316331461068d5760405162461bcd60e51b81526004016106849061245a565b60405180910390fd5b606680546001600160a01b0319166001600160a01b0383161790556000806106b36114e9565b90925090508061071b5760405162461bcd60e51b815260206004820152602d60248201527f427574746f6e546f6b656e3a20756e61626c6520746f2066657463682064617460448201526c612066726f6d206f7261636c6560981b6064820152608401610684565b6066546040805162a6016560e31b815290516000926001600160a01b0316916305300b28916004808301926020929190829003018186803b15801561075f57600080fd5b505afa158015610773573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610797919061231e565b90506107a481600a612541565b6b033b2e3c9fd0803ce80000006107bd816000196126a1565b6107c990600019612608565b6107d391906124ea565b6107dd91906125e9565b606b556107e98161161a565b606c556066546040516001600160a01b0390911681527f3df77beb5db05fcdd70a30fc8adf3f83f9501b68579455adbd100b81809403949060200160405180910390a161083583611895565b50505050565b60006001600160a01b03821661085357506000919050565b6001600160a01b0382166000908152606d602052604090205461062f906118f8565b60008060006108826114e9565b909250905080156108965761089682611895565b60006108a185611933565b905060006108b182606754611605565b90506108c0338888848661196e565b9695505050505050565b6000826001600160a01b0381166108f35760405162461bcd60e51b81526004016106849061248f565b6001600160a01b03811630141561091c5760405162461bcd60e51b8152600401610684906123c8565b6000806109276114e9565b9092509050801561093b5761093b82611895565b6001600160a01b0387166000908152606e60209081526040808320338452909152902054600019146109e8576001600160a01b0387166000908152606e602090815260408083203384529091528120805487929061099a908490612608565b90915550506001600160a01b0387166000818152606e6020908152604080832033808552908352928190205490519081529192916000805160206126f8833981519152910160405180910390a35b6109ff87876109f9886067546119f5565b88611a0a565b5060019695505050505050565b6000806000610a196114e9565b90925090508015610a2d57610a2d82611895565b6000610a3885611933565b90506000610a4882606754611605565b9050610a57333388848661196e565b95945050505050565b6000806000610a6d6114e9565b90925090508015610a8157610a8182611895565b6000610a8c85611933565b90506000610a9c82606754611605565b90506108c03388888486611aed565b6065546040805163313ce56760e01b815290516000926001600160a01b03169163313ce567916004808301926020929190829003018186803b158015610af057600080fd5b505afa158015610b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b289190612358565b905090565b336000908152606e602090815260408083206001600160a01b0386168452909152812080548391908390610b629084906124d2565b90915550506001600160a01b038316335b336000908152606e602090815260408083206001600160a01b0389811685529083529281902054905190815292909116916000805160206126f88339815191529101610623565b6000806000610bc76114e9565b90925090508015610bdb57610bdb82611895565b6000610be9856067546119f5565b90506000610bf6826118f8565b9050610a57333383898661196e565b600054610100900460ff1680610c1e575060005460ff16155b610c3a5760405162461bcd60e51b81526004016106849061240c565b600054610100900460ff16158015610c5c576000805461ffff19166101011790555b6001600160a01b038516610cc45760405162461bcd60e51b815260206004820152602960248201527f427574746f6e546f6b656e3a20696e76616c696420756e6465726c79696e67206044820152687265666572656e636560b81b6064820152608401610684565b610ccc611bc5565b606580546001600160a01b0319166001600160a01b0387161790558351610cfa90606990602087019061206e565b508251610d0e90606a90602086019061206e565b50610d276b033b2e3c9fd0803ce80000006000196126a1565b610d3390600019612608565b60008052606d6020527fda90043ba5b4096ba14704bc227ab0d3167da15b887e62ab2e76e37daa71135655610d678261065a565b8015610d79576000805461ff00191690555b5050505050565b60006001600160a01b038216610d9857506000919050565b6000610da26114e9565b506001600160a01b0384166000908152606d6020526040902054909150610dc99082611605565b9392505050565b6033546001600160a01b03163314610dfa5760405162461bcd60e51b81526004016106849061245a565b610e046000611c40565b565b6000816001600160a01b038116610e2f5760405162461bcd60e51b81526004016106849061248f565b6001600160a01b038116301415610e585760405162461bcd60e51b8152600401610684906123c8565b600080610e636114e9565b90925090508015610e7757610e7782611895565b6001600160a01b0386166000908152606d6020526040812054606754909190610ea1908390611605565b6001600160a01b0389166000908152606e6020908152604080832033845290915290205490915060001914610f51576001600160a01b0388166000908152606e6020908152604080832033845290915281208054839290610f03908490612608565b90915550506001600160a01b0388166000818152606e6020908152604080832033808552908352928190205490519081529192916000805160206126f8833981519152910160405180910390a35b610f5d88888484611a0a565b506001979650505050505050565b6000806000610f786114e9565b90925090508015610f8c57610f8c82611895565b336000908152606d602052604081205490610fa6826118f8565b90506000610fb683606754611605565b9050610fc6335b3384848761196e565b94505050505090565b606a805461055d9061264b565b6000806000610fe96114e9565b90925090508015610ffd57610ffd82611895565b336000908152606d602052604081205490611017826118f8565b9050600061102783606754611605565b905061103233610fbd565b50935050505090565b60008060006110486114e9565b9092509050801561105c5761105c82611895565b600061106a856067546119f5565b90506000611077826118f8565b9050610a573333838986611aed565b6000816001600160a01b0381166110af5760405162461bcd60e51b81526004016106849061248f565b6001600160a01b0381163014156110d85760405162461bcd60e51b8152600401610684906123c8565b6000806110e36114e9565b909250905080156110f7576110f782611895565b336000818152606d60205260409020546067549091611124918890849061111f908290611605565b611a0a565b50600195945050505050565b336000908152606e602090815260408083206001600160a01b0386168452909152812054821061118357336000908152606e602090815260408083206001600160a01b03871684529091528120556111b6565b336000908152606e602090815260408083206001600160a01b038716845290915281208054849290610b62908490612608565b6001600160a01b03831633610b73565b60008060006111d36114e9565b909250905080156111e7576111e782611895565b336000908152606d602052604081205490611201826118f8565b9050600061121183606754611605565b9050611221335b8884848761196e565b5095945050505050565b6000826001600160a01b0381166112545760405162461bcd60e51b81526004016106849061248f565b6001600160a01b03811630141561127d5760405162461bcd60e51b8152600401610684906123c8565b6000806112886114e9565b9092509050801561129c5761129c82611895565b61112433876109f9886067546119f5565b6000806112b86114e9565b509050610dc96112c884836119f5565b6118f8565b6000806112d86114e9565b909250905080156112ec576112ec82611895565b5050565b6000610b286112c86115ab565b600080600061130a6114e9565b9092509050801561131e5761131e82611895565b600061132985611933565b9050600061133982606754611605565b9050610a573333888486611aed565b60008060006113556114e9565b909250905080156113695761136982611895565b336000908152606d602052604081205490611383826118f8565b9050600061139383606754611605565b90506108c033611218565b60008060006113ab6114e9565b909250905080156113bf576113bf82611895565b60006113cd856067546119f5565b905060006113da826118f8565b90506108c03388838986611aed565b60008060006113f66114e9565b9092509050801561140a5761140a82611895565b6000611418856067546119f5565b90506000611425826118f8565b90506108c0338883898661196e565b60008061143f6114e9565b509050610dc961064e84611933565b6033546001600160a01b031633146114785760405162461bcd60e51b81526004016106849061245a565b6001600160a01b0381166114dd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610684565b6114e681611c40565b50565b600080600080606660009054906101000a90046001600160a01b03166001600160a01b0316633bc5de306040518163ffffffff1660e01b8152600401604080518083038186803b15801561153c57600080fd5b505afa158015611550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115749190612336565b90925090508080156115865750600082115b61159257606754611594565b815b8180156115a15750600083115b9350935050509091565b6000808052606d6020527fda90043ba5b4096ba14704bc227ab0d3167da15b887e62ab2e76e37daa711356546115ef6b033b2e3c9fd0803ce80000006000196126a1565b6115fb90600019612608565b610b289190612608565b600061161082611c92565b610dc990846124ea565b600060128211156116825760405162461bcd60e51b815260206004820152602c60248201527f427574746f6e546f6b656e3a20507269636520446563696d616c73206d75737460448201526b040c4ca40eadcc8cae44062760a31b6064820152608401610684565b81601214156116a157506e01ffffffffffffffffffffffffffff919050565b81600814156116bd57506bffffffffffffffffffffffff919050565b81600614156116d957506b1fffffffffffffffffffffff919050565b816116f057506a07ffffffffffffffffffff919050565b816001141561170b57506a0fffffffffffffffffffff919050565b816002141561172657506a3fffffffffffffffffffff919050565b816003141561174157506affffffffffffffffffffff919050565b816004141561175d57506b01ffffffffffffffffffffff919050565b816005141561177957506b07ffffffffffffffffffffff919050565b816007141561179557506b3fffffffffffffffffffffff919050565b81600914156117b257506c03ffffffffffffffffffffffff919050565b81600a14156117cf57506c07ffffffffffffffffffffffff919050565b81600b14156117ec57506c1fffffffffffffffffffffffff919050565b81600c141561180957506c7fffffffffffffffffffffffff919050565b81600d141561182657506cffffffffffffffffffffffffff919050565b81600e141561184457506d03ffffffffffffffffffffffffff919050565b81600f141561186257506d0fffffffffffffffffffffffffff919050565b816010141561188057506d1fffffffffffffffffffffffffff919050565b506d7fffffffffffffffffffffffffff919050565b606c54808211156118a4578091505b6067829055606880549060006118b983612686565b90915550506068546040518381527f11c6bf55864ff83827df712625d7a80e5583eef0264921025e7cd22003a215119060200160405180910390a25050565b60006b033b2e3c9fd0803ce8000000611913816000196126a1565b61191f90600019612608565b61192991906124ea565b61062f90836124ea565b60006b033b2e3c9fd0803ce800000061194e816000196126a1565b61195a90600019612608565b61196491906124ea565b61062f90836125e9565b600082116119d15760405162461bcd60e51b815260206004820152602a60248201527f427574746f6e546f6b656e3a20746f6f2066657720627574746f6e20746f6b656044820152693739903a3790313ab93760b11b6064820152608401610684565b6119de8560008385611a0a565b606554610d79906001600160a01b03168585611ca2565b6000611a0082611c92565b610dc990846125e9565b6001600160a01b0384166000908152606d602052604081208054849290611a32908490612608565b90915550506001600160a01b0383166000908152606d602052604081208054849290611a5f9084906124d2565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611aab91815260200190565b60405180910390a36001600160a01b0384166000908152606d6020526040902054610835575050506001600160a01b03166000908152606d6020526040812055565b60008311611b3d5760405162461bcd60e51b815260206004820181905260248201527f427574746f6e546f6b656e3a204e6f20746f6b656e73206465706f73697465646044820152606401610684565b60008211611ba05760405162461bcd60e51b815260206004820152602a60248201527f427574746f6e546f6b656e3a20746f6f2066657720627574746f6e20746f6b656044820152691b9cc81d1bc81b5a5b9d60b21b6064820152608401610684565b606554611bb8906001600160a01b0316863086611d0a565b610d796000858385611a0a565b600054610100900460ff1680611bde575060005460ff16155b611bfa5760405162461bcd60e51b81526004016106849061240c565b600054610100900460ff16158015611c1c576000805461ffff19166101011790555b611c24611d42565b611c2c611dac565b80156114e6576000805461ff001916905550565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600081606b5461062f91906124ea565b6040516001600160a01b038316602482015260448101829052611d0590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611e0c565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526108359085906323b872dd60e01b90608401611cce565b600054610100900460ff1680611d5b575060005460ff16155b611d775760405162461bcd60e51b81526004016106849061240c565b600054610100900460ff16158015611c2c576000805461ffff191661010117905580156114e6576000805461ff001916905550565b600054610100900460ff1680611dc5575060005460ff16155b611de15760405162461bcd60e51b81526004016106849061240c565b600054610100900460ff16158015611e03576000805461ffff19166101011790555b611c2c33611c40565b6000611e61826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611ee19092919063ffffffff16565b9050805160001480611e82575080806020019051810190611e8291906122ec565b611d055760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610684565b6060611ef08484600085611ef8565b949350505050565b606082471015611f595760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610684565b600080866001600160a01b03168587604051611f759190612379565b60006040518083038185875af1925050503d8060008114611fb2576040519150601f19603f3d011682016040523d82523d6000602084013e611fb7565b606091505b5091509150611fc887838387611fd3565b979650505050505050565b6060831561203f578251612038576001600160a01b0385163b6120385760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610684565b5081611ef0565b611ef083838151156120545781518083602001fd5b8060405162461bcd60e51b81526004016106849190612395565b82805461207a9061264b565b90600052602060002090601f01602090048101928261209c57600085556120e2565b82601f106120b557805160ff19168380011785556120e2565b828001600101855582156120e2579182015b828111156120e25782518255916020019190600101906120c7565b506120ee9291506120f2565b5090565b5b808211156120ee57600081556001016120f3565b80356001600160a01b038116811461211e57600080fd5b919050565b8051801515811461211e57600080fd5b600082601f830112612143578081fd5b813567ffffffffffffffff8082111561215e5761215e6126e1565b604051601f8301601f19908116603f01168101908282118183101715612186576121866126e1565b8160405283815286602085880101111561219e578485fd5b8360208701602083013792830160200193909352509392505050565b6000602082840312156121cb578081fd5b610dc982612107565b600080604083850312156121e6578081fd5b6121ef83612107565b91506121fd60208401612107565b90509250929050565b60008060006060848603121561221a578081fd5b61222384612107565b925061223160208501612107565b9150604084013590509250925092565b60008060008060808587031215612256578081fd5b61225f85612107565b9350602085013567ffffffffffffffff8082111561227b578283fd5b61228788838901612133565b9450604087013591508082111561229c578283fd5b506122a987828801612133565b9250506122b860608601612107565b905092959194509250565b600080604083850312156122d5578182fd5b6122de83612107565b946020939093013593505050565b6000602082840312156122fd578081fd5b610dc982612123565b600060208284031215612317578081fd5b5035919050565b60006020828403121561232f578081fd5b5051919050565b60008060408385031215612348578182fd5b825191506121fd60208401612123565b600060208284031215612369578081fd5b815160ff81168114610dc9578182fd5b6000825161238b81846020870161261f565b9190910192915050565b60208152600082518060208401526123b481604085016020870161261f565b601f01601f19169190910160400192915050565b60208082526024908201527f427574746f6e546f6b656e3a20726563697069656e7420746f6b656e206164646040820152637265737360e01b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526023908201527f427574746f6e546f6b656e3a20726563697069656e74207a65726f206164647260408201526265737360e81b606082015260800190565b600082198211156124e5576124e56126b5565b500190565b6000826124f9576124f96126cb565b500490565b600181815b8085111561253957816000190482111561251f5761251f6126b5565b8085161561252c57918102915b93841c9390800290612503565b509250929050565b6000610dc983836000826125575750600161062f565b816125645750600061062f565b816001811461257a5760028114612584576125a0565b600191505061062f565b60ff841115612595576125956126b5565b50506001821b61062f565b5060208310610133831016604e8410600b84101617156125c3575081810a61062f565b6125cd83836124fe565b80600019048211156125e1576125e16126b5565b029392505050565b6000816000190483118215151615612603576126036126b5565b500290565b60008282101561261a5761261a6126b5565b500390565b60005b8381101561263a578181015183820152602001612622565b838111156108355750506000910152565b600181811c9082168061265f57607f821691505b6020821081141561268057634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561269a5761269a6126b5565b5060010190565b6000826126b0576126b06126cb565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fdfe8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a264697066735822122047fcebbfe29ef01c24ad40ccc355eb763e8635f64251e01fdc63ccb9cdbd501964736f6c63430008040033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.