Multichain Info
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AaveV3Withdraw
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2023-01-25
*/
// SPDX-License-Identifier: MIT
pragma solidity =0.8.10;
interface IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint256 digits);
function totalSupply() external view returns (uint256 supply);
function balanceOf(address _owner) external view returns (uint256 balance);
function transfer(address _to, uint256 _value) external returns (bool success);
function transferFrom(
address _from,
address _to,
uint256 _value
) external returns (bool success);
function approve(address _spender, uint256 _value) external returns (bool success);
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
abstract contract IWETH {
function allowance(address, address) public virtual view returns (uint256);
function balanceOf(address) public virtual view returns (uint256);
function approve(address, uint256) public virtual;
function transfer(address, uint256) public virtual returns (bool);
function transferFrom(
address,
address,
uint256
) public virtual returns (bool);
function deposit() public payable virtual;
function withdraw(uint256) public virtual;
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
library Address {
//insufficient balance
error InsufficientBalance(uint256 available, uint256 required);
//unable to send value, recipient may have reverted
error SendingValueFail();
//insufficient balance for call
error InsufficientBalanceForCall(uint256 available, uint256 required);
//call to non-contract
error NonContractCall();
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly {
codehash := extcodehash(account)
}
return (codehash != accountHash && codehash != 0x0);
}
function sendValue(address payable recipient, uint256 amount) internal {
uint256 balance = address(this).balance;
if (balance < amount){
revert InsufficientBalance(balance, amount);
}
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{value: amount}("");
if (!(success)){
revert SendingValueFail();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
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");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
uint256 balance = address(this).balance;
if (balance < value){
revert InsufficientBalanceForCall(balance, value);
}
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(
address target,
bytes memory data,
uint256 weiValue,
string memory errorMessage
) private returns (bytes memory) {
if (!(isContract(target))){
revert NonContractCall();
}
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{value: weiValue}(data);
if (success) {
return returndata;
} else {
// 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
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
);
}
/// @dev Edited so it always first approves 0 and then the value, because of non standard tokens
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(
token,
abi.encodeWithSelector(token.approve.selector, spender, newAllowance)
);
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(
value,
"SafeERC20: decreased allowance below zero"
);
_callOptionalReturn(
token,
abi.encodeWithSelector(token.approve.selector, spender, newAllowance)
);
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(
data,
"SafeERC20: low-level call failed"
);
if (returndata.length > 0) {
// Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
abstract contract IDFSRegistry {
function getAddr(bytes4 _id) public view virtual returns (address);
function addNewContract(
bytes32 _id,
address _contractAddr,
uint256 _waitPeriod
) public virtual;
function startContractChange(bytes32 _id, address _newContractAddr) public virtual;
function approveContractChange(bytes32 _id) public virtual;
function cancelContractChange(bytes32 _id) public virtual;
function changeWaitPeriod(bytes32 _id, uint256 _newWaitPeriod) public virtual;
}
contract MainnetAuthAddresses {
address internal constant ADMIN_VAULT_ADDR = 0xCCf3d848e08b94478Ed8f46fFead3008faF581fD;
address internal constant FACTORY_ADDRESS = 0x5a15566417e6C1c9546523066500bDDBc53F88C7;
address internal constant ADMIN_ADDR = 0x25eFA336886C74eA8E282ac466BdCd0199f85BB9; // USED IN ADMIN VAULT CONSTRUCTOR
}
contract AuthHelper is MainnetAuthAddresses {
}
contract AdminVault is AuthHelper {
address public owner;
address public admin;
error SenderNotAdmin();
constructor() {
owner = msg.sender;
admin = ADMIN_ADDR;
}
/// @notice Admin is able to change owner
/// @param _owner Address of new owner
function changeOwner(address _owner) public {
if (admin != msg.sender){
revert SenderNotAdmin();
}
owner = _owner;
}
/// @notice Admin is able to set new admin
/// @param _admin Address of multisig that becomes new admin
function changeAdmin(address _admin) public {
if (admin != msg.sender){
revert SenderNotAdmin();
}
admin = _admin;
}
}
contract AdminAuth is AuthHelper {
using SafeERC20 for IERC20;
AdminVault public constant adminVault = AdminVault(ADMIN_VAULT_ADDR);
error SenderNotOwner();
error SenderNotAdmin();
modifier onlyOwner() {
if (adminVault.owner() != msg.sender){
revert SenderNotOwner();
}
_;
}
modifier onlyAdmin() {
if (adminVault.admin() != msg.sender){
revert SenderNotAdmin();
}
_;
}
/// @notice withdraw stuck funds
function withdrawStuckFunds(address _token, address _receiver, uint256 _amount) public onlyOwner {
if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {
payable(_receiver).transfer(_amount);
} else {
IERC20(_token).safeTransfer(_receiver, _amount);
}
}
/// @notice Destroy the contract
function kill() public onlyAdmin {
selfdestruct(payable(msg.sender));
}
}
contract DFSRegistry is AdminAuth {
error EntryAlreadyExistsError(bytes4);
error EntryNonExistentError(bytes4);
error EntryNotInChangeError(bytes4);
error ChangeNotReadyError(uint256,uint256);
error EmptyPrevAddrError(bytes4);
error AlreadyInContractChangeError(bytes4);
error AlreadyInWaitPeriodChangeError(bytes4);
event AddNewContract(address,bytes4,address,uint256);
event RevertToPreviousAddress(address,bytes4,address,address);
event StartContractChange(address,bytes4,address,address);
event ApproveContractChange(address,bytes4,address,address);
event CancelContractChange(address,bytes4,address,address);
event StartWaitPeriodChange(address,bytes4,uint256);
event ApproveWaitPeriodChange(address,bytes4,uint256,uint256);
event CancelWaitPeriodChange(address,bytes4,uint256,uint256);
struct Entry {
address contractAddr;
uint256 waitPeriod;
uint256 changeStartTime;
bool inContractChange;
bool inWaitPeriodChange;
bool exists;
}
mapping(bytes4 => Entry) public entries;
mapping(bytes4 => address) public previousAddresses;
mapping(bytes4 => address) public pendingAddresses;
mapping(bytes4 => uint256) public pendingWaitTimes;
/// @notice Given an contract id returns the registered address
/// @dev Id is keccak256 of the contract name
/// @param _id Id of contract
function getAddr(bytes4 _id) public view returns (address) {
return entries[_id].contractAddr;
}
/// @notice Helper function to easily query if id is registered
/// @param _id Id of contract
function isRegistered(bytes4 _id) public view returns (bool) {
return entries[_id].exists;
}
/////////////////////////// OWNER ONLY FUNCTIONS ///////////////////////////
/// @notice Adds a new contract to the registry
/// @param _id Id of contract
/// @param _contractAddr Address of the contract
/// @param _waitPeriod Amount of time to wait before a contract address can be changed
function addNewContract(
bytes4 _id,
address _contractAddr,
uint256 _waitPeriod
) public onlyOwner {
if (entries[_id].exists){
revert EntryAlreadyExistsError(_id);
}
entries[_id] = Entry({
contractAddr: _contractAddr,
waitPeriod: _waitPeriod,
changeStartTime: 0,
inContractChange: false,
inWaitPeriodChange: false,
exists: true
});
emit AddNewContract(msg.sender, _id, _contractAddr, _waitPeriod);
}
/// @notice Reverts to the previous address immediately
/// @dev In case the new version has a fault, a quick way to fallback to the old contract
/// @param _id Id of contract
function revertToPreviousAddress(bytes4 _id) public onlyOwner {
if (!(entries[_id].exists)){
revert EntryNonExistentError(_id);
}
if (previousAddresses[_id] == address(0)){
revert EmptyPrevAddrError(_id);
}
address currentAddr = entries[_id].contractAddr;
entries[_id].contractAddr = previousAddresses[_id];
emit RevertToPreviousAddress(msg.sender, _id, currentAddr, previousAddresses[_id]);
}
/// @notice Starts an address change for an existing entry
/// @dev Can override a change that is currently in progress
/// @param _id Id of contract
/// @param _newContractAddr Address of the new contract
function startContractChange(bytes4 _id, address _newContractAddr) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (entries[_id].inWaitPeriodChange){
revert AlreadyInWaitPeriodChangeError(_id);
}
entries[_id].changeStartTime = block.timestamp; // solhint-disable-line
entries[_id].inContractChange = true;
pendingAddresses[_id] = _newContractAddr;
emit StartContractChange(msg.sender, _id, entries[_id].contractAddr, _newContractAddr);
}
/// @notice Changes new contract address, correct time must have passed
/// @param _id Id of contract
function approveContractChange(bytes4 _id) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (!entries[_id].inContractChange){
revert EntryNotInChangeError(_id);
}
if (block.timestamp < (entries[_id].changeStartTime + entries[_id].waitPeriod)){// solhint-disable-line
revert ChangeNotReadyError(block.timestamp, (entries[_id].changeStartTime + entries[_id].waitPeriod));
}
address oldContractAddr = entries[_id].contractAddr;
entries[_id].contractAddr = pendingAddresses[_id];
entries[_id].inContractChange = false;
entries[_id].changeStartTime = 0;
pendingAddresses[_id] = address(0);
previousAddresses[_id] = oldContractAddr;
emit ApproveContractChange(msg.sender, _id, oldContractAddr, entries[_id].contractAddr);
}
/// @notice Cancel pending change
/// @param _id Id of contract
function cancelContractChange(bytes4 _id) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (!entries[_id].inContractChange){
revert EntryNotInChangeError(_id);
}
address oldContractAddr = pendingAddresses[_id];
pendingAddresses[_id] = address(0);
entries[_id].inContractChange = false;
entries[_id].changeStartTime = 0;
emit CancelContractChange(msg.sender, _id, oldContractAddr, entries[_id].contractAddr);
}
/// @notice Starts the change for waitPeriod
/// @param _id Id of contract
/// @param _newWaitPeriod New wait time
function startWaitPeriodChange(bytes4 _id, uint256 _newWaitPeriod) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (entries[_id].inContractChange){
revert AlreadyInContractChangeError(_id);
}
pendingWaitTimes[_id] = _newWaitPeriod;
entries[_id].changeStartTime = block.timestamp; // solhint-disable-line
entries[_id].inWaitPeriodChange = true;
emit StartWaitPeriodChange(msg.sender, _id, _newWaitPeriod);
}
/// @notice Changes new wait period, correct time must have passed
/// @param _id Id of contract
function approveWaitPeriodChange(bytes4 _id) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (!entries[_id].inWaitPeriodChange){
revert EntryNotInChangeError(_id);
}
if (block.timestamp < (entries[_id].changeStartTime + entries[_id].waitPeriod)){ // solhint-disable-line
revert ChangeNotReadyError(block.timestamp, (entries[_id].changeStartTime + entries[_id].waitPeriod));
}
uint256 oldWaitTime = entries[_id].waitPeriod;
entries[_id].waitPeriod = pendingWaitTimes[_id];
entries[_id].inWaitPeriodChange = false;
entries[_id].changeStartTime = 0;
pendingWaitTimes[_id] = 0;
emit ApproveWaitPeriodChange(msg.sender, _id, oldWaitTime, entries[_id].waitPeriod);
}
/// @notice Cancel wait period change
/// @param _id Id of contract
function cancelWaitPeriodChange(bytes4 _id) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (!entries[_id].inWaitPeriodChange){
revert EntryNotInChangeError(_id);
}
uint256 oldWaitPeriod = pendingWaitTimes[_id];
pendingWaitTimes[_id] = 0;
entries[_id].inWaitPeriodChange = false;
entries[_id].changeStartTime = 0;
emit CancelWaitPeriodChange(msg.sender, _id, oldWaitPeriod, entries[_id].waitPeriod);
}
}
abstract contract DSAuthority {
function canCall(
address src,
address dst,
bytes4 sig
) public view virtual returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority(address indexed authority);
event LogSetOwner(address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
constructor() {
owner = msg.sender;
emit LogSetOwner(msg.sender);
}
function setOwner(address owner_) public auth {
owner = owner_;
emit LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_) public auth {
authority = authority_;
emit LogSetAuthority(address(authority));
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig), "Not authorized");
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(address(0))) {
return false;
} else {
return authority.canCall(src, address(this), sig);
}
}
}
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint256 wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
}
abstract contract DSProxy is DSAuth, DSNote {
DSProxyCache public cache; // global cache for contracts
constructor(address _cacheAddr) {
if (!(setCache(_cacheAddr))){
require(isAuthorized(msg.sender, msg.sig), "Not authorized");
}
}
// solhint-disable-next-line no-empty-blocks
receive() external payable {}
// use the proxy to execute calldata _data on contract _code
function execute(bytes memory _code, bytes memory _data)
public
payable
virtual
returns (address target, bytes32 response);
function execute(address _target, bytes memory _data)
public
payable
virtual
returns (bytes32 response);
//set new cache
function setCache(address _cacheAddr) public payable virtual returns (bool);
}
contract DSProxyCache {
mapping(bytes32 => address) cache;
function read(bytes memory _code) public view returns (address) {
bytes32 hash = keccak256(_code);
return cache[hash];
}
function write(bytes memory _code) public returns (address target) {
assembly {
target := create(0, add(_code, 0x20), mload(_code))
switch iszero(extcodesize(target))
case 1 {
// throw if contract failed to deploy
revert(0, 0)
}
}
bytes32 hash = keccak256(_code);
cache[hash] = target;
}
}
contract DefisaverLogger {
event RecipeEvent(
address indexed caller,
string indexed logName
);
event ActionDirectEvent(
address indexed caller,
string indexed logName,
bytes data
);
function logRecipeEvent(
string memory _logName
) public {
emit RecipeEvent(msg.sender, _logName);
}
function logActionDirectEvent(
string memory _logName,
bytes memory _data
) public {
emit ActionDirectEvent(msg.sender, _logName, _data);
}
}
contract MainnetActionsUtilAddresses {
address internal constant DFS_REG_CONTROLLER_ADDR = 0xF8f8B3C98Cf2E63Df3041b73f80F362a4cf3A576;
address internal constant REGISTRY_ADDR = 0x287778F121F134C66212FB16c9b53eC991D32f5b;
address internal constant DFS_LOGGER_ADDR = 0xcE7a977Cac4a481bc84AC06b2Da0df614e621cf3;
address internal constant SUB_STORAGE_ADDR = 0x1612fc28Ee0AB882eC99842Cde0Fc77ff0691e90;
address internal constant PROXY_AUTH_ADDR = 0x149667b6FAe2c63D1B4317C716b0D0e4d3E2bD70;
}
contract ActionsUtilHelper is MainnetActionsUtilAddresses {
}
abstract contract ActionBase is AdminAuth, ActionsUtilHelper {
event ActionEvent(
string indexed logName,
bytes data
);
DFSRegistry public constant registry = DFSRegistry(REGISTRY_ADDR);
DefisaverLogger public constant logger = DefisaverLogger(
DFS_LOGGER_ADDR
);
//Wrong sub index value
error SubIndexValueError();
//Wrong return index value
error ReturnIndexValueError();
/// @dev Subscription params index range [128, 255]
uint8 public constant SUB_MIN_INDEX_VALUE = 128;
uint8 public constant SUB_MAX_INDEX_VALUE = 255;
/// @dev Return params index range [1, 127]
uint8 public constant RETURN_MIN_INDEX_VALUE = 1;
uint8 public constant RETURN_MAX_INDEX_VALUE = 127;
/// @dev If the input value should not be replaced
uint8 public constant NO_PARAM_MAPPING = 0;
/// @dev We need to parse Flash loan actions in a different way
enum ActionType { FL_ACTION, STANDARD_ACTION, FEE_ACTION, CHECK_ACTION, CUSTOM_ACTION }
/// @notice Parses inputs and runs the implemented action through a proxy
/// @dev Is called by the RecipeExecutor chaining actions together
/// @param _callData Array of input values each value encoded as bytes
/// @param _subData Array of subscribed vales, replaces input values if specified
/// @param _paramMapping Array that specifies how return and subscribed values are mapped in input
/// @param _returnValues Returns values from actions before, which can be injected in inputs
/// @return Returns a bytes32 value through DSProxy, each actions implements what that value is
function executeAction(
bytes memory _callData,
bytes32[] memory _subData,
uint8[] memory _paramMapping,
bytes32[] memory _returnValues
) public payable virtual returns (bytes32);
/// @notice Parses inputs and runs the single implemented action through a proxy
/// @dev Used to save gas when executing a single action directly
function executeActionDirect(bytes memory _callData) public virtual payable;
/// @notice Returns the type of action we are implementing
function actionType() public pure virtual returns (uint8);
//////////////////////////// HELPER METHODS ////////////////////////////
/// @notice Given an uint256 input, injects return/sub values if specified
/// @param _param The original input value
/// @param _mapType Indicated the type of the input in paramMapping
/// @param _subData Array of subscription data we can replace the input value with
/// @param _returnValues Array of subscription data we can replace the input value with
function _parseParamUint(
uint _param,
uint8 _mapType,
bytes32[] memory _subData,
bytes32[] memory _returnValues
) internal pure returns (uint) {
if (isReplaceable(_mapType)) {
if (isReturnInjection(_mapType)) {
_param = uint(_returnValues[getReturnIndex(_mapType)]);
} else {
_param = uint256(_subData[getSubIndex(_mapType)]);
}
}
return _param;
}
/// @notice Given an addr input, injects return/sub values if specified
/// @param _param The original input value
/// @param _mapType Indicated the type of the input in paramMapping
/// @param _subData Array of subscription data we can replace the input value with
/// @param _returnValues Array of subscription data we can replace the input value with
function _parseParamAddr(
address _param,
uint8 _mapType,
bytes32[] memory _subData,
bytes32[] memory _returnValues
) internal view returns (address) {
if (isReplaceable(_mapType)) {
if (isReturnInjection(_mapType)) {
_param = address(bytes20((_returnValues[getReturnIndex(_mapType)])));
} else {
/// @dev The last two values are specially reserved for proxy addr and owner addr
if (_mapType == 254) return address(this); //DSProxy address
if (_mapType == 255) return DSProxy(payable(address(this))).owner(); // owner of DSProxy
_param = address(uint160(uint256(_subData[getSubIndex(_mapType)])));
}
}
return _param;
}
/// @notice Given an bytes32 input, injects return/sub values if specified
/// @param _param The original input value
/// @param _mapType Indicated the type of the input in paramMapping
/// @param _subData Array of subscription data we can replace the input value with
/// @param _returnValues Array of subscription data we can replace the input value with
function _parseParamABytes32(
bytes32 _param,
uint8 _mapType,
bytes32[] memory _subData,
bytes32[] memory _returnValues
) internal pure returns (bytes32) {
if (isReplaceable(_mapType)) {
if (isReturnInjection(_mapType)) {
_param = (_returnValues[getReturnIndex(_mapType)]);
} else {
_param = _subData[getSubIndex(_mapType)];
}
}
return _param;
}
/// @notice Checks if the paramMapping value indicated that we need to inject values
/// @param _type Indicated the type of the input
function isReplaceable(uint8 _type) internal pure returns (bool) {
return _type != NO_PARAM_MAPPING;
}
/// @notice Checks if the paramMapping value is in the return value range
/// @param _type Indicated the type of the input
function isReturnInjection(uint8 _type) internal pure returns (bool) {
return (_type >= RETURN_MIN_INDEX_VALUE) && (_type <= RETURN_MAX_INDEX_VALUE);
}
/// @notice Transforms the paramMapping value to the index in return array value
/// @param _type Indicated the type of the input
function getReturnIndex(uint8 _type) internal pure returns (uint8) {
if (!(isReturnInjection(_type))){
revert SubIndexValueError();
}
return (_type - RETURN_MIN_INDEX_VALUE);
}
/// @notice Transforms the paramMapping value to the index in sub array value
/// @param _type Indicated the type of the input
function getSubIndex(uint8 _type) internal pure returns (uint8) {
if (_type < SUB_MIN_INDEX_VALUE){
revert ReturnIndexValueError();
}
return (_type - SUB_MIN_INDEX_VALUE);
}
}
library TokenUtils {
using SafeERC20 for IERC20;
address public constant WETH_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address public constant ETH_ADDR = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
function approveToken(
address _tokenAddr,
address _to,
uint256 _amount
) internal {
if (_tokenAddr == ETH_ADDR) return;
if (IERC20(_tokenAddr).allowance(address(this), _to) < _amount) {
IERC20(_tokenAddr).safeApprove(_to, _amount);
}
}
function pullTokensIfNeeded(
address _token,
address _from,
uint256 _amount
) internal returns (uint256) {
// handle max uint amount
if (_amount == type(uint256).max) {
_amount = getBalance(_token, _from);
}
if (_from != address(0) && _from != address(this) && _token != ETH_ADDR && _amount != 0) {
IERC20(_token).safeTransferFrom(_from, address(this), _amount);
}
return _amount;
}
function withdrawTokens(
address _token,
address _to,
uint256 _amount
) internal returns (uint256) {
if (_amount == type(uint256).max) {
_amount = getBalance(_token, address(this));
}
if (_to != address(0) && _to != address(this) && _amount != 0) {
if (_token != ETH_ADDR) {
IERC20(_token).safeTransfer(_to, _amount);
} else {
(bool success, ) = _to.call{value: _amount}("");
require(success, "Eth send fail");
}
}
return _amount;
}
function depositWeth(uint256 _amount) internal {
IWETH(WETH_ADDR).deposit{value: _amount}();
}
function withdrawWeth(uint256 _amount) internal {
IWETH(WETH_ADDR).withdraw(_amount);
}
function getBalance(address _tokenAddr, address _acc) internal view returns (uint256) {
if (_tokenAddr == ETH_ADDR) {
return _acc.balance;
} else {
return IERC20(_tokenAddr).balanceOf(_acc);
}
}
function getTokenDecimals(address _token) internal view returns (uint256) {
if (_token == ETH_ADDR) return 18;
return IERC20(_token).decimals();
}
}
interface IPoolAddressesProvider {
/**
* @dev Emitted when the market identifier is updated.
* @param oldMarketId The old id of the market
* @param newMarketId The new id of the market
*/
event MarketIdSet(string indexed oldMarketId, string indexed newMarketId);
/**
* @dev Emitted when the pool is updated.
* @param oldAddress The old address of the Pool
* @param newAddress The new address of the Pool
*/
event PoolUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the pool configurator is updated.
* @param oldAddress The old address of the PoolConfigurator
* @param newAddress The new address of the PoolConfigurator
*/
event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the price oracle is updated.
* @param oldAddress The old address of the PriceOracle
* @param newAddress The new address of the PriceOracle
*/
event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL manager is updated.
* @param oldAddress The old address of the ACLManager
* @param newAddress The new address of the ACLManager
*/
event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL admin is updated.
* @param oldAddress The old address of the ACLAdmin
* @param newAddress The new address of the ACLAdmin
*/
event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the price oracle sentinel is updated.
* @param oldAddress The old address of the PriceOracleSentinel
* @param newAddress The new address of the PriceOracleSentinel
*/
event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the pool data provider is updated.
* @param oldAddress The old address of the PoolDataProvider
* @param newAddress The new address of the PoolDataProvider
*/
event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when a new proxy is created.
* @param id The identifier of the proxy
* @param proxyAddress The address of the created proxy contract
* @param implementationAddress The address of the implementation contract
*/
event ProxyCreated(
bytes32 indexed id,
address indexed proxyAddress,
address indexed implementationAddress
);
/**
* @dev Emitted when a new non-proxied contract address is registered.
* @param id The identifier of the contract
* @param oldAddress The address of the old contract
* @param newAddress The address of the new contract
*/
event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the implementation of the proxy registered with id is updated
* @param id The identifier of the contract
* @param proxyAddress The address of the proxy contract
* @param oldImplementationAddress The address of the old implementation contract
* @param newImplementationAddress The address of the new implementation contract
*/
event AddressSetAsProxy(
bytes32 indexed id,
address indexed proxyAddress,
address oldImplementationAddress,
address indexed newImplementationAddress
);
/**
* @notice Returns the id of the Aave market to which this contract points to.
* @return The market id
**/
function getMarketId() external view returns (string memory);
/**
* @notice Associates an id with a specific PoolAddressesProvider.
* @dev This can be used to create an onchain registry of PoolAddressesProviders to
* identify and validate multiple Aave markets.
* @param newMarketId The market id
*/
function setMarketId(string calldata newMarketId) external;
/**
* @notice Returns an address by its identifier.
* @dev The returned address might be an EOA or a contract, potentially proxied
* @dev It returns ZERO if there is no registered address with the given id
* @param id The id
* @return The address of the registered for the specified id
*/
function getAddress(bytes32 id) external view returns (address);
/**
* @notice General function to update the implementation of a proxy registered with
* certain `id`. If there is no proxy registered, it will instantiate one and
* set as implementation the `newImplementationAddress`.
* @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit
* setter function, in order to avoid unexpected consequences
* @param id The id
* @param newImplementationAddress The address of the new implementation
*/
function setAddressAsProxy(bytes32 id, address newImplementationAddress) external;
/**
* @notice Sets an address for an id replacing the address saved in the addresses map.
* @dev IMPORTANT Use this function carefully, as it will do a hard replacement
* @param id The id
* @param newAddress The address to set
*/
function setAddress(bytes32 id, address newAddress) external;
/**
* @notice Returns the address of the Pool proxy.
* @return The Pool proxy address
**/
function getPool() external view returns (address);
/**
* @notice Updates the implementation of the Pool, or creates a proxy
* setting the new `pool` implementation when the function is called for the first time.
* @param newPoolImpl The new Pool implementation
**/
function setPoolImpl(address newPoolImpl) external;
/**
* @notice Returns the address of the PoolConfigurator proxy.
* @return The PoolConfigurator proxy address
**/
function getPoolConfigurator() external view returns (address);
/**
* @notice Updates the implementation of the PoolConfigurator, or creates a proxy
* setting the new `PoolConfigurator` implementation when the function is called for the first time.
* @param newPoolConfiguratorImpl The new PoolConfigurator implementation
**/
function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external;
/**
* @notice Returns the address of the price oracle.
* @return The address of the PriceOracle
*/
function getPriceOracle() external view returns (address);
/**
* @notice Updates the address of the price oracle.
* @param newPriceOracle The address of the new PriceOracle
*/
function setPriceOracle(address newPriceOracle) external;
/**
* @notice Returns the address of the ACL manager.
* @return The address of the ACLManager
*/
function getACLManager() external view returns (address);
/**
* @notice Updates the address of the ACL manager.
* @param newAclManager The address of the new ACLManager
**/
function setACLManager(address newAclManager) external;
/**
* @notice Returns the address of the ACL admin.
* @return The address of the ACL admin
*/
function getACLAdmin() external view returns (address);
/**
* @notice Updates the address of the ACL admin.
* @param newAclAdmin The address of the new ACL admin
*/
function setACLAdmin(address newAclAdmin) external;
/**
* @notice Returns the address of the price oracle sentinel.
* @return The address of the PriceOracleSentinel
*/
function getPriceOracleSentinel() external view returns (address);
/**
* @notice Updates the address of the price oracle sentinel.
* @param newPriceOracleSentinel The address of the new PriceOracleSentinel
**/
function setPriceOracleSentinel(address newPriceOracleSentinel) external;
/**
* @notice Returns the address of the data provider.
* @return The address of the DataProvider
*/
function getPoolDataProvider() external view returns (address);
/**
* @notice Updates the address of the data provider.
* @param newDataProvider The address of the new DataProvider
**/
function setPoolDataProvider(address newDataProvider) external;
}
library DataTypes {
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
//the current stable borrow rate. Expressed in ray
uint128 currentStableBorrowRate;
//timestamp of last update
uint40 lastUpdateTimestamp;
//the id of the reserve. Represents the position in the list of the active reserves
uint16 id;
//aToken address
address aTokenAddress;
//stableDebtToken address
address stableDebtTokenAddress;
//variableDebtToken address
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the current treasury balance, scaled
uint128 accruedToTreasury;
//the outstanding unbacked aTokens minted through the bridging feature
uint128 unbacked;
//the outstanding debt borrowed against this asset in isolation mode
uint128 isolationModeTotalDebt;
}
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: asset is paused
//bit 61: borrowing in isolation mode is enabled
//bit 62-63: reserved
//bit 64-79: reserve factor
//bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap
//bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap
//bit 152-167 liquidation protocol fee
//bit 168-175 eMode category
//bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled
//bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals
//bit 252-255 unused
uint256 data;
}
struct UserConfigurationMap {
/**
* @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset.
* The first bit indicates if an asset is used as collateral by the user, the second whether an
* asset is borrowed by the user.
*/
uint256 data;
}
struct EModeCategory {
// each eMode category has a custom ltv and liquidation threshold
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
// each eMode category may or may not have a custom oracle to override the individual assets price oracles
address priceSource;
string label;
}
enum InterestRateMode {
NONE,
STABLE,
VARIABLE
}
struct ReserveCache {
uint256 currScaledVariableDebt;
uint256 nextScaledVariableDebt;
uint256 currPrincipalStableDebt;
uint256 currAvgStableBorrowRate;
uint256 currTotalStableDebt;
uint256 nextAvgStableBorrowRate;
uint256 nextTotalStableDebt;
uint256 currLiquidityIndex;
uint256 nextLiquidityIndex;
uint256 currVariableBorrowIndex;
uint256 nextVariableBorrowIndex;
uint256 currLiquidityRate;
uint256 currVariableBorrowRate;
uint256 reserveFactor;
ReserveConfigurationMap reserveConfiguration;
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
uint40 reserveLastUpdateTimestamp;
uint40 stableDebtLastUpdateTimestamp;
}
struct ExecuteLiquidationCallParams {
uint256 reservesCount;
uint256 debtToCover;
address collateralAsset;
address debtAsset;
address user;
bool receiveAToken;
address priceOracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ExecuteSupplyParams {
address asset;
uint256 amount;
address onBehalfOf;
uint16 referralCode;
}
struct ExecuteBorrowParams {
address asset;
address user;
address onBehalfOf;
uint256 amount;
InterestRateMode interestRateMode;
uint16 referralCode;
bool releaseUnderlying;
uint256 maxStableRateBorrowSizePercent;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ExecuteRepayParams {
address asset;
uint256 amount;
InterestRateMode interestRateMode;
address onBehalfOf;
bool useATokens;
}
struct ExecuteWithdrawParams {
address asset;
uint256 amount;
address to;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
}
struct ExecuteSetUserEModeParams {
uint256 reservesCount;
address oracle;
uint8 categoryId;
}
struct FinalizeTransferParams {
address asset;
address from;
address to;
uint256 amount;
uint256 balanceFromBefore;
uint256 balanceToBefore;
uint256 reservesCount;
address oracle;
uint8 fromEModeCategory;
}
struct FlashloanParams {
address receiverAddress;
address[] assets;
uint256[] amounts;
uint256[] interestRateModes;
address onBehalfOf;
bytes params;
uint16 referralCode;
uint256 flashLoanPremiumToProtocol;
uint256 flashLoanPremiumTotal;
uint256 maxStableRateBorrowSizePercent;
uint256 reservesCount;
address addressesProvider;
uint8 userEModeCategory;
bool isAuthorizedFlashBorrower;
}
struct FlashloanSimpleParams {
address receiverAddress;
address asset;
uint256 amount;
bytes params;
uint16 referralCode;
uint256 flashLoanPremiumToProtocol;
uint256 flashLoanPremiumTotal;
}
struct FlashLoanRepaymentParams {
uint256 amount;
uint256 totalPremium;
uint256 flashLoanPremiumToProtocol;
address asset;
address receiverAddress;
uint16 referralCode;
}
struct CalculateUserAccountDataParams {
UserConfigurationMap userConfig;
uint256 reservesCount;
address user;
address oracle;
uint8 userEModeCategory;
}
struct ValidateBorrowParams {
ReserveCache reserveCache;
UserConfigurationMap userConfig;
address asset;
address userAddress;
uint256 amount;
InterestRateMode interestRateMode;
uint256 maxStableLoanPercent;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
bool isolationModeActive;
address isolationModeCollateralAddress;
uint256 isolationModeDebtCeiling;
}
struct ValidateLiquidationCallParams {
ReserveCache debtReserveCache;
uint256 totalDebt;
uint256 healthFactor;
address priceOracleSentinel;
}
struct CalculateInterestRatesParams {
uint256 unbacked;
uint256 liquidityAdded;
uint256 liquidityTaken;
uint256 totalStableDebt;
uint256 totalVariableDebt;
uint256 averageStableBorrowRate;
uint256 reserveFactor;
address reserve;
address aToken;
}
struct InitReserveParams {
address asset;
address aTokenAddress;
address stableDebtAddress;
address variableDebtAddress;
address interestRateStrategyAddress;
uint16 reservesCount;
uint16 maxNumberReserves;
}
}
interface IPoolV3 {
/**
* @dev Emitted on mintUnbacked()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the supply
* @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens
* @param amount The amount of supplied assets
* @param referralCode The referral code used
**/
event MintUnbacked(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referralCode
);
/**
* @dev Emitted on backUnbacked()
* @param reserve The address of the underlying asset of the reserve
* @param backer The address paying for the backing
* @param amount The amount added as backing
* @param fee The amount paid in fees
**/
event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee);
/**
* @dev Emitted on supply()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the supply
* @param onBehalfOf The beneficiary of the supply, receiving the aTokens
* @param amount The amount supplied
* @param referralCode The referral code used
**/
event Supply(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referralCode
);
/**
* @dev Emitted on withdraw()
* @param reserve The address of the underlying asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to The 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 interestRateMode The rate mode: 1 for Stable, 2 for Variable
* @param borrowRate The numeric rate at which the user has borrowed, expressed in ray
* @param referralCode The referral code used
**/
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
DataTypes.InterestRateMode interestRateMode,
uint256 borrowRate,
uint16 indexed referralCode
);
/**
* @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
* @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly
**/
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount,
bool useATokens
);
/**
* @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 interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable
**/
event SwapBorrowRateMode(
address indexed reserve,
address indexed user,
DataTypes.InterestRateMode interestRateMode
);
/**
* @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets
* @param asset The address of the underlying asset of the reserve
* @param totalDebt The total isolation mode debt for the reserve
*/
event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt);
/**
* @dev Emitted when the user selects a certain asset category for eMode
* @param user The address of the user
* @param categoryId The category id
**/
event UserEModeSet(address indexed user, uint8 categoryId);
/**
* @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 interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt
* @param premium The fee flash borrowed
* @param referralCode The referral code used
**/
event FlashLoan(
address indexed target,
address initiator,
address indexed asset,
uint256 amount,
DataTypes.InterestRateMode interestRateMode,
uint256 premium,
uint16 indexed referralCode
);
/**
* @dev Emitted when a borrower is liquidated.
* @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 liquidator
* @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.
* @param reserve The address of the underlying asset of the reserve
* @param liquidityRate The next liquidity rate
* @param stableBorrowRate The next stable borrow rate
* @param variableBorrowRate The next variable borrow rate
* @param liquidityIndex The next liquidity index
* @param variableBorrowIndex The next variable borrow index
**/
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 stableBorrowRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
/**
* @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest.
* @param reserve The address of the reserve
* @param amountMinted The amount minted to the treasury
**/
event MintedToTreasury(address indexed reserve, uint256 amountMinted);
/**
* @dev Mints an `amount` of aTokens to the `onBehalfOf`
* @param asset The address of the underlying asset to mint
* @param amount The amount to mint
* @param onBehalfOf The address that will receive the aTokens
* @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 mintUnbacked(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @dev Back the current unbacked underlying with `amount` and pay `fee`.
* @param asset The address of the underlying asset to back
* @param amount The amount to back
* @param fee The amount paid in fees
**/
function backUnbacked(
address asset,
uint256 amount,
uint256 fee
) external;
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @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 supply(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @notice Supply with transfer approval of asset to be supplied done via permit function
* see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @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 deadline The deadline timestamp that the permit is valid
* @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 permitV The V parameter of ERC712 permit sig
* @param permitR The R parameter of ERC712 permit sig
* @param permitS The S parameter of ERC712 permit sig
**/
function supplyWithPermit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external;
/**
* @notice 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 The 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);
/**
* @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already supplied 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 The 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 The 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 interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf The 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 interestRateMode,
address onBehalfOf
) external returns (uint256);
/**
* @notice Repay with transfer approval of asset to be repaid done via permit function
* see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
* @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 interestRateMode 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
* @param deadline The deadline timestamp that the permit is valid
* @param permitV The V parameter of ERC712 permit sig
* @param permitR The R parameter of ERC712 permit sig
* @param permitS The S parameter of ERC712 permit sig
* @return The final amount repaid
**/
function repayWithPermit(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external returns (uint256);
/**
* @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the
* equivalent debt tokens
* - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens
* @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken
* balance is not enough to cover the whole debt
* @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 interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @return The final amount repaid
**/
function repayWithATokens(
address asset,
uint256 amount,
uint256 interestRateMode
) external returns (uint256);
/**
* @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa
* @param asset The address of the underlying asset borrowed
* @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable
**/
function swapBorrowRateMode(address asset, uint256 interestRateMode) external;
/**
* @notice 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 supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too
* much has been borrowed at a stable rate and suppliers 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;
/**
* @notice Allows suppliers to enable/disable a specific supplied asset as collateral
* @param asset The address of the underlying asset supplied
* @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise
**/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
/**
* @notice 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;
/**
* @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* @dev 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 IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts of the assets being flash-borrowed
* @param interestRateModes 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 The 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 interestRateModes,
address onBehalfOf,
bytes calldata params,
uint16 referralCode
) external;
/**
* @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* @dev 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 IFlashLoanSimpleReceiver interface
* @param asset The address of the asset being flash-borrowed
* @param amount The amount of the asset being flash-borrowed
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode The 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 flashLoanSimple(
address receiverAddress,
address asset,
uint256 amount,
bytes calldata params,
uint16 referralCode
) external;
/**
* @notice Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralBase The total collateral of the user in the base currency used by the price feed
* @return totalDebtBase The total debt of the user in the base currency used by the price feed
* @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed
* @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 totalCollateralBase,
uint256 totalDebtBase,
uint256 availableBorrowsBase,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
/**
* @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an
* interest rate strategy
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param aTokenAddress The address of the aToken that will be assigned to the reserve
* @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve
* @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve
* @param interestRateStrategyAddress The address of the interest rate strategy contract
**/
function initReserve(
address asset,
address aTokenAddress,
address stableDebtAddress,
address variableDebtAddress,
address interestRateStrategyAddress
) external;
/**
* @notice Drop a reserve
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
**/
function dropReserve(address asset) external;
/**
* @notice Updates the address of the interest rate strategy contract
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param rateStrategyAddress The address of the interest rate strategy contract
**/
function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress)
external;
/**
* @notice Sets the configuration bitmap of the reserve as a whole
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param configuration The new configuration bitmap
**/
function setConfiguration(address asset, DataTypes.ReserveConfigurationMap calldata configuration)
external;
/**
* @notice 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);
/**
* @notice 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);
/**
* @notice 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);
/**
* @notice 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);
/**
* @notice Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state and configuration data of the reserve
**/
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
/**
* @notice Validates and finalizes an aToken transfer
* @dev Only callable by the overlying aToken of the `asset`
* @param asset The address of the underlying asset of the aToken
* @param from The user from which the aTokens are transferred
* @param to The user receiving the aTokens
* @param amount The amount being transferred/withdrawn
* @param balanceFromBefore The aToken balance of the `from` user before the transfer
* @param balanceToBefore The aToken balance of the `to` user before the transfer
*/
function finalizeTransfer(
address asset,
address from,
address to,
uint256 amount,
uint256 balanceFromBefore,
uint256 balanceToBefore
) external;
/**
* @notice Returns the list of the initialized reserves
* @dev It does not include dropped reserves
* @return The addresses of the reserves
**/
function getReservesList() external view returns (address[] memory);
/**
* @notice Returns the PoolAddressesProvider connected to this contract
* @return The address of the PoolAddressesProvider
**/
function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
/**
* @notice Updates the protocol fee on the bridging
* @param bridgeProtocolFee The part of the premium sent to the protocol treasury
*/
function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external;
/**
* @notice Updates flash loan premiums. Flash loan premium consists of two parts:
* - A part is sent to aToken holders as extra, one time accumulated interest
* - A part is collected by the protocol treasury
* @dev The total premium is calculated on the total borrowed amount
* @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal`
* @dev Only callable by the PoolConfigurator contract
* @param flashLoanPremiumTotal The total premium, expressed in bps
* @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps
*/
function updateFlashloanPremiums(
uint128 flashLoanPremiumTotal,
uint128 flashLoanPremiumToProtocol
) external;
/**
* @notice Configures a new category for the eMode.
* @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category.
* The category 0 is reserved as it's the default for volatile assets
* @param id The id of the category
* @param config The configuration of the category
*/
function configureEModeCategory(uint8 id, DataTypes.EModeCategory memory config) external;
/**
* @notice Returns the data of an eMode category
* @param id The id of the category
* @return The configuration data of the category
*/
function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory);
/**
* @notice Allows a user to use the protocol in eMode
* @param categoryId The id of the category
*/
function setUserEMode(uint8 categoryId) external;
/**
* @notice Returns the eMode the user is using
* @param user The address of the user
* @return The eMode id
*/
function getUserEMode(address user) external view returns (uint256);
/**
* @notice Resets the isolation mode total debt of the given asset to zero
* @dev It requires the given asset has zero debt ceiling
* @param asset The address of the underlying asset to reset the isolationModeTotalDebt
*/
function resetIsolationModeTotalDebt(address asset) external;
/**
* @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate
* @return The percentage of available liquidity to borrow, expressed in bps
*/
function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() external view returns (uint256);
/**
* @notice Returns the total fee on flash loans
* @return The total fee on flashloans
*/
function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128);
/**
* @notice Returns the part of the bridge fees sent to protocol
* @return The bridge fee sent to the protocol treasury
*/
function BRIDGE_PROTOCOL_FEE() external view returns (uint256);
/**
* @notice Returns the part of the flashloan fees sent to protocol
* @return The flashloan fee sent to the protocol treasury
*/
function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128);
/**
* @notice Returns the maximum number of reserves supported to be listed in this Pool
* @return The maximum number of reserves supported
*/
function MAX_NUMBER_RESERVES() external view returns (uint16);
/**
* @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens
* @param assets The list of reserves for which the minting needs to be executed
**/
function mintToTreasury(address[] calldata assets) external;
/**
* @notice Rescue and transfer tokens locked in this contract
* @param token The address of the token
* @param to The address of the recipient
* @param amount The amount of token to transfer
*/
function rescueTokens(
address token,
address to,
uint256 amount
) external;
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @dev Deprecated: Use the `supply` function instead
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @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;
/**
* @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct
* @param id The id of the reserve as stored in the DataTypes.ReserveData struct
* @return The address of the reserve associated with id
**/
function getReserveAddressById(uint16 id) external view returns (address);
}
interface IL2PoolV3 is IPoolV3{
/**
* @notice Calldata efficient wrapper of the supply function on behalf of the caller
* @param args Arguments for the supply function packed in one bytes32
* 96 bits 16 bits 128 bits 16 bits
* | 0-padding | referralCode | shortenedAmount | assetId |
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
*/
function supply(bytes32 args) external;
/**
* @notice Calldata efficient wrapper of the supplyWithPermit function on behalf of the caller
* @param args Arguments for the supply function packed in one bytes32
* 56 bits 8 bits 32 bits 16 bits 128 bits 16 bits
* | 0-padding | permitV | shortenedDeadline | referralCode | shortenedAmount | assetId |
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
* @param r The R parameter of ERC712 permit sig
* @param s The S parameter of ERC712 permit sig
*/
function supplyWithPermit(
bytes32 args,
bytes32 r,
bytes32 s
) external;
/**
* @notice Calldata efficient wrapper of the withdraw function, withdrawing to the caller
* @param args Arguments for the withdraw function packed in one bytes32
* 112 bits 128 bits 16 bits
* | 0-padding | shortenedAmount | assetId |
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
*/
function withdraw(bytes32 args) external;
/**
* @notice Calldata efficient wrapper of the borrow function, borrowing on behalf of the caller
* @param args Arguments for the borrow function packed in one bytes32
* 88 bits 16 bits 8 bits 128 bits 16 bits
* | 0-padding | referralCode | shortenedInterestRateMode | shortenedAmount | assetId |
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
*/
function borrow(bytes32 args) external;
/**
* @notice Calldata efficient wrapper of the repay function, repaying on behalf of the caller
* @param args Arguments for the repay function packed in one bytes32
* 104 bits 8 bits 128 bits 16 bits
* | 0-padding | shortenedInterestRateMode | shortenedAmount | assetId |
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
* @return The final amount repaid
*/
function repay(bytes32 args) external returns (uint256);
/**
* @notice Calldata efficient wrapper of the repayWithPermit function, repaying on behalf of the caller
* @param args Arguments for the repayWithPermit function packed in one bytes32
* 64 bits 8 bits 32 bits 8 bits 128 bits 16 bits
* | 0-padding | permitV | shortenedDeadline | shortenedInterestRateMode | shortenedAmount | assetId |
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
* @param r The R parameter of ERC712 permit sig
* @param s The S parameter of ERC712 permit sig
* @return The final amount repaid
*/
function repayWithPermit(
bytes32 args,
bytes32 r,
bytes32 s
) external returns (uint256);
/**
* @notice Calldata efficient wrapper of the repayWithATokens function
* @param args Arguments for the repayWithATokens function packed in one bytes32
* 104 bits 8 bits 128 bits 16 bits
* | 0-padding | shortenedInterestRateMode | shortenedAmount | assetId |
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
* @return The final amount repaid
*/
function repayWithATokens(bytes32 args) external returns (uint256);
/**
* @notice Calldata efficient wrapper of the swapBorrowRateMode function
* @param args Arguments for the swapBorrowRateMode function packed in one bytes32
* 232 bits 8 bits 16 bits
* | 0-padding | shortenedInterestRateMode | assetId |
* @dev assetId is the index of the asset in the reservesList.
*/
function swapBorrowRateMode(bytes32 args) external;
/**
* @notice Calldata efficient wrapper of the rebalanceStableBorrowRate function
* @param args Arguments for the rebalanceStableBorrowRate function packed in one bytes32
* 80 bits 160 bits 16 bits
* | 0-padding | user address | assetId |
* @dev assetId is the index of the asset in the reservesList.
*/
function rebalanceStableBorrowRate(bytes32 args) external;
/**
* @notice Calldata efficient wrapper of the setUserUseReserveAsCollateral function
* @param args Arguments for the setUserUseReserveAsCollateral function packed in one bytes32
* 239 bits 1 bit 16 bits
* | 0-padding | useAsCollateral | assetId |
* @dev assetId is the index of the asset in the reservesList.
*/
function setUserUseReserveAsCollateral(bytes32 args) external;
/**
* @notice Calldata efficient wrapper of the liquidationCall function
* @param args1 part of the arguments for the liquidationCall function packed in one bytes32
* 64 bits 160 bits 16 bits 16 bits
* | 0-padding | user address | debtAssetId | collateralAssetId |
* @param args2 part of the arguments for the liquidationCall function packed in one bytes32
* 127 bits 1 bit 128 bits
* | 0-padding | receiveAToken | shortenedDebtToCover |
* @dev the shortenedDebtToCover is cast to 256 bits at decode time,
* if type(uint128).max the value will be expanded to type(uint256).max
*/
function liquidationCall(bytes32 args1, bytes32 args2) external;
}
interface IAaveProtocolDataProvider {
/**
* @notice Returns the user data in a reserve
* @param asset The address of the underlying asset of the reserve
* @param user The address of the user
* @return currentATokenBalance The current AToken balance of the user
* @return currentStableDebt The current stable debt of the user
* @return currentVariableDebt The current variable debt of the user
* @return principalStableDebt The principal stable debt of the user
* @return scaledVariableDebt The scaled variable debt of the user
* @return stableBorrowRate The stable borrow rate of the user
* @return liquidityRate The liquidity rate of the reserve
* @return stableRateLastUpdated The timestamp of the last update of the user stable rate
* @return usageAsCollateralEnabled True if the user is using the asset as collateral, false
* otherwise
**/
function getUserReserveData(address asset, address user)
external
view
returns (
uint256 currentATokenBalance,
uint256 currentStableDebt,
uint256 currentVariableDebt,
uint256 principalStableDebt,
uint256 scaledVariableDebt,
uint256 stableBorrowRate,
uint256 liquidityRate,
uint40 stableRateLastUpdated,
bool usageAsCollateralEnabled
);
function getSiloedBorrowing(address asset) external view returns (bool);
}
contract MainnetAaveV3Addresses {
address internal constant REWARDS_CONTROLLER_ADDRESS = 0x8164Cc65827dcFe994AB23944CBC90e0aa80bFcb;
address internal constant DEFAULT_AAVE_MARKET = 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e;
address internal constant AAVE_ORACLE_V3 = 0x54586bE62E3c3580375aE3723C145253060Ca0C2;
// Not used in the current implementation
address internal constant TRANSIENT_STORAGE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
}
contract AaveV3Helper is MainnetAaveV3Addresses {
uint16 public constant AAVE_REFERRAL_CODE = 64;
uint256 public constant STABLE_ID = 1;
uint256 public constant VARIABLE_ID = 2;
/// @notice Returns the lending pool contract of the specified market
function getLendingPool(address _market) internal view returns (IL2PoolV3) {
return IL2PoolV3(IPoolAddressesProvider(_market).getPool());
}
/// @notice Fetch the data provider for the specified market
function getDataProvider(address _market) internal view returns (IAaveProtocolDataProvider) {
return
IAaveProtocolDataProvider(
IPoolAddressesProvider(_market).getPoolDataProvider()
);
}
function boolToBytes(bool x) internal pure returns (bytes1 r) {
return x ? bytes1(0x01) : bytes1(0x00);
}
function bytesToBool(bytes1 x) internal pure returns (bool r) {
return x != bytes1(0x00);
}
function getWholeDebt(address _market, address _tokenAddr, uint _borrowType, address _debtOwner) internal view returns (uint256 debt) {
IAaveProtocolDataProvider dataProvider = getDataProvider(_market);
(, uint256 borrowsStable, uint256 borrowsVariable, , , , , , ) =
dataProvider.getUserReserveData(_tokenAddr, _debtOwner);
if (_borrowType == STABLE_ID) {
debt = borrowsStable;
} else if (_borrowType == VARIABLE_ID) {
debt = borrowsVariable;
}
}
}
contract AaveV3Withdraw is ActionBase, AaveV3Helper {
using TokenUtils for address;
struct Params {
uint16 assetId;
bool useDefaultMarket;
uint256 amount;
address to;
address market;
}
/// @inheritdoc ActionBase
function executeAction(
bytes calldata callData,
bytes32[] memory _subData,
uint8[] memory _paramMapping,
bytes32[] memory _returnValues
) public payable virtual override returns (bytes32) {
Params memory params = parseInputs(callData);
params.assetId = uint16(_parseParamUint(uint16(params.assetId), _paramMapping[0], _subData, _returnValues));
params.useDefaultMarket = _parseParamUint(params.useDefaultMarket ? 1 : 0, _paramMapping[1], _subData, _returnValues) == 1;
params.amount = _parseParamUint(params.amount, _paramMapping[2], _subData, _returnValues);
params.to = _parseParamAddr(params.to, _paramMapping[3], _subData, _returnValues);
params.market = _parseParamAddr(params.market, _paramMapping[4], _subData, _returnValues);
if (params.useDefaultMarket) {
params.market = DEFAULT_AAVE_MARKET;
}
(uint256 withdrawnAmount, bytes memory logData) = _withdraw(
params.market,
params.assetId,
params.amount,
params.to
);
emit ActionEvent("AaveV3Withdraw", logData);
return bytes32(withdrawnAmount);
}
/// @inheritdoc ActionBase
function executeActionDirect(bytes memory _callData) public payable override {
Params memory params = parseInputs(_callData);
(, bytes memory logData) = _withdraw(
params.market,
params.assetId,
params.amount,
params.to
);
logger.logActionDirectEvent("AaveV3Withdraw", logData);
}
function executeActionDirectL2() public payable {
Params memory params = decodeInputs(msg.data[4:]);
(, bytes memory logData) = _withdraw(
params.market,
params.assetId,
params.amount,
params.to
);
logger.logActionDirectEvent("AaveV3Withdraw", logData);
}
/// @inheritdoc ActionBase
function actionType() public pure virtual override returns (uint8) {
return uint8(ActionType.STANDARD_ACTION);
}
//////////////////////////// ACTION LOGIC ////////////////////////////
/// @notice User withdraws tokens from the Aave protocol
/// @param _market Address provider for specific market
/// @param _assetId The id of the token to be deposited
/// @param _amount Amount of tokens to be withdrawn -> send type(uint).max for whole amount
/// @param _to Where the withdrawn tokens will be sent
function _withdraw(
address _market,
uint16 _assetId,
uint256 _amount,
address _to
) internal returns (uint256, bytes memory) {
IPoolV3 lendingPool = getLendingPool(_market);
address tokenAddr = lendingPool.getReserveAddressById(_assetId);
uint256 tokenBefore;
// only need to remember this is _amount is max, no need to waste gas otherwise
if (_amount == type(uint256).max) {
tokenBefore = tokenAddr.getBalance(_to);
}
// withdraw underlying tokens from aave and send _to address
lendingPool.withdraw(tokenAddr, _amount, _to);
// if the input amount is max calc. what was the exact _amount
if (_amount == type(uint256).max) {
_amount = tokenAddr.getBalance(_to) - tokenBefore;
}
bytes memory logData = abi.encode(_market, tokenAddr, _amount, _to);
return (_amount, logData);
}
function parseInputs(bytes memory _callData) public pure returns (Params memory params) {
params = abi.decode(_callData, (Params));
}
function encodeInputs(Params memory params) public pure returns (bytes memory encodedInput) {
encodedInput = bytes.concat(this.executeActionDirectL2.selector);
encodedInput = bytes.concat(encodedInput, bytes2(params.assetId));
encodedInput = bytes.concat(encodedInput, boolToBytes(params.useDefaultMarket));
encodedInput = bytes.concat(encodedInput, bytes32(params.amount));
encodedInput = bytes.concat(encodedInput, bytes20(params.to));
if (!params.useDefaultMarket) {
encodedInput = bytes.concat(encodedInput, bytes20(params.market));
}
}
function decodeInputs(bytes calldata encodedInput) public pure returns (Params memory params) {
params.assetId = uint16(bytes2(encodedInput[0:2]));
params.useDefaultMarket = bytesToBool(bytes1(encodedInput[2:3]));
params.amount = uint256(bytes32(encodedInput[3:35]));
params.to = address(bytes20(encodedInput[35:55]));
if (params.useDefaultMarket) {
params.market = DEFAULT_AAVE_MARKET;
} else {
params.market = address(bytes20(encodedInput[55:75]));
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"NonContractCall","type":"error"},{"inputs":[],"name":"ReturnIndexValueError","type":"error"},{"inputs":[],"name":"SenderNotAdmin","type":"error"},{"inputs":[],"name":"SenderNotOwner","type":"error"},{"inputs":[],"name":"SubIndexValueError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"logName","type":"string"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ActionEvent","type":"event"},{"inputs":[],"name":"AAVE_REFERRAL_CODE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NO_PARAM_MAPPING","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RETURN_MAX_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RETURN_MIN_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STABLE_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUB_MAX_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUB_MIN_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VARIABLE_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actionType","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"adminVault","outputs":[{"internalType":"contract AdminVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedInput","type":"bytes"}],"name":"decodeInputs","outputs":[{"components":[{"internalType":"uint16","name":"assetId","type":"uint16"},{"internalType":"bool","name":"useDefaultMarket","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"market","type":"address"}],"internalType":"struct AaveV3Withdraw.Params","name":"params","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"assetId","type":"uint16"},{"internalType":"bool","name":"useDefaultMarket","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"market","type":"address"}],"internalType":"struct AaveV3Withdraw.Params","name":"params","type":"tuple"}],"name":"encodeInputs","outputs":[{"internalType":"bytes","name":"encodedInput","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32[]","name":"_subData","type":"bytes32[]"},{"internalType":"uint8[]","name":"_paramMapping","type":"uint8[]"},{"internalType":"bytes32[]","name":"_returnValues","type":"bytes32[]"}],"name":"executeAction","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_callData","type":"bytes"}],"name":"executeActionDirect","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"executeActionDirectL2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"logger","outputs":[{"internalType":"contract DefisaverLogger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_callData","type":"bytes"}],"name":"parseInputs","outputs":[{"components":[{"internalType":"uint16","name":"assetId","type":"uint16"},{"internalType":"bool","name":"useDefaultMarket","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"market","type":"address"}],"internalType":"struct AaveV3Withdraw.Params","name":"params","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract DFSRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawStuckFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50611ea4806100206000396000f3fe60806040526004361061015f5760003560e01c80638b835979116100c05780639864dcdd11610074578063d3c2e7ed11610059578063d3c2e7ed146103d9578063d4f922dc146103ee578063f24ccbfe1461040357600080fd5b80639864dcdd146103a4578063c579d490146103b957600080fd5b80638cedca71116100a55780638cedca71146103495780638df50f74146103715780639093410d1461038457600080fd5b80638b835979146102b05780638bcb62161461033457600080fd5b80632ba38bcb11610117578063389f87ff116100fc578063389f87ff1461023b57806341c0e1b51461024e5780637b1039991461026357600080fd5b80632ba38bcb146102035780632fa13cb81461022657600080fd5b80630f2eee42116101485780630f2eee42146101be578063247492f8146101e55780632895f3aa146101f957600080fd5b806305a363de146101645780630ec5ef8214610191575b600080fd5b34801561017057600080fd5b50610179604081565b60405161ffff90911681526020015b60405180910390f35b34801561019d57600080fd5b506101b16101ac366004611665565b61042b565b604051610188919061174c565b3480156101ca57600080fd5b506101d3608081565b60405160ff9091168152602001610188565b3480156101f157600080fd5b5060016101d3565b610201610564565b005b34801561020f57600080fd5b50610218600181565b604051908152602001610188565b34801561023257600080fd5b506101d3600081565b610201610249366004611766565b610620565b34801561025a57600080fd5b506102016106d6565b34801561026f57600080fd5b5061028b73287778f121f134c66212fb16c9b53ec991d32f5b81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610188565b3480156102bc57600080fd5b506102d06102cb366004611862565b6107c0565b6040516101889190600060a08201905061ffff835116825260208301511515602083015260408301516040830152606083015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080860151166080850152505092915050565b34801561034057600080fd5b506101d3600181565b34801561035557600080fd5b5061028b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b61021861037f366004611933565b6108da565b34801561039057600080fd5b506102d061039f366004611766565b610aeb565b3480156103b057600080fd5b506101d3607f81565b3480156103c557600080fd5b506102016103d4366004611a49565b610b28565b3480156103e557600080fd5b506101d360ff81565b3480156103fa57600080fd5b50610218600281565b34801561040f57600080fd5b5061028b73ce7a977cac4a481bc84ac06b2da0df614e621cf381565b604080517f2895f3aa0000000000000000000000000000000000000000000000000000000060208201528151600481830301815260248201909252825161047a91839160f01b90604401611a8a565b6040516020818303038152906040529050806104998360200151610cb0565b6040516020016104aa929190611ad1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252908401519092506104ee91839190602001611b18565b604051602081830303815290604052905080826060015160601b604051602001610519929190611b3a565b6040516020818303038152906040529050816020015161055f5780826080015160601b60405160200161054d929190611b3a565b60405160208183030381529060405290505b919050565b60006105766102cb3660048185611b81565b905060006105968260800151836000015184604001518560600151610ce5565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073ce7a977cac4a481bc84ac06b2da0df614e621cf3915063f4b24b55906105ea908490600401611bab565b600060405180830381600087803b15801561060457600080fd5b505af1158015610618573d6000803e3d6000fd5b505050505050565b600061062b82610aeb565b9050600061064b8260800151836000015184604001518560600151610ce5565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073ce7a977cac4a481bc84ac06b2da0df614e621cf3915063f4b24b559061069f908490600401611bab565b600060405180830381600087803b1580156106b957600080fd5b505af11580156106cd573d6000803e3d6000fd5b50505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1673ccf3d848e08b94478ed8f46ffead3008faf581fd73ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107709190611bf2565b73ffffffffffffffffffffffffffffffffffffffff16146107bd576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526107f9600260008486611b81565b61080291611c0f565b60f01c8152610848610818600360028587611b81565b61082191611c57565b7fff0000000000000000000000000000000000000000000000000000000000000016151590565b1515602082015261085d602360038486611b81565b61086691611c9d565b6040820152610879603760238486611b81565b61088291611cd9565b606090811c908201526020810151156108b457732f39d218133afab8f2b819b1066c7e434ad94e9e60808201526108d4565b6108c2604b60378486611b81565b6108cb91611cd9565b60601c60808201525b92915050565b60008061091c87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610aeb92505050565b905061094c816000015161ffff168560008151811061093d5761093d611d1f565b60200260200101518786610f2b565b61ffff168152602081015161097f90610966576000610969565b60015b60ff168560018151811061093d5761093d611d1f565b6001146020820152604081015184516109a691908690600290811061093d5761093d611d1f565b8160400181815250506109d98160600151856003815181106109ca576109ca611d1f565b60200260200101518786610fa9565b73ffffffffffffffffffffffffffffffffffffffff16606082015260808101518451610a139190869060049081106109ca576109ca611d1f565b73ffffffffffffffffffffffffffffffffffffffff166080820152602081015115610a5357732f39d218133afab8f2b819b1066c7e434ad94e9e60808201525b600080610a728360800151846000015185604001518660600151610ce5565b6040517f416176655633576974686472617700000000000000000000000000000000000081529193509150600e0160405180910390207f2b6d22f419271bcc89bbac8deec947c664365d6e24d06fef0ca7c325c704dce382604051610ad7919061174c565b60405180910390a250979650505050505050565b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825190916108d49184018101908401611d4e565b3373ffffffffffffffffffffffffffffffffffffffff1673ccf3d848e08b94478ed8f46ffead3008faf581fd73ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc29190611bf2565b73ffffffffffffffffffffffffffffffffffffffff1614610c0f576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff84161415610c8a5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610c84573d6000803e3d6000fd5b50505050565b610cab73ffffffffffffffffffffffffffffffffffffffff84168383611086565b505050565b600081610cbe5760006108d4565b7f010000000000000000000000000000000000000000000000000000000000000092915050565b600060606000610cf487611113565b6040517f5275179700000000000000000000000000000000000000000000000000000000815261ffff8816600482015290915060009073ffffffffffffffffffffffffffffffffffffffff831690635275179790602401602060405180830381865afa158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190611bf2565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610ddb57610dd873ffffffffffffffffffffffffffffffffffffffff831687611184565b90505b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820189905287811660448301528416906369328dec906064016020604051808303816000875af1158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c9190611db3565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610ed35780610ec673ffffffffffffffffffffffffffffffffffffffff841688611184565b610ed09190611dfb565b96505b506040805173ffffffffffffffffffffffffffffffffffffffff998a1660208201529189168282015260608201879052949097166080808901919091528451808903909101815260a090970190935250919492505050565b600060ff841615610f9e57610f3f8461126d565b15610f735781610f4e8561128c565b60ff1681518110610f6157610f61611d1f565b602002602001015160001c9450610f9e565b82610f7d856112d8565b60ff1681518110610f9057610f90611d1f565b602002602001015160001c94505b50835b949350505050565b600060ff841615610f9e57610fbd8461126d565b15610ff15781610fcc8561128c565b60ff1681518110610fdf57610fdf611d1f565b602002602001015160601c9450610f9e565b8360ff1660fe1415611004575030610fa1565b8360ff1660ff1415610f73573073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107f9190611bf2565b9050610fa1565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610cab908490611323565b60008173ffffffffffffffffffffffffffffffffffffffff1663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611160573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d49190611bf2565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156111d6575073ffffffffffffffffffffffffffffffffffffffff8116316108d4565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015611242573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112669190611db3565b90506108d4565b6000600160ff8316108015906108d45750607f60ff8316111592915050565b60006112978261126d565b6112cd576040517fdcc95a3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d4600183611e12565b6000608060ff83161015611318576040517f866f6e8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d4608083611e12565b6000611385826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114349092919063ffffffff16565b805190915015610cab57808060200190518101906113a39190611e35565b610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6060610fa18484600085606061144985611542565b61147f576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516114a89190611e52565b60006040518083038185875af1925050503d80600081146114e5576040519150601f19603f3d011682016040523d82523d6000602084013e6114ea565b606091505b509150915081156114fe579150610fa19050565b80511561150e5780518082602001fd5b836040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142b919061174c565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610fa1575050151592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156115cd576115cd61157b565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561161a5761161a61157b565b604052919050565b61ffff8116811461163257600080fd5b50565b801515811461163257600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461163257600080fd5b600060a0828403121561167757600080fd5b61167f6115aa565b823561168a81611622565b8152602083013561169a81611635565b60208201526040838101359082015260608301356116b781611643565b606082015260808301356116ca81611643565b60808201529392505050565b60005b838110156116f15781810151838201526020016116d9565b83811115610c845750506000910152565b6000815180845261171a8160208601602086016116d6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061175f6020830184611702565b9392505050565b6000602080838503121561177957600080fd5b823567ffffffffffffffff8082111561179157600080fd5b818501915085601f8301126117a557600080fd5b8135818111156117b7576117b761157b565b6117e7847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016115d3565b915080825286848285010111156117fd57600080fd5b8084840185840137600090820190930192909252509392505050565b60008083601f84011261182b57600080fd5b50813567ffffffffffffffff81111561184357600080fd5b60208301915083602082850101111561185b57600080fd5b9250929050565b6000806020838503121561187557600080fd5b823567ffffffffffffffff81111561188c57600080fd5b61189885828601611819565b90969095509350505050565b600067ffffffffffffffff8211156118be576118be61157b565b5060051b60200190565b600082601f8301126118d957600080fd5b813560206118ee6118e9836118a4565b6115d3565b82815260059290921b8401810191818101908684111561190d57600080fd5b8286015b848110156119285780358352918301918301611911565b509695505050505050565b60008060008060006080868803121561194b57600080fd5b853567ffffffffffffffff8082111561196357600080fd5b61196f89838a01611819565b909750955060209150878201358181111561198957600080fd5b6119958a828b016118c8565b9550506040880135818111156119aa57600080fd5b8801601f81018a136119bb57600080fd5b80356119c96118e9826118a4565b81815260059190911b8201840190848101908c8311156119e857600080fd5b928501925b82841015611a1657833560ff81168114611a075760008081fd5b825292850192908501906119ed565b96505050506060880135915080821115611a2f57600080fd5b50611a3c888289016118c8565b9150509295509295909350565b600080600060608486031215611a5e57600080fd5b8335611a6981611643565b92506020840135611a7981611643565b929592945050506040919091013590565b60008351611a9c8184602088016116d6565b7fffff000000000000000000000000000000000000000000000000000000000000939093169190920190815260020192915050565b60008351611ae38184602088016116d6565b7fff00000000000000000000000000000000000000000000000000000000000000939093169190920190815260010192915050565b60008351611b2a8184602088016116d6565b9190910191825250602001919050565b60008351611b4c8184602088016116d6565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000939093169190920190815260140192915050565b60008085851115611b9157600080fd5b83861115611b9e57600080fd5b5050820193919092039150565b60408152600e60408201527f4161766556335769746864726177000000000000000000000000000000000000606082015260806020820152600061175f6080830184611702565b600060208284031215611c0457600080fd5b815161175f81611643565b7fffff0000000000000000000000000000000000000000000000000000000000008135818116916002851015611c4f5780818660020360031b1b83161692505b505092915050565b7fff000000000000000000000000000000000000000000000000000000000000008135818116916001851015611c4f5760019490940360031b84901b1690921692915050565b803560208310156108d4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008135818116916014851015611c4f5760149490940360031b84901b1690921692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060a08284031215611d6057600080fd5b611d686115aa565b8251611d7381611622565b81526020830151611d8381611635565b6020820152604083810151908201526060830151611da081611643565b606082015260808301516116ca81611643565b600060208284031215611dc557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611e0d57611e0d611dcc565b500390565b600060ff821660ff841680821015611e2c57611e2c611dcc565b90039392505050565b600060208284031215611e4757600080fd5b815161175f81611635565b60008251611e648184602087016116d6565b919091019291505056fea26469706673582212204c2a1104ca08ac582af5b5b9d79e877dbf46517e23d8f30f86a6aa02ab99f93064736f6c634300080a0033
Deployed Bytecode
0x60806040526004361061015f5760003560e01c80638b835979116100c05780639864dcdd11610074578063d3c2e7ed11610059578063d3c2e7ed146103d9578063d4f922dc146103ee578063f24ccbfe1461040357600080fd5b80639864dcdd146103a4578063c579d490146103b957600080fd5b80638cedca71116100a55780638cedca71146103495780638df50f74146103715780639093410d1461038457600080fd5b80638b835979146102b05780638bcb62161461033457600080fd5b80632ba38bcb11610117578063389f87ff116100fc578063389f87ff1461023b57806341c0e1b51461024e5780637b1039991461026357600080fd5b80632ba38bcb146102035780632fa13cb81461022657600080fd5b80630f2eee42116101485780630f2eee42146101be578063247492f8146101e55780632895f3aa146101f957600080fd5b806305a363de146101645780630ec5ef8214610191575b600080fd5b34801561017057600080fd5b50610179604081565b60405161ffff90911681526020015b60405180910390f35b34801561019d57600080fd5b506101b16101ac366004611665565b61042b565b604051610188919061174c565b3480156101ca57600080fd5b506101d3608081565b60405160ff9091168152602001610188565b3480156101f157600080fd5b5060016101d3565b610201610564565b005b34801561020f57600080fd5b50610218600181565b604051908152602001610188565b34801561023257600080fd5b506101d3600081565b610201610249366004611766565b610620565b34801561025a57600080fd5b506102016106d6565b34801561026f57600080fd5b5061028b73287778f121f134c66212fb16c9b53ec991d32f5b81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610188565b3480156102bc57600080fd5b506102d06102cb366004611862565b6107c0565b6040516101889190600060a08201905061ffff835116825260208301511515602083015260408301516040830152606083015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080860151166080850152505092915050565b34801561034057600080fd5b506101d3600181565b34801561035557600080fd5b5061028b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b61021861037f366004611933565b6108da565b34801561039057600080fd5b506102d061039f366004611766565b610aeb565b3480156103b057600080fd5b506101d3607f81565b3480156103c557600080fd5b506102016103d4366004611a49565b610b28565b3480156103e557600080fd5b506101d360ff81565b3480156103fa57600080fd5b50610218600281565b34801561040f57600080fd5b5061028b73ce7a977cac4a481bc84ac06b2da0df614e621cf381565b604080517f2895f3aa0000000000000000000000000000000000000000000000000000000060208201528151600481830301815260248201909252825161047a91839160f01b90604401611a8a565b6040516020818303038152906040529050806104998360200151610cb0565b6040516020016104aa929190611ad1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252908401519092506104ee91839190602001611b18565b604051602081830303815290604052905080826060015160601b604051602001610519929190611b3a565b6040516020818303038152906040529050816020015161055f5780826080015160601b60405160200161054d929190611b3a565b60405160208183030381529060405290505b919050565b60006105766102cb3660048185611b81565b905060006105968260800151836000015184604001518560600151610ce5565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073ce7a977cac4a481bc84ac06b2da0df614e621cf3915063f4b24b55906105ea908490600401611bab565b600060405180830381600087803b15801561060457600080fd5b505af1158015610618573d6000803e3d6000fd5b505050505050565b600061062b82610aeb565b9050600061064b8260800151836000015184604001518560600151610ce5565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073ce7a977cac4a481bc84ac06b2da0df614e621cf3915063f4b24b559061069f908490600401611bab565b600060405180830381600087803b1580156106b957600080fd5b505af11580156106cd573d6000803e3d6000fd5b50505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1673ccf3d848e08b94478ed8f46ffead3008faf581fd73ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107709190611bf2565b73ffffffffffffffffffffffffffffffffffffffff16146107bd576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526107f9600260008486611b81565b61080291611c0f565b60f01c8152610848610818600360028587611b81565b61082191611c57565b7fff0000000000000000000000000000000000000000000000000000000000000016151590565b1515602082015261085d602360038486611b81565b61086691611c9d565b6040820152610879603760238486611b81565b61088291611cd9565b606090811c908201526020810151156108b457732f39d218133afab8f2b819b1066c7e434ad94e9e60808201526108d4565b6108c2604b60378486611b81565b6108cb91611cd9565b60601c60808201525b92915050565b60008061091c87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610aeb92505050565b905061094c816000015161ffff168560008151811061093d5761093d611d1f565b60200260200101518786610f2b565b61ffff168152602081015161097f90610966576000610969565b60015b60ff168560018151811061093d5761093d611d1f565b6001146020820152604081015184516109a691908690600290811061093d5761093d611d1f565b8160400181815250506109d98160600151856003815181106109ca576109ca611d1f565b60200260200101518786610fa9565b73ffffffffffffffffffffffffffffffffffffffff16606082015260808101518451610a139190869060049081106109ca576109ca611d1f565b73ffffffffffffffffffffffffffffffffffffffff166080820152602081015115610a5357732f39d218133afab8f2b819b1066c7e434ad94e9e60808201525b600080610a728360800151846000015185604001518660600151610ce5565b6040517f416176655633576974686472617700000000000000000000000000000000000081529193509150600e0160405180910390207f2b6d22f419271bcc89bbac8deec947c664365d6e24d06fef0ca7c325c704dce382604051610ad7919061174c565b60405180910390a250979650505050505050565b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825190916108d49184018101908401611d4e565b3373ffffffffffffffffffffffffffffffffffffffff1673ccf3d848e08b94478ed8f46ffead3008faf581fd73ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc29190611bf2565b73ffffffffffffffffffffffffffffffffffffffff1614610c0f576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff84161415610c8a5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610c84573d6000803e3d6000fd5b50505050565b610cab73ffffffffffffffffffffffffffffffffffffffff84168383611086565b505050565b600081610cbe5760006108d4565b7f010000000000000000000000000000000000000000000000000000000000000092915050565b600060606000610cf487611113565b6040517f5275179700000000000000000000000000000000000000000000000000000000815261ffff8816600482015290915060009073ffffffffffffffffffffffffffffffffffffffff831690635275179790602401602060405180830381865afa158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190611bf2565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610ddb57610dd873ffffffffffffffffffffffffffffffffffffffff831687611184565b90505b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820189905287811660448301528416906369328dec906064016020604051808303816000875af1158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c9190611db3565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610ed35780610ec673ffffffffffffffffffffffffffffffffffffffff841688611184565b610ed09190611dfb565b96505b506040805173ffffffffffffffffffffffffffffffffffffffff998a1660208201529189168282015260608201879052949097166080808901919091528451808903909101815260a090970190935250919492505050565b600060ff841615610f9e57610f3f8461126d565b15610f735781610f4e8561128c565b60ff1681518110610f6157610f61611d1f565b602002602001015160001c9450610f9e565b82610f7d856112d8565b60ff1681518110610f9057610f90611d1f565b602002602001015160001c94505b50835b949350505050565b600060ff841615610f9e57610fbd8461126d565b15610ff15781610fcc8561128c565b60ff1681518110610fdf57610fdf611d1f565b602002602001015160601c9450610f9e565b8360ff1660fe1415611004575030610fa1565b8360ff1660ff1415610f73573073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107f9190611bf2565b9050610fa1565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610cab908490611323565b60008173ffffffffffffffffffffffffffffffffffffffff1663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611160573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d49190611bf2565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156111d6575073ffffffffffffffffffffffffffffffffffffffff8116316108d4565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015611242573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112669190611db3565b90506108d4565b6000600160ff8316108015906108d45750607f60ff8316111592915050565b60006112978261126d565b6112cd576040517fdcc95a3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d4600183611e12565b6000608060ff83161015611318576040517f866f6e8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d4608083611e12565b6000611385826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114349092919063ffffffff16565b805190915015610cab57808060200190518101906113a39190611e35565b610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6060610fa18484600085606061144985611542565b61147f576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516114a89190611e52565b60006040518083038185875af1925050503d80600081146114e5576040519150601f19603f3d011682016040523d82523d6000602084013e6114ea565b606091505b509150915081156114fe579150610fa19050565b80511561150e5780518082602001fd5b836040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142b919061174c565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610fa1575050151592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156115cd576115cd61157b565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561161a5761161a61157b565b604052919050565b61ffff8116811461163257600080fd5b50565b801515811461163257600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461163257600080fd5b600060a0828403121561167757600080fd5b61167f6115aa565b823561168a81611622565b8152602083013561169a81611635565b60208201526040838101359082015260608301356116b781611643565b606082015260808301356116ca81611643565b60808201529392505050565b60005b838110156116f15781810151838201526020016116d9565b83811115610c845750506000910152565b6000815180845261171a8160208601602086016116d6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061175f6020830184611702565b9392505050565b6000602080838503121561177957600080fd5b823567ffffffffffffffff8082111561179157600080fd5b818501915085601f8301126117a557600080fd5b8135818111156117b7576117b761157b565b6117e7847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016115d3565b915080825286848285010111156117fd57600080fd5b8084840185840137600090820190930192909252509392505050565b60008083601f84011261182b57600080fd5b50813567ffffffffffffffff81111561184357600080fd5b60208301915083602082850101111561185b57600080fd5b9250929050565b6000806020838503121561187557600080fd5b823567ffffffffffffffff81111561188c57600080fd5b61189885828601611819565b90969095509350505050565b600067ffffffffffffffff8211156118be576118be61157b565b5060051b60200190565b600082601f8301126118d957600080fd5b813560206118ee6118e9836118a4565b6115d3565b82815260059290921b8401810191818101908684111561190d57600080fd5b8286015b848110156119285780358352918301918301611911565b509695505050505050565b60008060008060006080868803121561194b57600080fd5b853567ffffffffffffffff8082111561196357600080fd5b61196f89838a01611819565b909750955060209150878201358181111561198957600080fd5b6119958a828b016118c8565b9550506040880135818111156119aa57600080fd5b8801601f81018a136119bb57600080fd5b80356119c96118e9826118a4565b81815260059190911b8201840190848101908c8311156119e857600080fd5b928501925b82841015611a1657833560ff81168114611a075760008081fd5b825292850192908501906119ed565b96505050506060880135915080821115611a2f57600080fd5b50611a3c888289016118c8565b9150509295509295909350565b600080600060608486031215611a5e57600080fd5b8335611a6981611643565b92506020840135611a7981611643565b929592945050506040919091013590565b60008351611a9c8184602088016116d6565b7fffff000000000000000000000000000000000000000000000000000000000000939093169190920190815260020192915050565b60008351611ae38184602088016116d6565b7fff00000000000000000000000000000000000000000000000000000000000000939093169190920190815260010192915050565b60008351611b2a8184602088016116d6565b9190910191825250602001919050565b60008351611b4c8184602088016116d6565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000939093169190920190815260140192915050565b60008085851115611b9157600080fd5b83861115611b9e57600080fd5b5050820193919092039150565b60408152600e60408201527f4161766556335769746864726177000000000000000000000000000000000000606082015260806020820152600061175f6080830184611702565b600060208284031215611c0457600080fd5b815161175f81611643565b7fffff0000000000000000000000000000000000000000000000000000000000008135818116916002851015611c4f5780818660020360031b1b83161692505b505092915050565b7fff000000000000000000000000000000000000000000000000000000000000008135818116916001851015611c4f5760019490940360031b84901b1690921692915050565b803560208310156108d4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008135818116916014851015611c4f5760149490940360031b84901b1690921692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060a08284031215611d6057600080fd5b611d686115aa565b8251611d7381611622565b81526020830151611d8381611635565b6020820152604083810151908201526060830151611da081611643565b606082015260808301516116ca81611643565b600060208284031215611dc557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611e0d57611e0d611dcc565b500390565b600060ff821660ff841680821015611e2c57611e2c611dcc565b90039392505050565b600060208284031215611e4757600080fd5b815161175f81611635565b60008251611e648184602087016116d6565b919091019291505056fea26469706673582212204c2a1104ca08ac582af5b5b9d79e877dbf46517e23d8f30f86a6aa02ab99f93064736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.