Source Code
Latest 25 from a total of 64 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Deleverage ERC20 | 21918570 | 215 days ago | IN | 0 FRAX | 0.00004533 | ||||
| Deleverage ERC20 | 20556907 | 247 days ago | IN | 0 FRAX | 0.00000062 | ||||
| Leverage ERC20 | 20368860 | 251 days ago | IN | 0 FRAX | 0.00000047 | ||||
| Leverage ERC20 | 20368810 | 251 days ago | IN | 0 FRAX | 0.00000053 | ||||
| Leverage ERC20 | 20009255 | 260 days ago | IN | 0 FRAX | 0.0000004 | ||||
| Deleverage ERC20 | 18330746 | 298 days ago | IN | 0 FRAX | 0.0000006 | ||||
| Leverage ERC20 | 17170098 | 325 days ago | IN | 0 FRAX | 0.00000053 | ||||
| Deleverage ERC20 | 17135684 | 326 days ago | IN | 0 FRAX | 0.00000075 | ||||
| Deleverage ERC20 | 16831346 | 333 days ago | IN | 0 FRAX | 0.00000105 | ||||
| Leverage ERC20 | 16338192 | 345 days ago | IN | 0 FRAX | 0.00000047 | ||||
| Deleverage ERC20 | 16289984 | 346 days ago | IN | 0 FRAX | 0.00000066 | ||||
| Leverage ERC20 | 15936549 | 354 days ago | IN | 0 FRAX | 0.00000085 | ||||
| Leverage ERC20 | 15933824 | 354 days ago | IN | 0 FRAX | 0.00000076 | ||||
| Leverage ERC20 | 15670523 | 360 days ago | IN | 0 FRAX | 0.00000067 | ||||
| Leverage ERC20 | 15635115 | 361 days ago | IN | 0 FRAX | 0.00000131 | ||||
| Leverage ERC20 | 15563551 | 363 days ago | IN | 0 FRAX | 0.00000094 | ||||
| Leverage ERC20 | 15550277 | 363 days ago | IN | 0 FRAX | 0.00000103 | ||||
| Leverage ERC20 | 15340221 | 368 days ago | IN | 0 FRAX | 0.00000166 | ||||
| Leverage ERC20 | 15285450 | 369 days ago | IN | 0 FRAX | 0.00000275 | ||||
| Leverage ERC20 | 14634310 | 384 days ago | IN | 0 FRAX | 0.00000132 | ||||
| Leverage ERC20 | 13198084 | 417 days ago | IN | 0 FRAX | 0.00000266 | ||||
| Leverage ERC20 | 13140932 | 419 days ago | IN | 0 FRAX | 0.0000025 | ||||
| Deleverage Nativ... | 13140767 | 419 days ago | IN | 0 FRAX | 0.00000204 | ||||
| Deleverage ERC20 | 12831792 | 426 days ago | IN | 0 FRAX | 0.00000175 | ||||
| Leverage ERC20 | 12800691 | 426 days ago | IN | 0 FRAX | 0.00000181 |
Latest 7 internal transactions
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Leverager
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import "./interfaces/ILendingPool.sol";
import "./interfaces/ILendingPoolAddressesProvider.sol";
import "./interfaces/IFlashLoanReceiver.sol";
import "./interfaces/IWETH.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract Leverager is IFlashLoanReceiver, AccessControl {
using SafeERC20 for IERC20;
IWETH public immutable weth;
ILendingPool private immutable lendingPool;
ILendingPoolAddressesProvider private immutable addressesProvider;
uint256 public constant MIN_HF = 1.05e18;
bytes32 public constant PAUSER = keccak256("PAUSER");
bytes32 public constant UNPAUSER = keccak256("UNPAUSER");
bool public paused;
error Leverager__INVALID_INPUT();
error Leverager__INVALID_HEALTH_FACTOR();
error Leverager__UNAUTHORIZED_CALLER();
error Leverager__TRANSFER_FAILED();
error Leverager__INVALID_INITIATOR();
error Leverager__NATIVE_LEVERAGE_NOT_ACTIVATED();
error Leverager__INVALID_FLASHLOAN_CALLER();
error Leverager__PAUSED();
constructor(address _addressesProvider, address _weth) {
if (_addressesProvider == address(0)) revert Leverager__INVALID_INPUT();
addressesProvider = ILendingPoolAddressesProvider(_addressesProvider);
lendingPool = ILendingPool(addressesProvider.getLendingPool());
weth = IWETH(_weth);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
function leverageNative(
uint256 _borrowAmount,
uint256 _minHealthFactor
) external payable {
if (address(weth) == address(0)) revert Leverager__NATIVE_LEVERAGE_NOT_ACTIVATED();
if (msg.value != 0)
weth.deposit{value: msg.value}();
_leverage(address(weth), msg.value, _borrowAmount, _minHealthFactor);
}
function leverageERC20(
address _asset,
uint256 _initialDeposit,
uint256 _borrowAmount,
uint256 _minHealthFactor
) external {
if (_initialDeposit != 0)
IERC20(_asset).safeTransferFrom(msg.sender, address(this), _initialDeposit);
_leverage(_asset, _initialDeposit, _borrowAmount, _minHealthFactor);
}
function deleverageNative(uint256 _minHealthFactor) external {
if (address(weth) == address(0)) revert Leverager__NATIVE_LEVERAGE_NOT_ACTIVATED();
_deleverage(address(weth), _minHealthFactor);
weth.withdraw(weth.balanceOf(address(this)));
(bool success_, ) = payable(msg.sender).call{value: address(this).balance}("");
if (!success_) revert Leverager__TRANSFER_FAILED();
}
function deleverageERC20(
address _asset,
uint256 _minHealthFactor
) external {
_deleverage(_asset, _minHealthFactor);
uint256 assetBalance_ = IERC20(_asset).balanceOf(address(this));
if (assetBalance_ != 0)
IERC20(_asset).safeTransfer(msg.sender, assetBalance_);
}
/**
* @notice leverage an asset using flashloan.
* @dev Before calling _leverage() users will need to call:
* - DebtToken.approveDelegation(address(Leverager), _borrowAmount)
* - ERC20(_asset).approve(address(Leverager), _initialDeposit)
* @param _asset to leverage
* @param _initialDeposit amount to send
* @param _borrowAmount amount to borrow
* @param _minHealthFactor minimum hf
*/
function _leverage(
address _asset,
uint256 _initialDeposit,
uint256 _borrowAmount,
uint256 _minHealthFactor
) internal {
if (paused) revert Leverager__PAUSED();
if (_asset == address(0)) revert Leverager__INVALID_INPUT();
if (_borrowAmount == 0) revert Leverager__INVALID_INPUT();
if (_minHealthFactor < MIN_HF) revert Leverager__INVALID_HEALTH_FACTOR();
address[] memory assets_ = new address[](1);
assets_[0] = _asset;
uint256[] memory amounts_ = new uint256[](1);
amounts_[0] = _borrowAmount;
uint256[] memory modes_ = new uint256[](1);
modes_[0] = 2;
lendingPool.flashLoan(
address(this),
assets_, // [_asset]
amounts_,// [_borrowAmount]
modes_, // [2] variable debt
msg.sender, // onBehalfOf
abi.encode(true, msg.sender, _initialDeposit),
0 // referral code
);
(,,,,, uint256 healthFactor_) = lendingPool.getUserAccountData(msg.sender);
if (healthFactor_ < _minHealthFactor) revert Leverager__INVALID_HEALTH_FACTOR();
}
/**
* @notice deleverage an asset using flashloan.
* @dev Before calling loop() users will need to call:
* - ERC20(aToken).approve(address(this), type(uint256).max)
* @param _asset to deleverage
*/
function _deleverage(
address _asset,
uint256 _minHealthFactor
) internal {
if (paused) revert Leverager__PAUSED();
if (_asset == address(0)) revert Leverager__INVALID_INPUT();
if (_minHealthFactor < MIN_HF) revert Leverager__INVALID_HEALTH_FACTOR();
address debtToken_ = lendingPool.getReserveData(_asset).variableDebtTokenAddress;
address[] memory assets_ = new address[](1);
assets_[0] = _asset;
uint256[] memory amounts_ = new uint256[](1);
amounts_[0] = IERC20(debtToken_).balanceOf(msg.sender);
uint256[] memory modes_ = new uint256[](1);
modes_[0] = 0;
lendingPool.flashLoan(
address(this),
assets_, // [_asset]
amounts_,// [_borrowAmount]
modes_, // [0] no debt
msg.sender, // onBehalfOf
abi.encode(false, msg.sender, 0),
0 // referral code
);
(,,,,, uint256 healthFactor_) = lendingPool.getUserAccountData(msg.sender);
if (healthFactor_ < _minHealthFactor) revert Leverager__INVALID_HEALTH_FACTOR();
}
function executeOperation(
address[] memory _assets,
uint256[] memory _amounts,
uint256[] memory _premiums,
address _initiator,
bytes calldata _params
) external override returns (bool) {
if (paused) revert Leverager__PAUSED();
if (_initiator != address(this)) revert Leverager__INVALID_INITIATOR();
if (msg.sender != address(lendingPool)) revert Leverager__INVALID_FLASHLOAN_CALLER();
(bool isLeveraging, address sender_, uint256 initialDeposit_)
= abi.decode(_params, (bool, address, uint256));
// leverage
if (isLeveraging) {
uint256 amountToDeposit_ = initialDeposit_ + _amounts[0];
IERC20(_assets[0]).approve(address(lendingPool), amountToDeposit_);
lendingPool.deposit(
_assets[0],
amountToDeposit_,
sender_,
0
);
}
// deleverage
else {
address aToken_ = lendingPool.getReserveData(_assets[0]).aTokenAddress;
IERC20(_assets[0]).approve(address(lendingPool), _amounts[0]);
lendingPool.repay(
_assets[0],
_amounts[0],
2, // variable
sender_
);
IERC20(aToken_).safeTransferFrom(sender_, address(this), IERC20(aToken_).balanceOf(sender_));
lendingPool.withdraw(
_assets[0],
IERC20(aToken_).balanceOf(address(this)),
address(this)
);
// repay flashloan
IERC20(_assets[0]).approve(address(lendingPool), _amounts[0] + _premiums[0]);
}
return true;
}
function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider) {
return addressesProvider;
}
function LENDING_POOL() external view returns (ILendingPool) {
return lendingPool;
}
receive() external payable {
require(msg.sender == address(weth), 'Receive not allowed');
}
fallback() external payable {
revert('Fallback not allowed');
}
function pause() external onlyRole(PAUSER) {
paused = true;
}
function unpause() external onlyRole(UNPAUSER) {
paused = false;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (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.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
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].
*
* CAUTION: See Security Considerations above.
*/
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: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
import {ILendingPoolAddressesProvider} from './ILendingPoolAddressesProvider.sol';
import {ILendingPool} from './ILendingPool.sol';
/**
* @title IFlashLoanReceiver interface
* @notice Interface for the Aave fee IFlashLoanReceiver.
* @author Aave
* @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract
**/
interface IFlashLoanReceiver {
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external returns (bool);
function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider);
function LENDING_POOL() external view returns (ILendingPool);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
import {ILendingPoolAddressesProvider} from './ILendingPoolAddressesProvider.sol';
import {DataTypes} from '../lib/DataTypes.sol';
interface ILendingPool {
/**
* @dev Emitted on deposit()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the deposit
* @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
* @param amount The amount deposited
* @param referral The referral code used
**/
event Deposit(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referral
);
/**
* @dev Emitted on withdraw()
* @param reserve The address of the underlyng asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to Address that will receive the underlying
* @param amount The amount to be withdrawn
**/
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
/**
* @dev Emitted on borrow() and flashLoan() when debt needs to be opened
* @param reserve The address of the underlying asset being borrowed
* @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
* initiator of the transaction on flashLoan()
* @param onBehalfOf The address that will be getting the debt
* @param amount The amount borrowed out
* @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable
* @param borrowRate The numeric rate at which the user has borrowed
* @param referral The referral code used
**/
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint256 borrowRateMode,
uint256 borrowRate,
uint16 indexed referral
);
/**
* @dev Emitted on repay()
* @param reserve The address of the underlying asset of the reserve
* @param user The beneficiary of the repayment, getting his debt reduced
* @param repayer The address of the user initiating the repay(), providing the funds
* @param amount The amount repaid
**/
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount
);
/**
* @dev Emitted on swapBorrowRateMode()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user swapping his rate mode
* @param rateMode The rate mode that the user wants to swap to
**/
event Swap(address indexed reserve, address indexed user, uint256 rateMode);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on rebalanceStableBorrowRate()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user for which the rebalance has been executed
**/
event RebalanceStableBorrowRate(address indexed reserve, address indexed user);
/**
* @dev Emitted on flashLoan()
* @param target The address of the flash loan receiver contract
* @param initiator The address initiating the flash loan
* @param asset The address of the asset being flash borrowed
* @param amount The amount flash borrowed
* @param premium The fee flash borrowed
* @param referralCode The referral code used
**/
event FlashLoan(
address indexed target,
address indexed initiator,
address indexed asset,
uint256 amount,
uint256 premium,
uint16 referralCode
);
/**
* @dev Emitted when the pause is triggered.
*/
event Paused();
/**
* @dev Emitted when the pause is lifted.
*/
event Unpaused();
/**
* @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via
* LendingPoolCollateral manager using a DELEGATECALL
* This allows to have the events in the generated ABI for LendingPool.
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param liquidatedCollateralAmount The amount of collateral received by the liiquidator
* @param liquidator The address of the liquidator
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
event LiquidationCall(
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
/**
* @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared
* in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,
* the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it
* gets added to the LendingPool ABI
* @param reserve The address of the underlying asset of the reserve
* @param liquidityRate The new liquidity rate
* @param stableBorrowRate The new stable borrow rate
* @param variableBorrowRate The new variable borrow rate
* @param liquidityIndex The new liquidity index
* @param variableBorrowIndex The new variable borrow index
**/
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 stableBorrowRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
/**
* @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User deposits 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to deposit
* @param amount The amount to be deposited
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to Address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
**/
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256);
/**
* @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already deposited enough collateral, or he was given enough allowance by a credit delegator on the
* corresponding debt token (StableDebtToken or VariableDebtToken)
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 stable/variable debt tokens, depending on the `interestRateMode`
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
**/
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode,
uint16 referralCode,
address onBehalfOf
) external;
/**
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @return The final amount repaid
**/
function repay(
address asset,
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external returns (uint256);
/**
* @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa
* @param asset The address of the underlying asset borrowed
* @param rateMode The rate mode that the user wants to swap to
**/
function swapBorrowRateMode(address asset, uint256 rateMode) external;
/**
* @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
* - Users can be rebalanced if the following conditions are satisfied:
* 1. Usage ratio is above 95%
* 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been
* borrowed at a stable rate and depositors are not earning enough
* @param asset The address of the underlying asset borrowed
* @param user The address of the user to be rebalanced
**/
function rebalanceStableBorrowRate(address asset, address user) external;
/**
* @dev Allows depositors to enable/disable a specific deposited asset as collateral
* @param asset The address of the underlying asset deposited
* @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise
**/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
/**
* @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
function liquidationCall(
address collateralAsset,
address debtAsset,
address user,
uint256 debtToCover,
bool receiveAToken
) external;
/**
* @dev Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.
* For further details please visit https://developers.aave.com
* @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts amounts being flash-borrowed
* @param modes Types of the debt to open if the flash loan is not returned:
* 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
* 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function flashLoan(
address receiverAddress,
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata modes,
address onBehalfOf,
bytes calldata params,
uint16 referralCode
) external;
/**
* @dev Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralETH the total collateral in ETH of the user
* @return totalDebtETH the total debt in ETH of the user
* @return availableBorrowsETH the borrowing power left of the user
* @return currentLiquidationThreshold the liquidation threshold of the user
* @return ltv the loan to value of the user
* @return healthFactor the current health factor of the user
**/
function getUserAccountData(address user)
external
view
returns (
uint256 totalCollateralETH,
uint256 totalDebtETH,
uint256 availableBorrowsETH,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
function initReserve(
address reserve,
address aTokenAddress,
address stableDebtAddress,
address variableDebtAddress,
address interestRateStrategyAddress
) external;
function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress)
external;
function setConfiguration(address reserve, uint256 configuration) external;
/**
* @dev Returns the configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The configuration of the reserve
**/
function getConfiguration(address asset)
external
view
returns (DataTypes.ReserveConfigurationMap memory);
/**
* @dev Returns the configuration of the user across all the reserves
* @param user The user address
* @return The configuration of the user
**/
function getUserConfiguration(address user)
external
view
returns (DataTypes.UserConfigurationMap memory);
/**
* @dev Returns the normalized income normalized income of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve's normalized income
*/
function getReserveNormalizedIncome(address asset) external view returns (uint256);
/**
* @dev Returns the normalized variable debt per unit of asset
* @param asset The address of the underlying asset of the reserve
* @return The reserve normalized variable debt
*/
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
/**
* @dev Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state of the reserve
**/
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
function finalizeTransfer(
address asset,
address from,
address to,
uint256 amount,
uint256 balanceFromAfter,
uint256 balanceToBefore
) external;
function getReservesList() external view returns (address[] memory);
function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);
function setPause(bool val) external;
function paused() external view returns (bool);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
/**
* @title LendingPoolAddressesProvider contract
* @dev Main registry of addresses part of or connected to the protocol, including permissioned roles
* - Acting also as factory of proxies and admin of those, so with right to change its implementations
* - Owned by the Aave Governance
* @author Aave
**/
interface ILendingPoolAddressesProvider {
event MarketIdSet(string newMarketId);
event LendingPoolUpdated(address indexed newAddress);
event ConfigurationAdminUpdated(address indexed newAddress);
event EmergencyAdminUpdated(address indexed newAddress);
event LendingPoolConfiguratorUpdated(address indexed newAddress);
event LendingPoolCollateralManagerUpdated(address indexed newAddress);
event PriceOracleUpdated(address indexed newAddress);
event LendingRateOracleUpdated(address indexed newAddress);
event ProxyCreated(bytes32 id, address indexed newAddress);
event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);
function getMarketId() external view returns (string memory);
function setMarketId(string calldata marketId) external;
function setAddress(bytes32 id, address newAddress) external;
function setAddressAsProxy(bytes32 id, address impl) external;
function getAddress(bytes32 id) external view returns (address);
function getLendingPool() external view returns (address);
function setLendingPoolImpl(address pool) external;
function getLendingPoolConfigurator() external view returns (address);
function setLendingPoolConfiguratorImpl(address configurator) external;
function getLendingPoolCollateralManager() external view returns (address);
function setLendingPoolCollateralManager(address manager) external;
function getPoolAdmin() external view returns (address);
function setPoolAdmin(address admin) external;
function getEmergencyAdmin() external view returns (address);
function setEmergencyAdmin(address admin) external;
function getPriceOracle() external view returns (address);
function setPriceOracle(address priceOracle) external;
function getLendingRateOracle() external view returns (address);
function setLendingRateOracle(address lendingRateOracle) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IWETH {
function deposit() external payable;
function withdraw(uint256) external;
function approve(address guy, uint256 wad) external returns (bool);
function transferFrom(
address src,
address dst,
uint256 wad
) external returns (bool);
function balanceOf(address account) external view returns (uint256);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
library DataTypes {
// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
//the current stable borrow rate. Expressed in ray
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
//tokens addresses
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the id of the reserve. Represents the position in the list of the active reserves
uint8 id;
}
struct ReserveConfigurationMap {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: Reserve is active
//bit 57: reserve is frozen
//bit 58: borrowing is enabled
//bit 59: stable rate borrowing enabled
//bit 60-63: reserved
//bit 64-79: reserve factor
uint256 data;
}
struct UserConfigurationMap {
uint256 data;
}
enum InterestRateMode {NONE, STABLE, VARIABLE}
}{
"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[{"inputs":[{"internalType":"address","name":"_addressesProvider","type":"address"},{"internalType":"address","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Leverager__INVALID_FLASHLOAN_CALLER","type":"error"},{"inputs":[],"name":"Leverager__INVALID_HEALTH_FACTOR","type":"error"},{"inputs":[],"name":"Leverager__INVALID_INITIATOR","type":"error"},{"inputs":[],"name":"Leverager__INVALID_INPUT","type":"error"},{"inputs":[],"name":"Leverager__NATIVE_LEVERAGE_NOT_ACTIVATED","type":"error"},{"inputs":[],"name":"Leverager__PAUSED","type":"error"},{"inputs":[],"name":"Leverager__TRANSFER_FAILED","type":"error"},{"inputs":[],"name":"Leverager__UNAUTHORIZED_CALLER","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"ADDRESSES_PROVIDER","outputs":[{"internalType":"contract ILendingPoolAddressesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LENDING_POOL","outputs":[{"internalType":"contract ILendingPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_HF","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNPAUSER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_minHealthFactor","type":"uint256"}],"name":"deleverageERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minHealthFactor","type":"uint256"}],"name":"deleverageNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"_premiums","type":"uint256[]"},{"internalType":"address","name":"_initiator","type":"address"},{"internalType":"bytes","name":"_params","type":"bytes"}],"name":"executeOperation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_initialDeposit","type":"uint256"},{"internalType":"uint256","name":"_borrowAmount","type":"uint256"},{"internalType":"uint256","name":"_minHealthFactor","type":"uint256"}],"name":"leverageERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_borrowAmount","type":"uint256"},{"internalType":"uint256","name":"_minHealthFactor","type":"uint256"}],"name":"leverageNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60e06040523480156200001157600080fd5b5060405162002992380380620029928339810160408190526200003491620001b3565b6001600160a01b0382166200005c576040516373a2fd1160e11b815260040160405180910390fd5b6001600160a01b03821660c081905260408051630261bf8b60e01b81529051630261bf8b916004808201926020929091908290030181865afa158015620000a7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000cd9190620001eb565b6001600160a01b0390811660a0528116608052620000ed600033620000f5565b505062000210565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000192576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001513390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b80516001600160a01b0381168114620001ae57600080fd5b919050565b60008060408385031215620001c757600080fd5b620001d28362000196565b9150620001e26020840162000196565b90509250929050565b600060208284031215620001fe57600080fd5b620002098262000196565b9392505050565b60805160a05160c0516126c6620002cc600039600061022b01526000818161044c01528181610a3101528181610aea01528181610b6a01528181610c2e01528181610d1401528181610dc501528181610f340152818161108801528181611367015281816114470152818161167901528181611831015261191501526000818161013e015281816103280152818161063d01528181610687015281816106c1015281816107f70152818161084401526108bc01526126c66000f3fe60806040526004361061012e5760003560e01c80635c975abb116100ab578063920f5c841161006f578063920f5c8414610408578063a217fddf14610428578063b4dcfc771461043d578063d547741f14610470578063d9dc869414610490578063f42097ec146104c4576101a8565b80635c975abb14610386578063635fb9a6146103a05780638456cb59146103b357806387583755146103c857806391d14854146103e8576101a8565b806336568abe116100f257806336568abe146102e15780633f4ba83a146103015780633fc8cef31461031657806353a9e1a41461034a57806354edcb5214610366576101a8565b806301ffc9a7146101e75780630542975c1461021c5780630870dd5b14610263578063248a9ca3146102835780632f2ff15d146102c1576101a8565b366101a857336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146101a65760405162461bcd60e51b8152602060048201526013602482015272149958d95a5d99481b9bdd08185b1b1bddd959606a1b60448201526064015b60405180910390fd5b005b60405162461bcd60e51b815260206004820152601460248201527311985b1b189858dac81b9bdd08185b1b1bddd95960621b604482015260640161019d565b3480156101f357600080fd5b50610207610202366004611e5d565b6104f8565b60405190151581526020015b60405180910390f35b34801561022857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b039091168152602001610213565b34801561026f57600080fd5b506101a661027e366004611eac565b61052f565b34801561028f57600080fd5b506102b361029e366004611ee7565b60009081526020819052604090206001015490565b604051908152602001610213565b3480156102cd57600080fd5b506101a66102dc366004611f00565b61055c565b3480156102ed57600080fd5b506101a66102fc366004611f00565b610586565b34801561030d57600080fd5b506101a6610604565b34801561032257600080fd5b5061024b7f000000000000000000000000000000000000000000000000000000000000000081565b34801561035657600080fd5b506102b3670e92596fd629000081565b34801561037257600080fd5b506101a6610381366004611ee7565b61063b565b34801561039257600080fd5b506001546102079060ff1681565b6101a66103ae366004611f30565b6107f5565b3480156103bf57600080fd5b506101a66108e3565b3480156103d457600080fd5b506101a66103e3366004611f52565b61091c565b3480156103f457600080fd5b50610207610403366004611f00565b6109ad565b34801561041457600080fd5b506102076104233660046120c7565b6109d6565b34801561043457600080fd5b506102b3600081565b34801561044957600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061024b565b34801561047c57600080fd5b506101a661048b366004611f00565b611169565b34801561049c57600080fd5b506102b37f539440820030c4994db4e31b6b800deafd503688728f932addfe7a410515c14c81565b3480156104d057600080fd5b506102b37f82b32d9ab5100db08aeb9a0e08b422d14851ec118736590462bf9c085a6e944881565b60006001600160e01b03198216637965db0b60e01b148061052957506301ffc9a760e01b6001600160e01b03198316145b92915050565b821561054a5761054a6001600160a01b03851633308661118e565b610556848484846111f9565b50505050565b600082815260208190526040902060010154610577816114ed565b61058183836114fa565b505050565b6001600160a01b03811633146105f65760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b606482015260840161019d565b610600828261157e565b5050565b7f82b32d9ab5100db08aeb9a0e08b422d14851ec118736590462bf9c085a6e944861062e816114ed565b506001805460ff19169055565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166106825760405163c090d90f60e01b815260040160405180910390fd5b6106ac7f0000000000000000000000000000000000000000000000000000000000000000826115e3565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d9082906370a0823190602401602060405180830381865afa158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c91906121e9565b6040518263ffffffff1660e01b815260040161075a91815260200190565b600060405180830381600087803b15801561077457600080fd5b505af1158015610788573d6000803e3d6000fd5b50506040516000925033915047908381818185875af1925050503d80600081146107ce576040519150601f19603f3d011682016040523d82523d6000602084013e6107d3565b606091505b50509050806106005760405163090880f160e21b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661083c5760405163c090d90f60e01b815260040160405180910390fd5b34156108b7577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561089d57600080fd5b505af11580156108b1573d6000803e3d6000fd5b50505050505b6106007f00000000000000000000000000000000000000000000000000000000000000003484846111f9565b7f539440820030c4994db4e31b6b800deafd503688728f932addfe7a410515c14c61090d816114ed565b506001805460ff191681179055565b61092682826115e3565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561096d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099191906121e9565b90508015610581576105816001600160a01b03841633836119ba565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60015460009060ff16156109fd57604051634358fa5560e11b815260040160405180910390fd5b6001600160a01b0384163014610a265760405163486b182d60e11b815260040160405180910390fd5b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a6f57604051633a5a19c960e11b815260040160405180910390fd5b60008080610a7f85870187612210565b9250925092508215610c2a57600089600081518110610aa057610aa0612251565b602002602001015182610ab3919061227d565b90508a600081518110610ac857610ac8612251565b602090810291909101015160405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018490529091169063095ea7b3906044016020604051808303816000875af1158015610b43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b679190612290565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e8eda9df8c600081518110610baa57610baa612251565b60209081029190910101516040516001600160e01b031960e084901b1681526001600160a01b03918216600482015260248101859052908616604482015260006064820152608401600060405180830381600087803b158015610c0c57600080fd5b505af1158015610c20573d6000803e3d6000fd5b5050505050611159565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335ea6a758c600081518110610c6e57610c6e612251565b60200260200101516040518263ffffffff1660e01b8152600401610ca191906001600160a01b0391909116815260200190565b61018060405180830381865afa158015610cbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce39190612340565b60e0015190508a600081518110610cfc57610cfc612251565b60200260200101516001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000008c600081518110610d4657610d46612251565b60200260200101516040518363ffffffff1660e01b8152600401610d7f9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610d9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc29190612290565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663573ade818c600081518110610e0557610e05612251565b60200260200101518c600081518110610e2057610e20612251565b60209081029190910101516040516001600160e01b031960e085901b1681526001600160a01b03928316600482015260248101919091526002604482015290861660648201526084016020604051808303816000875af1158015610e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eac91906121e9565b506040516370a0823160e01b81526001600160a01b038085166004830152610f329185913091908516906370a0823190602401602060405180830381865afa158015610efc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2091906121e9565b6001600160a01b03851692919061118e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166369328dec8c600081518110610f7457610f74612251565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015610fc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe791906121e9565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201523060448201526064016020604051808303816000875af1158015611038573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105c91906121e9565b508a60008151811061107057611070612251565b60200260200101516001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000008b6000815181106110ba576110ba612251565b60200260200101518d6000815181106110d5576110d5612251565b60200260200101516110e7919061227d565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611132573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111569190612290565b50505b5060019998505050505050505050565b600082815260208190526040902060010154611184816114ed565b610581838361157e565b6040516001600160a01b03808516602483015283166044820152606481018290526105569085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526119ea565b60015460ff161561121d57604051634358fa5560e11b815260040160405180910390fd5b6001600160a01b038416611244576040516373a2fd1160e11b815260040160405180910390fd5b81600003611265576040516373a2fd1160e11b815260040160405180910390fd5b670e92596fd629000081101561128e57604051630cb463f160e01b815260040160405180910390fd5b6040805160018082528183019092526000916020808301908036833701905050905084816000815181106112c4576112c4612251565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050838160008151811061131557611315612251565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905060028160008151811061135957611359612251565b6020026020010181815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ab9c4b5d30858585336001338e6040516020016113cb9392919092151583526001600160a01b03919091166020830152604082015260600190565b60405160208183030381529060405260006040518863ffffffff1660e01b81526004016113fe97969594939291906124b8565b600060405180830381600087803b15801561141857600080fd5b505af115801561142c573d6000803e3d6000fd5b5050604051632fe4a15f60e21b8152336004820152600092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316915063bf92857c9060240160c060405180830381865afa158015611497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bb9190612574565b95505050505050848110156114e357604051630cb463f160e01b815260040160405180910390fd5b5050505050505050565b6114f78133611abf565b50565b61150482826109ad565b610600576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561153a3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61158882826109ad565b15610600576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60015460ff161561160757604051634358fa5560e11b815260040160405180910390fd5b6001600160a01b03821661162e576040516373a2fd1160e11b815260040160405180910390fd5b670e92596fd629000081101561165757604051630cb463f160e01b815260040160405180910390fd5b6040516335ea6a7560e01b81526001600160a01b0383811660048301526000917f0000000000000000000000000000000000000000000000000000000000000000909116906335ea6a759060240161018060405180830381865afa1580156116c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e79190612340565b61012001516040805160018082528183019092529192506000919060208083019080368337019050509050838160008151811061172657611726612251565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050506040516370a0823160e01b81523360048201529091506001600160a01b038416906370a0823190602401602060405180830381865afa1580156117a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117cc91906121e9565b816000815181106117df576117df612251565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905060008160008151811061182357611823612251565b6020026020010181815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ab9c4b5d308585853360003360006040516020016118999392919092151583526001600160a01b0391909116602083015260ff16604082015260600190565b60405160208183030381529060405260006040518863ffffffff1660e01b81526004016118cc97969594939291906124b8565b600060405180830381600087803b1580156118e657600080fd5b505af11580156118fa573d6000803e3d6000fd5b5050604051632fe4a15f60e21b8152336004820152600092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316915063bf92857c9060240160c060405180830381865afa158015611965573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119899190612574565b95505050505050858110156119b157604051630cb463f160e01b815260040160405180910390fd5b50505050505050565b6040516001600160a01b03831660248201526044810182905261058190849063a9059cbb60e01b906064016111c2565b6000611a3f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611b189092919063ffffffff16565b9050805160001480611a60575080806020019051810190611a609190612290565b6105815760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161019d565b611ac982826109ad565b61060057611ad681611b2f565b611ae1836020611b41565b604051602001611af29291906125be565b60408051601f198184030181529082905262461bcd60e51b825261019d91600401612633565b6060611b278484600085611ce4565b949350505050565b60606105296001600160a01b03831660145b60606000611b50836002612646565b611b5b90600261227d565b67ffffffffffffffff811115611b7357611b73611f7e565b6040519080825280601f01601f191660200182016040528015611b9d576020820181803683370190505b509050600360fc1b81600081518110611bb857611bb8612251565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611be757611be7612251565b60200101906001600160f81b031916908160001a9053506000611c0b846002612646565b611c1690600161227d565b90505b6001811115611c8e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611c4a57611c4a612251565b1a60f81b828281518110611c6057611c60612251565b60200101906001600160f81b031916908160001a90535060049490941c93611c878161265d565b9050611c19565b508315611cdd5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161019d565b9392505050565b606082471015611d455760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161019d565b600080866001600160a01b03168587604051611d619190612674565b60006040518083038185875af1925050503d8060008114611d9e576040519150601f19603f3d011682016040523d82523d6000602084013e611da3565b606091505b5091509150611db487838387611dbf565b979650505050505050565b60608315611e2e578251600003611e27576001600160a01b0385163b611e275760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161019d565b5081611b27565b611b278383815115611e435781518083602001fd5b8060405162461bcd60e51b815260040161019d9190612633565b600060208284031215611e6f57600080fd5b81356001600160e01b031981168114611cdd57600080fd5b6001600160a01b03811681146114f757600080fd5b8035611ea781611e87565b919050565b60008060008060808587031215611ec257600080fd5b8435611ecd81611e87565b966020860135965060408601359560600135945092505050565b600060208284031215611ef957600080fd5b5035919050565b60008060408385031215611f1357600080fd5b823591506020830135611f2581611e87565b809150509250929050565b60008060408385031215611f4357600080fd5b50508035926020909101359150565b60008060408385031215611f6557600080fd5b8235611f7081611e87565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051610180810167ffffffffffffffff81118282101715611fb857611fb8611f7e565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611fe757611fe7611f7e565b604052919050565b600067ffffffffffffffff82111561200957612009611f7e565b5060051b60200190565b600082601f83011261202457600080fd5b8135602061203961203483611fef565b611fbe565b82815260059290921b8401810191818101908684111561205857600080fd5b8286015b84811015612073578035835291830191830161205c565b509695505050505050565b60008083601f84011261209057600080fd5b50813567ffffffffffffffff8111156120a857600080fd5b6020830191508360208285010111156120c057600080fd5b9250929050565b60008060008060008060a087890312156120e057600080fd5b863567ffffffffffffffff808211156120f857600080fd5b818901915089601f83011261210c57600080fd5b8135602061211c61203483611fef565b82815260059290921b8401810191818101908d84111561213b57600080fd5b948201945b8386101561216257853561215381611e87565b82529482019490820190612140565b9a50508a01359250508082111561217857600080fd5b6121848a838b01612013565b9650604089013591508082111561219a57600080fd5b6121a68a838b01612013565b95506121b460608a01611e9c565b945060808901359150808211156121ca57600080fd5b506121d789828a0161207e565b979a9699509497509295939492505050565b6000602082840312156121fb57600080fd5b5051919050565b80151581146114f757600080fd5b60008060006060848603121561222557600080fd5b833561223081612202565b9250602084013561224081611e87565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561052957610529612267565b6000602082840312156122a257600080fd5b8151611cdd81612202565b6000602082840312156122bf57600080fd5b6040516020810181811067ffffffffffffffff821117156122e2576122e2611f7e565b6040529151825250919050565b80516fffffffffffffffffffffffffffffffff81168114611ea757600080fd5b805164ffffffffff81168114611ea757600080fd5b8051611ea781611e87565b805160ff81168114611ea757600080fd5b6000610180828403121561235357600080fd5b61235b611f94565b61236584846122ad565b8152612373602084016122ef565b6020820152612384604084016122ef565b6040820152612395606084016122ef565b60608201526123a6608084016122ef565b60808201526123b760a084016122ef565b60a08201526123c860c0840161230f565b60c08201526123d960e08401612324565b60e08201526101006123ec818501612324565b908201526101206123fe848201612324565b90820152610140612410848201612324565b9082015261016061242284820161232f565b908201529392505050565b600081518084526020808501945080840160005b8381101561245d57815187529582019590820190600101612441565b509495945050505050565b60005b8381101561248357818101518382015260200161246b565b50506000910152565b600081518084526124a4816020860160208601612468565b601f01601f19169290920160200192915050565b6001600160a01b03888116825260e0602080840182905289519184018290526000928a820192909190610100860190855b818110156125075785518516835294830194918301916001016124e9565b5050858103604087015261251b818c61242d565b93505050508281036060840152612532818861242d565b6001600160a01b0387166080850152905082810360a0840152612555818661248c565b91505061256860c083018461ffff169052565b98975050505050505050565b60008060008060008060c0878903121561258d57600080fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516125f6816017850160208801612468565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612627816028840160208801612468565b01602801949350505050565b602081526000611cdd602083018461248c565b808202811582820484141761052957610529612267565b60008161266c5761266c612267565b506000190190565b60008251612686818460208701612468565b919091019291505056fea2646970667358221220a1a77e1d2368b4167ae9fe236ebc61076871311837bdebcdc535f17bea9d137164736f6c63430008130033000000000000000000000000198147e0a57f009e337ea3f0e5fe9bbca3ed1975000000000000000000000000fc00000000000000000000000000000000000006
Deployed Bytecode
0x60806040526004361061012e5760003560e01c80635c975abb116100ab578063920f5c841161006f578063920f5c8414610408578063a217fddf14610428578063b4dcfc771461043d578063d547741f14610470578063d9dc869414610490578063f42097ec146104c4576101a8565b80635c975abb14610386578063635fb9a6146103a05780638456cb59146103b357806387583755146103c857806391d14854146103e8576101a8565b806336568abe116100f257806336568abe146102e15780633f4ba83a146103015780633fc8cef31461031657806353a9e1a41461034a57806354edcb5214610366576101a8565b806301ffc9a7146101e75780630542975c1461021c5780630870dd5b14610263578063248a9ca3146102835780632f2ff15d146102c1576101a8565b366101a857336001600160a01b037f000000000000000000000000fc0000000000000000000000000000000000000616146101a65760405162461bcd60e51b8152602060048201526013602482015272149958d95a5d99481b9bdd08185b1b1bddd959606a1b60448201526064015b60405180910390fd5b005b60405162461bcd60e51b815260206004820152601460248201527311985b1b189858dac81b9bdd08185b1b1bddd95960621b604482015260640161019d565b3480156101f357600080fd5b50610207610202366004611e5d565b6104f8565b60405190151581526020015b60405180910390f35b34801561022857600080fd5b507f000000000000000000000000198147e0a57f009e337ea3f0e5fe9bbca3ed19755b6040516001600160a01b039091168152602001610213565b34801561026f57600080fd5b506101a661027e366004611eac565b61052f565b34801561028f57600080fd5b506102b361029e366004611ee7565b60009081526020819052604090206001015490565b604051908152602001610213565b3480156102cd57600080fd5b506101a66102dc366004611f00565b61055c565b3480156102ed57600080fd5b506101a66102fc366004611f00565b610586565b34801561030d57600080fd5b506101a6610604565b34801561032257600080fd5b5061024b7f000000000000000000000000fc0000000000000000000000000000000000000681565b34801561035657600080fd5b506102b3670e92596fd629000081565b34801561037257600080fd5b506101a6610381366004611ee7565b61063b565b34801561039257600080fd5b506001546102079060ff1681565b6101a66103ae366004611f30565b6107f5565b3480156103bf57600080fd5b506101a66108e3565b3480156103d457600080fd5b506101a66103e3366004611f52565b61091c565b3480156103f457600080fd5b50610207610403366004611f00565b6109ad565b34801561041457600080fd5b506102076104233660046120c7565b6109d6565b34801561043457600080fd5b506102b3600081565b34801561044957600080fd5b507f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d522861024b565b34801561047c57600080fd5b506101a661048b366004611f00565b611169565b34801561049c57600080fd5b506102b37f539440820030c4994db4e31b6b800deafd503688728f932addfe7a410515c14c81565b3480156104d057600080fd5b506102b37f82b32d9ab5100db08aeb9a0e08b422d14851ec118736590462bf9c085a6e944881565b60006001600160e01b03198216637965db0b60e01b148061052957506301ffc9a760e01b6001600160e01b03198316145b92915050565b821561054a5761054a6001600160a01b03851633308661118e565b610556848484846111f9565b50505050565b600082815260208190526040902060010154610577816114ed565b61058183836114fa565b505050565b6001600160a01b03811633146105f65760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b606482015260840161019d565b610600828261157e565b5050565b7f82b32d9ab5100db08aeb9a0e08b422d14851ec118736590462bf9c085a6e944861062e816114ed565b506001805460ff19169055565b7f000000000000000000000000fc000000000000000000000000000000000000066001600160a01b03166106825760405163c090d90f60e01b815260040160405180910390fd5b6106ac7f000000000000000000000000fc00000000000000000000000000000000000006826115e3565b6040516370a0823160e01b81523060048201527f000000000000000000000000fc000000000000000000000000000000000000066001600160a01b031690632e1a7d4d9082906370a0823190602401602060405180830381865afa158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c91906121e9565b6040518263ffffffff1660e01b815260040161075a91815260200190565b600060405180830381600087803b15801561077457600080fd5b505af1158015610788573d6000803e3d6000fd5b50506040516000925033915047908381818185875af1925050503d80600081146107ce576040519150601f19603f3d011682016040523d82523d6000602084013e6107d3565b606091505b50509050806106005760405163090880f160e21b815260040160405180910390fd5b7f000000000000000000000000fc000000000000000000000000000000000000066001600160a01b031661083c5760405163c090d90f60e01b815260040160405180910390fd5b34156108b7577f000000000000000000000000fc000000000000000000000000000000000000066001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561089d57600080fd5b505af11580156108b1573d6000803e3d6000fd5b50505050505b6106007f000000000000000000000000fc000000000000000000000000000000000000063484846111f9565b7f539440820030c4994db4e31b6b800deafd503688728f932addfe7a410515c14c61090d816114ed565b506001805460ff191681179055565b61092682826115e3565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561096d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099191906121e9565b90508015610581576105816001600160a01b03841633836119ba565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60015460009060ff16156109fd57604051634358fa5560e11b815260040160405180910390fd5b6001600160a01b0384163014610a265760405163486b182d60e11b815260040160405180910390fd5b336001600160a01b037f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52281614610a6f57604051633a5a19c960e11b815260040160405180910390fd5b60008080610a7f85870187612210565b9250925092508215610c2a57600089600081518110610aa057610aa0612251565b602002602001015182610ab3919061227d565b90508a600081518110610ac857610ac8612251565b602090810291909101015160405163095ea7b360e01b81526001600160a01b037f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d522881166004830152602482018490529091169063095ea7b3906044016020604051808303816000875af1158015610b43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b679190612290565b507f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52286001600160a01b031663e8eda9df8c600081518110610baa57610baa612251565b60209081029190910101516040516001600160e01b031960e084901b1681526001600160a01b03918216600482015260248101859052908616604482015260006064820152608401600060405180830381600087803b158015610c0c57600080fd5b505af1158015610c20573d6000803e3d6000fd5b5050505050611159565b60007f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52286001600160a01b03166335ea6a758c600081518110610c6e57610c6e612251565b60200260200101516040518263ffffffff1660e01b8152600401610ca191906001600160a01b0391909116815260200190565b61018060405180830381865afa158015610cbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce39190612340565b60e0015190508a600081518110610cfc57610cfc612251565b60200260200101516001600160a01b031663095ea7b37f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52288c600081518110610d4657610d46612251565b60200260200101516040518363ffffffff1660e01b8152600401610d7f9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610d9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc29190612290565b507f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52286001600160a01b031663573ade818c600081518110610e0557610e05612251565b60200260200101518c600081518110610e2057610e20612251565b60209081029190910101516040516001600160e01b031960e085901b1681526001600160a01b03928316600482015260248101919091526002604482015290861660648201526084016020604051808303816000875af1158015610e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eac91906121e9565b506040516370a0823160e01b81526001600160a01b038085166004830152610f329185913091908516906370a0823190602401602060405180830381865afa158015610efc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2091906121e9565b6001600160a01b03851692919061118e565b7f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52286001600160a01b03166369328dec8c600081518110610f7457610f74612251565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015610fc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe791906121e9565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201523060448201526064016020604051808303816000875af1158015611038573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105c91906121e9565b508a60008151811061107057611070612251565b60200260200101516001600160a01b031663095ea7b37f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52288b6000815181106110ba576110ba612251565b60200260200101518d6000815181106110d5576110d5612251565b60200260200101516110e7919061227d565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611132573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111569190612290565b50505b5060019998505050505050505050565b600082815260208190526040902060010154611184816114ed565b610581838361157e565b6040516001600160a01b03808516602483015283166044820152606481018290526105569085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526119ea565b60015460ff161561121d57604051634358fa5560e11b815260040160405180910390fd5b6001600160a01b038416611244576040516373a2fd1160e11b815260040160405180910390fd5b81600003611265576040516373a2fd1160e11b815260040160405180910390fd5b670e92596fd629000081101561128e57604051630cb463f160e01b815260040160405180910390fd5b6040805160018082528183019092526000916020808301908036833701905050905084816000815181106112c4576112c4612251565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050838160008151811061131557611315612251565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905060028160008151811061135957611359612251565b6020026020010181815250507f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52286001600160a01b031663ab9c4b5d30858585336001338e6040516020016113cb9392919092151583526001600160a01b03919091166020830152604082015260600190565b60405160208183030381529060405260006040518863ffffffff1660e01b81526004016113fe97969594939291906124b8565b600060405180830381600087803b15801561141857600080fd5b505af115801561142c573d6000803e3d6000fd5b5050604051632fe4a15f60e21b8152336004820152600092507f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52286001600160a01b0316915063bf92857c9060240160c060405180830381865afa158015611497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bb9190612574565b95505050505050848110156114e357604051630cb463f160e01b815260040160405180910390fd5b5050505050505050565b6114f78133611abf565b50565b61150482826109ad565b610600576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561153a3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61158882826109ad565b15610600576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60015460ff161561160757604051634358fa5560e11b815260040160405180910390fd5b6001600160a01b03821661162e576040516373a2fd1160e11b815260040160405180910390fd5b670e92596fd629000081101561165757604051630cb463f160e01b815260040160405180910390fd5b6040516335ea6a7560e01b81526001600160a01b0383811660048301526000917f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d5228909116906335ea6a759060240161018060405180830381865afa1580156116c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e79190612340565b61012001516040805160018082528183019092529192506000919060208083019080368337019050509050838160008151811061172657611726612251565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050506040516370a0823160e01b81523360048201529091506001600160a01b038416906370a0823190602401602060405180830381865afa1580156117a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117cc91906121e9565b816000815181106117df576117df612251565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905060008160008151811061182357611823612251565b6020026020010181815250507f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52286001600160a01b031663ab9c4b5d308585853360003360006040516020016118999392919092151583526001600160a01b0391909116602083015260ff16604082015260600190565b60405160208183030381529060405260006040518863ffffffff1660e01b81526004016118cc97969594939291906124b8565b600060405180830381600087803b1580156118e657600080fd5b505af11580156118fa573d6000803e3d6000fd5b5050604051632fe4a15f60e21b8152336004820152600092507f000000000000000000000000c1c5312bcaa6cb2ada949553af75802fe48d52286001600160a01b0316915063bf92857c9060240160c060405180830381865afa158015611965573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119899190612574565b95505050505050858110156119b157604051630cb463f160e01b815260040160405180910390fd5b50505050505050565b6040516001600160a01b03831660248201526044810182905261058190849063a9059cbb60e01b906064016111c2565b6000611a3f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611b189092919063ffffffff16565b9050805160001480611a60575080806020019051810190611a609190612290565b6105815760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161019d565b611ac982826109ad565b61060057611ad681611b2f565b611ae1836020611b41565b604051602001611af29291906125be565b60408051601f198184030181529082905262461bcd60e51b825261019d91600401612633565b6060611b278484600085611ce4565b949350505050565b60606105296001600160a01b03831660145b60606000611b50836002612646565b611b5b90600261227d565b67ffffffffffffffff811115611b7357611b73611f7e565b6040519080825280601f01601f191660200182016040528015611b9d576020820181803683370190505b509050600360fc1b81600081518110611bb857611bb8612251565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611be757611be7612251565b60200101906001600160f81b031916908160001a9053506000611c0b846002612646565b611c1690600161227d565b90505b6001811115611c8e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611c4a57611c4a612251565b1a60f81b828281518110611c6057611c60612251565b60200101906001600160f81b031916908160001a90535060049490941c93611c878161265d565b9050611c19565b508315611cdd5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161019d565b9392505050565b606082471015611d455760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161019d565b600080866001600160a01b03168587604051611d619190612674565b60006040518083038185875af1925050503d8060008114611d9e576040519150601f19603f3d011682016040523d82523d6000602084013e611da3565b606091505b5091509150611db487838387611dbf565b979650505050505050565b60608315611e2e578251600003611e27576001600160a01b0385163b611e275760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161019d565b5081611b27565b611b278383815115611e435781518083602001fd5b8060405162461bcd60e51b815260040161019d9190612633565b600060208284031215611e6f57600080fd5b81356001600160e01b031981168114611cdd57600080fd5b6001600160a01b03811681146114f757600080fd5b8035611ea781611e87565b919050565b60008060008060808587031215611ec257600080fd5b8435611ecd81611e87565b966020860135965060408601359560600135945092505050565b600060208284031215611ef957600080fd5b5035919050565b60008060408385031215611f1357600080fd5b823591506020830135611f2581611e87565b809150509250929050565b60008060408385031215611f4357600080fd5b50508035926020909101359150565b60008060408385031215611f6557600080fd5b8235611f7081611e87565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051610180810167ffffffffffffffff81118282101715611fb857611fb8611f7e565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611fe757611fe7611f7e565b604052919050565b600067ffffffffffffffff82111561200957612009611f7e565b5060051b60200190565b600082601f83011261202457600080fd5b8135602061203961203483611fef565b611fbe565b82815260059290921b8401810191818101908684111561205857600080fd5b8286015b84811015612073578035835291830191830161205c565b509695505050505050565b60008083601f84011261209057600080fd5b50813567ffffffffffffffff8111156120a857600080fd5b6020830191508360208285010111156120c057600080fd5b9250929050565b60008060008060008060a087890312156120e057600080fd5b863567ffffffffffffffff808211156120f857600080fd5b818901915089601f83011261210c57600080fd5b8135602061211c61203483611fef565b82815260059290921b8401810191818101908d84111561213b57600080fd5b948201945b8386101561216257853561215381611e87565b82529482019490820190612140565b9a50508a01359250508082111561217857600080fd5b6121848a838b01612013565b9650604089013591508082111561219a57600080fd5b6121a68a838b01612013565b95506121b460608a01611e9c565b945060808901359150808211156121ca57600080fd5b506121d789828a0161207e565b979a9699509497509295939492505050565b6000602082840312156121fb57600080fd5b5051919050565b80151581146114f757600080fd5b60008060006060848603121561222557600080fd5b833561223081612202565b9250602084013561224081611e87565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561052957610529612267565b6000602082840312156122a257600080fd5b8151611cdd81612202565b6000602082840312156122bf57600080fd5b6040516020810181811067ffffffffffffffff821117156122e2576122e2611f7e565b6040529151825250919050565b80516fffffffffffffffffffffffffffffffff81168114611ea757600080fd5b805164ffffffffff81168114611ea757600080fd5b8051611ea781611e87565b805160ff81168114611ea757600080fd5b6000610180828403121561235357600080fd5b61235b611f94565b61236584846122ad565b8152612373602084016122ef565b6020820152612384604084016122ef565b6040820152612395606084016122ef565b60608201526123a6608084016122ef565b60808201526123b760a084016122ef565b60a08201526123c860c0840161230f565b60c08201526123d960e08401612324565b60e08201526101006123ec818501612324565b908201526101206123fe848201612324565b90820152610140612410848201612324565b9082015261016061242284820161232f565b908201529392505050565b600081518084526020808501945080840160005b8381101561245d57815187529582019590820190600101612441565b509495945050505050565b60005b8381101561248357818101518382015260200161246b565b50506000910152565b600081518084526124a4816020860160208601612468565b601f01601f19169290920160200192915050565b6001600160a01b03888116825260e0602080840182905289519184018290526000928a820192909190610100860190855b818110156125075785518516835294830194918301916001016124e9565b5050858103604087015261251b818c61242d565b93505050508281036060840152612532818861242d565b6001600160a01b0387166080850152905082810360a0840152612555818661248c565b91505061256860c083018461ffff169052565b98975050505050505050565b60008060008060008060c0878903121561258d57600080fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516125f6816017850160208801612468565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612627816028840160208801612468565b01602801949350505050565b602081526000611cdd602083018461248c565b808202811582820484141761052957610529612267565b60008161266c5761266c612267565b506000190190565b60008251612686818460208701612468565b919091019291505056fea2646970667358221220a1a77e1d2368b4167ae9fe236ebc61076871311837bdebcdc535f17bea9d137164736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000198147e0a57f009e337ea3f0e5fe9bbca3ed1975000000000000000000000000fc00000000000000000000000000000000000006
-----Decoded View---------------
Arg [0] : _addressesProvider (address): 0x198147E0A57F009E337EA3F0E5FE9bbCa3ED1975
Arg [1] : _weth (address): 0xFC00000000000000000000000000000000000006
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000198147e0a57f009e337ea3f0e5fe9bbca3ed1975
Arg [1] : 000000000000000000000000fc00000000000000000000000000000000000006
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.